Вычисление строковых выражений требует перераспределения памяти, а это компилятор делает только с выражениями типа string. Поэтому результат выражения, приведенного в третьем варианте, также имеет тип string
PChar
. Память для хранения результата выражения выделяется динамически, как и для обычных переменных типа string. Чтобы передать указатель на но выражение в функцию, следует привести его к PChar
. В эпилог процедуры, вызывающей функцию SetWindowText
или иную функцию с подобным аргументом, добавляется код, который освобождает динамически сформированную строку, поэтому утечек памяти не происходит. Разумеется, существуют и другие способы формирования параметра типа LPCTSTR
, кроме предложенных здесь. Можно, например, выделить память для нуль-терминированной строки с помощью StrNew
или родственной ей функции из модуля SysUtils
. Можно использовать массив типа Char
. Можно выделять память какими-либо другими способами. Но предложенные здесь три варианта в большинстве случаев наиболее удобны.Параметры типа LPTSTR
Таким образом, перед программой встает задача узнать, какой объем памяти следует выделить под возвращаемую строку. Здесь API не предлагает универсального решения, разные функции по-разному решают эту проблему. Например, при получении заголовка окна с помощью GetWindowText
GetWindowTextLength
. Функции типа GetCurrentDirectory
возвращают длину строки. Если при первом вызове этой функции памяти выделено недостаточно, можно увеличить буфер и вызвать функцию еще раз. И наконец, есть функции типа SHGetSpecialFolderPath
, в описании которых написано, каков минимальный размер буфера, необходимый для гарантированной передачи полной строки этой функцией (это, разумеется, возможно только в том случае, когда размер возвращаемой строки имеет какое-то естественное ограничение). Следует также отметить, что большинство API-функций, возвращающих строки, в качестве одного из параметров принимают размер буфера, чтобы не скопировать больше байтов, чем буфер может принять.Выделять буфер для получения строки можно многими способами. На практике удобнее всего статические массивы, тип string
Статические массивы могут использоваться, если размер буфера известен на этапе компиляции. Массивы типа Char
Строки типа string
SetLength
, а затем передать указатель на начало строки в функцию API. Здесь следует соблюдать осторожность: если длина строки окажется равной нулю, переменная типа string
будет иметь значение nil
, а система попытается записать по этому указателю пустую строку, состоящую из единственного символа #0
. Это приведет к ошибке Access violation.Третий способ — выделение памяти для буфера с помощью StrAlloc
StrDispose
. При этом крайне желательно использовать конструкцию try/finally
, чтобы возникновение исключений не привело к утечкам памяти.Все три способа получения строковых данных от функций Windows API показаны в примере EnumWnd
1.2. Примеры использования Windows API