Глава 4. Стандартные диалоговые окна
К стандартным диалоговым окнам (иногда
они также называются диалоговые окна
общего назначения) относятся знакомые
всем окна выбора цвета, выбора шрифта,
открытия и сохранения файла и другие. Для
создания каждого из таких окон
предназначена одна из функций Windows API,
однако их достаточно сложно использовать
из-за большого количества подводных камней.
Далее в этой главе будут приведены
подробные примеры создания таких окон и
подробно описан весь процесс.
Все функции, переменные, записи для
работы со стандартными диалоговыми окнами
расположены в одном модуле, который
называется commdlg. Поэтому вы должны
подключить этот модуль, если собираетесь
использовать окна типа «Open File». Порядок
работы со стандартными диалогами следующий:
- инициализация соответствующей записи:
установка нужных флагов, начальных
значений;
- вызов соответствующей функции с данной
записью в качестве параметра;
- анализ результата, возвращенного
функцией
Диалоговое окно «Open File»
В Windows 2000 обычное окно открытия
файла выглядит так:
Создается оно при помощи функции GetOpenFileName,
а принимает она единственный параметр –
запись типа TOpenFilename. Вот заголовок
функции и параметры этой записи, а также их
описание.
tagOFNA = packed record
lStructSize: DWORD;
hWndOwner: HWND;
hInstance: HINST;
lpstrFilter: PChar;
lpstrCustomFilter: PChar;
nMaxCustFilter: DWORD;
nFilterIndex: DWORD;
lpstrFile: PChar;
nMaxFile: DWORD;
lpstrFileTitle: PChar;
nMaxFileTitle: DWORD;
lpstrInitialDir: PChar;
lpstrTitle: PChar;
Flags: DWORD;
nFileOffset: Word;
nFileExtension: Word;
lpstrDefExt: PChar;
lCustData: LPARAM;
lpfnHook: function(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
lpTemplateName: PChar;
pvReserved: Pointer;
dwReserved: DWORD;
FlagsEx: DWORD;
end;
TOpenFilenameA = tagOFNA;
TOpenFilename = TOpenFilenameA;
function GetOpenFileName(var OpenFile: TOpenFilename): Bool; stdcall;
|
- lStructSize
- Если приложение предназначено для
работы в Windows95/98/NT то это поле должно быть
равно 76. Если приложение
предназначено для Windows 2000, то sizeof(TOPENFILENAME);
- hwndOwner
- описатель окна, которое будет
владельцем данного диалога, может быть
нулем, если владельца не будет;
- hInstance
- определяет различные параметры при
изменении внешнего вида диалога, за
подробностями обращайтесь в справку по
winapi;
- lpstrFilter
- указатель на буфер, содержащий строку с
фильтром, содержимое данного поля
используется для построения выпадающего
списка «Files of type » (см. рисунок выше).
Буфер представляет собой пары описание_фильтра,
фильтр, каждый элемент пары – строка с
завершающим нулем, в конце всех фильтров
стоит два символа с кодом нуль. описание_фильтра
– это строка типа «Text files», фильтр – «*.txt;*.text;*.asc».
Подробности ниже в примере.
- lpstrCustomFilter
- указатель на буфер в котором находится
фильтр, используемый как стартовый, но
только в том случае, когда поле nFilterIndex
равно нулю;
- nMaxCustFilter
- размер буфера для поля lpstrCustomFilter,
должен быть не меньше 40;
- nFilterIndex
- в этом поле номер фильтра, выбранный
изначально. Номер соответствует номеру
пары из поля lpstrFilter, нумерация
начинается с единицы. Если нуль, то
используется фильтр из поля lpstrCustomFilter;
- lpstrFile
- указатель на буфер, содержащий имя
файла использующееся для инициализации
диалога. Если пользователь выбрал какой-нибудь
файл, то в буфере сохраняется полное имя
этого файла. Если размер буфера
недостаточен, то функция возвращает false,
а вызов функции CommDlgExtendedError
возвращает FNERR_BUFFERTOOSMALL;
- nMaxFile
- размер буфера, заданного в предыдущем
параметре, должен быть не меньше 256;
- lpstrFileTitle
- указатель на буфер, который принимает
только имя файла с расширением (без пути),
может быть nil, тогда ничего не
возвращается;
- nMaxFileTitle
- определяет размер буфера, заданного ы
предыдущем параметре. Игнорируется, если lpstrFileTitle
равен nil;
- lpstrInitialDir
- строка, определяющая начальный каталог.
Если это поле равно nil, то поведение
диалога зависит от версии операционной
системы, подробности в справке по WinApi;
- lpstrTitle
- строка с заголовком диалога, если поле
равно nil, то используется заголовок по
умолчанию (Save As, например);
- Flags
- набор флагов, использующихся для
инициализации диалога. После закрытия
диалога здесь будут содержаться флаги,
описывающие действия пользователя. Набор
флагов очень большой, поэтому я опишу
лишь самые важные.
- OFN_EXPLORER
- создается именно такое окно, как
показано на рисунке выше, т.е. «современного»
вида. В MSDN написано, что даже если не
указывать этот флаг, все равно диалог
будет отображаться в современном виде,
однако у меня отсутствие этого флага
приводит к тому, что диалоговое окно
отображается так как в Win3.1;
- OFN_CREATEPROMPT
- вызывает появления запроса на
создание файла, если файла, выбранного
пользователем не существует;
- OFN_FILEMUSTEXIST
- определяет, что пользователь может
выбрать только существующие файлы;
- OFN_HIDEREADONLY
- скрывает флажок с надписью «Read only»
- OFN_NODEREFERENCELINKS
- если этот флаг установлен, то при
выборе файла ярлыка windows (с расширением
.LNK), будет возвращено имя этого файла.
Если флаг не установлен, то будет
возвращено имя файла, на который
ссылается ярлык;
- OFN_OVERWRITEPROMPT
- показать запрос на подтверждение
перезаписи выбранного файла, если он
уже существует, используется в диалоге
«Save as»;
- OFN_PATHMUSTEXIST
- если этот флаг установлен, то
пользователь может вводить только
корректные имена файлов и каталогов;
- OFN_READONLY
- если этот флаг установлен перед
вызовом функции, флажок «Read only»
помечается включенным. Если этот флаг
присутствует после вызова функции,
значит пользователь включил флажок «Read
only»;
- OFN_SHOWHELP
- если этот флаг определён, то в диалоге
появляется кнопка Help, при нажатии
на которую посылается сообщение HELPMSGSTRING
окну, описатель которого занесён в поле
hwndOwner. Чтобы получить численное
значение сообщения, вы должны вызвать
функцию RegisterWindowMessage(HELPMSGSTRING);
- OFN_ALLOWMULTISELECT
- если этот флаг определён,
пользователь может выбрать несколько
файлов. В этом случае имена файлов
возвращаются в буфере из поля lpstrFile
таким образом: сначала идет имя
каталога, затем символ с кодом нуль,
затем список имен выбранных файлов,
также разделённых нулевым символом.
- nFileOffset
- определяет позицию (отсчет ведется с
нуля), с которой начинается имя файла с
расшрением, в буфере из поля lpstrFile.
Например, для строки 'c:\dir1\dir2\file.ext', это
поле будет иметь значение 13 – номер
позиции, с которой начинается имя файла 'file.ext';
- nFileExtension
- определяет позицию (отсчет ведется с
нуля), с которой начинается расширение
выбранного пользователем файла. Если
пользователь не указал расширения и поле lpstrDefExt
есть nil, то позиция определяет
завершающий нулевой символ. Если
пользователь не указал расширение, но
поставил точку в конце имени файла, то
позиция равна нулю;
- lpstrDefExt
- определяет строку с расширением по
умолчанию, которое добавляется, если
пользователь не указал расширения.
Строка может быть любой длины, но
добавляются только первые три символа.
Строка не может содержать символа «точка»
(.);
- lCustData
- некоторые данные, которые передаются
диалогу при создании;
- lpfnHook
- указатель на hook-функцию, которая
управляет диалогом. Используется, когда
вы хотите добавить в диалого
дополнительные элементы управления,
например;
- lpTemplateName
- определяет идентификатор ресурса
диалога для изменения внешнего вида
диалога;
- pvReserved
- зарезервировано
- dwReserved
- зарезервировано
- FlagsEx
- Только для Windows 2000/XP. Может содержать
константу OFN_EX_NOPLACESBAR, которая прячет
полосу в левой части окна с пиктограммами
рабочего стола и т.п.
Нужно отметить, что вышеописанная
запись используется ещё и в функции GetSaveFileName
и разница между этими функциями небольшая
– фактически только в надписи на кнопке «Open»
или «Save», поэтому пример только для функции GetOpenfileName.
Как сделать
Для начала следует определить все
константы и глобальные переменные, которые
будут использоваться.
Во-первых, константа с файловым
фильтром. В данном примере определяется
константа с двумя фильтрами: Text files (*.txt)'#0'*.txt'
и All files'#0'*.*'. Разделяются фильтры
символом с кодом нуль (#0), завершается
строка двумя нулевыми символами. Каждый
фильтр состоит из текста фильтра, затем
нулевой символ, затем сам фильтр – файловая
маска.
const
szFileFilter: string = 'Text files (*.txt)'#0'*.txt'#0'All files'#0'*.*'#0#0;
|
Определяем глобальные переменные,
в основном буферы для хранения строк.
var
lpCustFilter: array[0..255] of char = '';
nFilterIndex: DWORD = 0;
szFile: array[0..2048] of char = '';
szFileTitle: array[0..255] of char;
szCurrentDir: array[0..1024] of char = '';
|
Теперь пишем код для вызова
функции GetOpenFileName. В данном случае код
находится внутри оконной функции – это
реакция на нажатие кнопки.
var
...
ofn: TOPENFILENAME;
s: string;
cf: PChar;
errcode: DWORD;
...
ofn.lStructSize := sizeof(TOPENFILENAME);
ofn.hWndOwner := wnd;
ofn.hInstance := hInstance;
ofn.lpstrFilter := @szFileFilter[1]; //преобразуем тип string к типу PChar
ofn.lpstrCustomFilter := lpCustFilter;
ofn.nMaxCustFilter := sizeof(lpCustFilter);
ofn.nFilterIndex := nFilterIndex;
ofn.lpstrFile := szFile;
ofn.nMaxFile := sizeof(szFile);
ofn.nFilterIndex := 0;
ofn.lpstrFileTitle := szFileTitle;
ofn.nMaxFileTitle := sizeof(szFileTitle);
ofn.lpstrInitialDir := szCurrentDir; // Глобальная переменная, где хранится адрес текущего каталога.
Текущий каталог для ЭТОЙ функции, не для программы!
ofn.lpstrTitle := 'Заголовок диалога Open file';
ofn.Flags := OFN_EXPLORER or OFN_ALLOWMULTISELECT or
OFN_ENABLESIZING or OFN_SHOWHELP or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST;
ofn.lpstrDefExt := 'txt';
ofn.lpfnHook := nil;
ofn.lpTemplateName := nil;
ofn.lCustData := 0;
if GetOpenFileName(ofn) then begin
//т.е. пользователь выбрал файл(ы) и нажал OK
nFilterIndex := ofn.nFilterIndex; // Запоминаем номер текущего фильтра
if length(ofn.lpstrFile) < ofn.nFileOffset then begin
// т.е. пользователь открыл несколько файлов
cf := szFile;
inc(cf, ofn.nFileOffset);
s := 'Вы выбрали НЕСКОЛЬКО файлов в каталоге'#13#10;
s := s + szFile + ''#13#10;
repeat
s := s + cf + #13#10;
inc(cf, length(cf)+1);
until length(cf)=0;
end else begin
// Т.е. пользователь открыл всего один файл
s := 'Вы выбрали всего ОДИН файл: ' + szFile;
end;
end else begin
//либо пользователь нажал Cancel, либо произошла какая-то ошибка
errcode := CommDlgExtendedError;
case errcode of
0: s := 'Вы нажали CANCEL';
else
s := 'Ошибка с кодом ' + IntToStr(errcode);
end;
end;
say(wnd, s);
|
Используемая в примере функция CommDlgExtendedError
возвращает код ошибки от выполнения самого
последнего вызова функции из модуля commdlg.
Весь код программы вы можете
скачать здесь.
Диалоговое окно «Save File»
Диалоговое окно «Save As», вызывается
абсолютно точно так же, как и окно «Open
File», только вместо GetOpenFileName
вызывается GetSaveFileName. Ещё нужно добавить
в список флагов флаг OFN_OVERWRITEPROMPT для того,
чтобы появлялся запрос на перезапись
существующего файла.
Диалоговое окно «Color»
Стандартное диалоговое окно
выбора цвета обычно выглядит так:
Для его создания использутся
функция ChooseColor и запись TChooseColor. Вот
заголовок функции и все поля записи, а также
их описание.
function ChooseColor(var CC: TChooseColor): Bool; stdcall;
ChooseColor = packed record
lStructSize: DWORD;
hWndOwner: HWND;
hInstance: HWND;
rgbResult: COLORREF;
lpCustColors: ^COLORREF;
Flags: DWORD;
lCustData: LPARAM;
lpfnHook: function(Wnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
lpTemplateName: PAnsiChar;
end;
|
- lStructSize
- размер данного типа, должен быть равен sizeof(TCHOOSECOLOR);
- hwndOwner
- описатель родительского окна для
данного диалога, если это поле равно нулю,
то диалог не имеет родителя и
отображается на панели задач;
- rgbResult
- если установлен флаг CC_RGBINIT, то это
поле определяет начальный цвет,
выбранный в диалоге, точнее ближайший из
доступных в системе. Если флаг не
установлен, то начальный цвет – черный.
Если пользователь щелкнул по кнопке ОК,
то это поле после завершения работы
диалога содержит выбранный цвет. Цвет в
формате RGB.
- lpCustColors
- указатель на массив из 16 значений типа COLORREF,
которые содержат цветовые значения в
поле Custom colors (см. рисунок выше);
- Flags
- набор флагов для инициализации диалога
и получения информации, когда он
завершается. Должен быть комбинацией
следующих констант, соединённых
оператором or:
- CC_FULLOPEN
- окно появляется изначально с
возможностью выбоа любого цвета и не
надо нажимать кнопку «Define custom colors»;
- CC_PREVENTFULLOPEN
- кнопка «Define Custom Colors » недоступна;
- CC_RGBINIT
- если этот флаг определён, то диалог
использует значение из поля rgbResult
для задания текущего (выбранного) цвета;
- CC_SHOWHELP
- если этот флаг определен, то на
диалоге появляется кнопка «Help»;
- CC_SOLIDCOLOR
- если этот флаг определён, то в поле
всех цветов отображаются только
сплошные, но не смешанные цвета.
- lCustData
- некоторое число, которое передается в
оконную процедуру диалога. Задается, если
вы используете hook-функцию для этого
диалога;
Как сделать
Для начала определим глобальные
переменные, чтобы информация, полученная в
какой-нибудь момент, была доступна позже.
var
custColors: array[0..15] of COLORREF; // массив с преопределенными цветами
crCurColor: COLORREF = $FFFFFF; // Белый цвет - начальный
|
А вот сам код, создающий этот
диалог.
var
cc: TChooseColor;
hbrMain: HBRUSH;
...
cc.lStructSize := sizeof(TCHOOSECOLOR);
cc.hWndOwner := wnd;
cc.Flags := CC_RGBINIT;
cc.lpCustColors := @custcolors[0];
cc.rgbResult := crCurColor;
if ChooseColor(cc) then begin
// т.е. пользователь нажал но ОК
// создаем кисть выбранного цвета
hbrMain := CreateSolidBrush(cc.rgbResult);
// меняем цвет кисть фона окна на нашу
SetClassLong(wnd, GCL_HBRBACKGROUND,hbrMain);
// перерисовываем окно
InvalidateRect(wnd, nil, true);
end;
|
Демонстрационную программу можете
скачать отсюда.
Программа представляет собой окно с
кнопкой, при нажатии на кнопку появляется
окно выбора цвета, затем выбранным цветом
закрашивается вся клиентская часть окна.
Диалоговое окно «Font»
Стандартное диалоговое окно
выбора шрифта выглядит так:
Для его создания используется
функция ChooseFont и запись TChooseFont.
function ChooseFont(var ChooseFont: TChooseFont): Bool; stdcall;
TChooseFont = packed record
lStructSize: DWORD;
hWndOwner: HWND;
hDC: HDC;
lpLogFont: PLogFontW;
iPointSize: Integer;
Flags: DWORD;
rgbColors: COLORREF;
lCustData: LPARAM;
lpfnHook: function(Wnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
lpTemplateName: PWideChar;
hInstance: HINST;
lpszStyle: PWideChar;
nFontType: Word;
wReserved: Word;
nSizeMin: Integer;
nSizeMax: Integer;
end;
|
- lStructSize
- размер данной записи, нужно
использовать sizeof(TChooseFont);
- hwndOwner
- описатель владельца данного диалога,
может быть нулем, если владельца быть не
должно;
- hDC
- описатель графического контекста
принтера, шрифты которого нужно включить
в список. Это поле используется только
если установлены флаги CF_PRINTERFONTS или CF_BOTH;
- lpLogFont
- указатель на запись типа TLogFont. Если
установлен флаг CF_INITTOLOGFONTSTRUCT, то
данные из этого поля используются для
инициализации диалога. Если пользователь
нажал на ОК в диалоге, то в это поле
помещается результат о выбранном шрифте;
- iPointSize
- определяет размер выбранного шрифта (в
1/10 пункта). После закрытия диалога
содержит размер шрифта, выбранного
пользователем;
- Flags
- набор битовых флагов для установки
параметров диалогового окна. Вот
некоторое из них:
- CF_APPLY
- на диалоге появляется кнопка «Apply»,
для обработки нажатия на эту кнопку
нужно использовать hook-функцию для
этого диалога;
- CF_BOTH
- этот флаг является комбинацией флагов
CF_SCREENFONTS и CF_PRINTERFONTS, в диалоге
отображаются как экранные, так и
принтерные шрифты. Принтер
определяется своим контекстом,
переданным в поле hDC
- CF_TTONLY
- определяет, что в диалоге будут
показаны только шрифты TrueType;
- CF_EFFECTS
- этот флаг позволяет устанавливать в
диалоге такие параметры шрифта как
цвет, подчеркивание, зачеркивание, вы
можете использовать поле rgbColors для
задания начального цвета шрифта;
- CF_FIXEDPITCHONLY
- если этот флаг установлен, то
отображаются только моноширинные
шрифты;
- CF_FORCEFONTEXIST
- не позволяет пользователю выбрать
некорректные или несуществующие
шрифты;
- CF_INITTOLOGFONTSTRUCT
- определяет, что нужно использовать
поле pLogFont для инициализации
диалога;
- CF_LIMITSIZE
- определяет, что отображаются шрифты с
размером только из диапазона,
определяемого полями nSizeMin и nSizeMax;
- CF_NOFACESEL
- если установлен этот флаг, то поле
выбора имени шрифта не
инициализируется;
- CF_NOSCRIPTSEL
- этот флаг делает недоступным
выпадающий список «Script» в диалоге,
возвращаемый тип набора символов равен
DEFAULT_CHARSET;
- CF_NOSTYLESEL
- если установлен этот флаг, то поле
выбора стиля шрифта (список «Font style») не
инициализируется;
- CF_NOSIZESEL
- если установлен этот флаг, то поле
выбора размера шрифта не
инициализируется;
- CF_NOSIMULATIONS
- если установлен этот флаг, от
отображаются только реальные шрифты;
- CF_NOVECTORFONTS
- если установлен этот флаг, то
векторные шрифты не отображаются;
- CF_NOVERTFONTS
- если установлен этот флаг, то
отображаются только горизонтально
ориентированные шрифты;
- CF_PRINTERFONTS
- отображаются только шрифты принтера,
определяемого контекстом в поле hDC;
- CF_SCALABLEONLY
- отображаются только масштабируемые
шрифты;
- CF_SCREENFONTS
- отображаются только экранные шрифты;
- CF_SELECTSCRIPT
- если установлен этот флаг, то
отобоажаются только шрифты с набором
символов, установленным в поле pLogFont
(точнее, в поле lfCharSet записи TLogFont, на
которую указывает поле pLogFont);
- CF_SHOWHELP
- на диалоге отображается кнопка «Help»;
- CF_USESTYLE
- если установлен этот флаг, то поле lpszStyle
будет использоваться для
инициализации стиля шрифта;
- CF_WYSIWYG
- если установлен это флаг, то
отображаются только шрифты, доступные
как на экране, так и на принтере
одновременно.
- rgbColors
- если установлен флаг CF_EFFECTS, это поле
используется для задания начального
цвета шрифта. После закрытия окна
содержит цвет шрифта, выбранный
пользователем;
- lCustData
- содержит значение, передаваемое в hook-процедуру
при инициализации диалога;
- lpfnHook
- указатель на hook-функцию для этого
диалога;
- lpTemplateName
- строка с именем ресурса диалогового
окна для переопределения текущего вида
окна;
- hInstance
- либо описатель модуля с шаблоном
диалогового окна, либо описатель блока
памяти с этим шаблоном4
- lpszStyle
- указатель на буфер, сожержащий стиль
шрифта. Если установлен флаг CF_USESTYLE,
это поле используется для инициализации.
После закрытия окна содержит стиль,
установленный пользователем;
- nFontType
- определяет тип возвращенного шрифта,
является набором следующих флагов:
- BOLD_FONTTYPE
- возвращен полужирный шрифт;
- ITALIC_FONTTYPE
- возвращен наклонный шрифт;
- PRINTER_FONTTYPE
- возвращен принтерный шрифт;
- REGULAR_FONTTYPE
- возвращен нормальный шрифт (нормальной
жирности);
- SCREEN_FONTTYPE
- возвращен экранный шрифт;
- SIMULATED_FONTTYPE
- возвращен шрифт, сгенерированный GDI;
- wReserved
- зарезервировано в целях выравнивания;
- nSizeMin
- определяет минимальный размер шрифта,
который может выбрать пользователь,
срабатывает, только если установлен флаг CF_LIMITSIZE;
- nSizeMax
- определяет максимальный размер шрифта,
который может выбрать пользователь,
срабатывает, только если установлен флаг CF_LIMITSIZE;
Как сделать
Порядок работы такой же: заполнить
поля записи, вызвать функцию ChooseFont с
этой записью в качестве параметра,
проанализировать результат.
Демонстрационная программа представляет
собой окно с кнопкой и дочерним окном типа
static с надписью. При нажатии на кнопку
появляется диалог выбора шрифта. Выбранный
шрифт используется как новый шрифт для окна
типа static (тестовое окно).
Обратите внимание, что функция ChooseFont
не создает сам шрифт, а лишь его описание,
расположенное в записи типа TLogFont. Чтобы
создать шрифт, нужно вызвать функцию CreateFontIndirect
с этой записью в качестве параметра.
Сначала определяем глобальные
переменные.
var
lfFont: TLogFont; // данные о текущем шрифте
fntFont: HFONT = 0; // описатель текущего шрифта
crTextColor: COLORREF = 0; // текущий цвет
hbrBrush: HBRUSH; // текущая кисть для закраски фона тестового окна
|
В оконной функции определяем
обработчик нажатия кнопки:
var
cf: TCHOOSEFONT; // запись с параметрами вызова функции
fnt: HFONT;
...
IDOK : begin
cf.lStructSize := sizeof(TCHOOSEFONT);
cf.hWndOwner := wnd; // описатель главного окна
// разрешаем использование эффектов, инициализируем диалог данными о текущем шрифте,
// разрешаем только экранные шрифты
cf.Flags := CF_EFFECTS or CF_INITTOLOGFONTSTRUCT or CF_NOSIMULATIONS or CF_SCREENFONTS;
cf.lpLogFont := @lfFont;
// устанавливаем начальный шрифт в диалоге
cf.rgbColors := crTextColor;
// создаем диалог при помощи вызова функции ChooseFont
if ChooseFont(cf) then begin
// если пользователь нажал ОК
// запоминаем выбранный цвет
crTextColor := cf.rgbColors;
// создаем шрифт по его описанию, полученному из диалога
fnt := CreateFontIndirect(lfFont);
// устанавливаем новый шрифт в тестовом окне
SendMessage(wndStatic, WM_SETFONT, fnt, 1);
// удаляем старый (предыдущий) шрифт
DeleteObject(fntFont);
fntFont := fnt;
end;
end;
|
К сожалению, цвет шрифта тестового
окна так просто не изменить, поэтому ставим
обработчик сообщения WM_CTLCOLORSTATIC, которое
посылается, если нужно перерисовать
дочерние элементы управления типа static. В
параметре wParam этого сообщения
передаётся описатель контекста элемента, а
в lParam его описатель как окна.
WM_CTLCOLORSTATIC: begin
if lParam=wndStatic then begin
// устанавливаем новый цвет шрифта
SetTextColor(wParam, crTextColor);
// устанавливаем фон текста
SetBkColor(wParam, GetSysColor(COLOR_BTNFACE));
// возвращаемое значение должно быть описателем кисти, которой
// будет закрашен фон элемента управления
result := hbrBrush;
end;
end;
|
Значение переменной hbrBrush нужно
определить перед созданием тестового окна:
// создаем однородную кисть такого же цвета, как цвет всего окна
hbrBrush := CreateSolidBrush(GetSyscolor(COLOR_BTNFACE));
|