Читаем О чём не пишут в книгах по Delphi полностью

Вычисление строковых выражений требует перераспределения памяти, а это компилятор делает только с выражениями типа string. Поэтому результат выражения, приведенного в третьем варианте, также имеет тип string. Но его можно привести к PChar. Память для хранения результата выражения выделяется динамически, как и для обычных переменных типа string. Чтобы передать указатель на но выражение в функцию, следует привести его к PChar. В эпилог процедуры, вызывающей функцию SetWindowText или иную функцию с подобным аргументом, добавляется код, который освобождает динамически сформированную строку, поэтому утечек памяти не происходит. Разумеется, существуют и другие способы формирования параметра типа LPCTSTR, кроме предложенных здесь. Можно, например, выделить память для нуль-терминированной строки с помощью StrNew или родственной ей функции из модуля SysUtils. Можно использовать массив типа Char. Можно выделять память какими-либо другими способами. Но предложенные здесь три варианта в большинстве случаев наиболее удобны.

Параметры типа LPTSTR применяются в тех случаях, когда функция может не только читать, но и модифицировать передаваемое ей значение. В большинстве случаев такие параметры чисто выходные, т. е. функция не интересуется, какое значение имел параметр при вызове, используя его только для возврата значения. При возврате строкового значения всегда возникает проблема: где, кем и как будет выделена память, в которую будет записана строка? Функции Windows API, за очень редким исключением, решают эту проблему следующим образом: память должна выделить вызывающая программа, а в функцию передается указатель на этот заранее выделенный блок. Сама функция только копирует строку в этот блок.

Таким образом, перед программой встает задача узнать, какой объем памяти следует выделить под возвращаемую строку. Здесь API не предлагает универсального решения, разные функции по-разному решают эту проблему. Например, при получении заголовка окна с помощью GetWindowText размер этого заголовка можно узнать, вызвав предварительно GetWindowTextLength. Функции типа GetCurrentDirectory возвращают длину строки. Если при первом вызове этой функции памяти выделено недостаточно, можно увеличить буфер и вызвать функцию еще раз. И наконец, есть функции типа SHGetSpecialFolderPath, в описании которых написано, каков минимальный размер буфера, необходимый для гарантированной передачи полной строки этой функцией (это, разумеется, возможно только в том случае, когда размер возвращаемой строки имеет какое-то естественное ограничение). Следует также отметить, что большинство API-функций, возвращающих строки, в качестве одного из параметров принимают размер буфера, чтобы не скопировать больше байтов, чем буфер может принять.

Выделять буфер для получения строки можно многими способами. На практике удобнее всего статические массивы, тип string или динамическое выделение памяти для нуль-терминированных строк.

Статические массивы могут использоваться, если размер буфера известен на этапе компиляции. Массивы типа Char с начальным индексом 0 рассматриваются компилятором как нуль-терминированные строки, поэтому с ними удобно выполнять дальнейшие операции. Этот способ удобен тем, что не нужно заботиться о выделении и освобождении памяти, поэтому он часто применяется там, где формально длина строки на этапе неизвестна, но "исходя из здравого смысла" можно сделать вывод, что в подавляющем большинстве случаев эта длина не превысит некоторой величины, которая и берется в качестве размера массива.

Строки типа string также могут служить буфером для получения строковых значений от системы. Для этого нужно предварительно установить требуемую длину строки с помощью SetLength, а затем передать указатель на начало строки в функцию API. Здесь следует соблюдать осторожность: если длина строки окажется равной нулю, переменная типа string будет иметь значение nil, а система попытается записать по этому указателю пустую строку, состоящую из единственного символа #0. Это приведет к ошибке Access violation.

Третий способ — выделение памяти для буфера с помощью StrAlloc или аналогичной ей функции. Память, выделенную таким образом, следует обязательно освобождать с помощью StrDispose. При этом крайне желательно использовать конструкцию try/finally, чтобы возникновение исключений не привело к утечкам памяти.

Все три способа получения строковых данных от функций Windows API показаны в примере EnumWnd, находящемся на прилагаемом компакт-диске.

<p>1.2. Примеры использования Windows API</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных