Ресурсы — это двоичные данные добавленные в конец исполнимого файла или библиотеки. Ресурсы могут быть как стандартными, так и определяемыми программистом. Стандартные ресурсы — это пиктограммы, курсоры, растровые изображения, метафайлы, шрифты, таблицы строк, таблицы акселераторов, шаблоны меню, шаблоны диалоговых окон и «информация о версии». Ресурсы, определяемые программистом содержат любую информацию, которую программа должна использовать и не должна изменять.
При разработке приложений на Delphi
вам не нужно заботиться о ресурсах, так как
Delphi берет их поддержку на себя. Однако
полезно уметь манипулировать с ресурсами
на этапе разработки программы. В давние
времена программисты вынуждены были
разрабатывать ресурсы, пользуясь только
Блокнотом windows, позже появились специальные
программы разработки ресурсов. Результатом
работы такой программы обычно является так
называемый файл проекта ресурса (resource
script), который затем компилируется в
двоичный файл с расширением .res. После
этого этот двоичный файл должен быть
подключен к вашей программе при помощи
директивы компилятора {$R} следующим
образом :
{$R filename.res} |
Вы можете редактировать .res файл при помощи Image Editor, входящего в состав Delphi, однако в этом случае вы будете способны редактировать только графические ресурсы. Чтобы иметь возможность создавать и редактировать все типы ресурсов, вы должны обзавестись специализированным редактором ресурсов, например Resource Workshop фирмы Borland (вы можете скачать его отсюда). При помощи этой программы вы сможете создавать свои проекты ресусов, редактировать уже существующие, редактировать ресурсы прямо в исполнимых файлах. Вы также можете использовать для создания и редактирования ресурсов редакторы, входящие в среду разработки «Visual Studio» или «Borland C++ 5»
Наконец вы создали проект ресурсов в виде текстового файла .rc (я вам настоятельно советую не создавать .res файл прямо в редакторе ресурсов, лучше сохраняйте проект в виде .rc файла. Кроме того, новый проект начинайте всегда в пустом каталоге и никогда не удаляйте файлы, созданные редактором). Теперь нужно откомпилировать rc файл, для чего используется входящая в состав Delphi программа BRCC32.EXE. Это консольная программа с интерфейсом командной строки, требующая в качестве параметра имя компилируемого rc файла. По умолчанию создается .res файл с именем, совпадающим с именем проекта ресурсов. Кроме того, НЕ создавайте проект ресурса (.rc файл) c тем же именем, что и проект Delphi, например, если ваш проект Delphi называется project.dpr .rc-файл НЕ должен называться project.rc, иначе Delphi просто перезапишет ваш .res файл на свой.
Если у вас есть готовая пиктогамма в .ico файле, то вы можете добавить её в файл проекта ресурсов следующим образом:
120 ICON filename1.ico MAINICON ICON filename2.ico |
Когда ресурсы подключкны к проекту
Delphi, вы можете загружать пиктограмму при
помощи функции LoadIcon. В нашем случае это
делается так:
var icon1, icon2 : THandle ... icon1:=LoadIcon(hInstance, PChar(120)); //Эквивалентный вызов: //icon1 := LoadIcon(hInstance, '#120'); icon2:=LoadIcon(hInstance,'MAINICON'); |
Если у вас есть растровое изображение в формате .bmp, вы можете добавить его в файл проекта ресурсов следующим образом:
130 BITMAP bitmap1.bmp new_bitmap BITMAP bitmap2.bmp |
Когда ресурсы подключены, вы можете загружать свои растровые изображения при помощи функции LoadBitmap, параметры которой точно такие же как и у LoadIcon
Простейшим примером диалогового окна является окно «About Program», находящееся в меню почти каждой Windows-программы; это окно обычно имеет только одну кнопку.
Кроме того, на основе ресурсов диалоговых окон можно создавать полноценные приложения, в том числе и в Delphi. В этом случае значительно сокращается время на написание интерфейсной части win32api-приложения.
Конечно, можно создавать диалоговые окна и при помощи функции CreateWindow, но тогда вам придется точно указывать размера и координаты всех дочерних элементов управления вашего окна. Однако всего этого можно избежать, если воспользоваться предлагаемым Windows способом создания диалоговых окон из ресурсов определенного вида — ресурсов диалоговых окон (dialog box resources). Шаблон диалогового окна создается в специализированном редакторе ресурсов так же как и в редакторе форм Delphi (мышкой перетаскиваете элементы управления из палитры на форму).
Преимущество такого способа создания диалоговых окон заключается в том, что Windows берет на себя обеспечение интерфейса диалоговых окон, к которому привык пользователь — кнопки по умолчанию (срабатывающия, когда пользователь нажмет <Enter> или <Esc>); возможность переключения между дочерними элементами управления при помощи клавиши <Tab> и т.п.
Шаблон диалогового окна, создаваемый в редакторе ресурсов, представляет собой тестовый файл, который перед использованием нужно откомпилировать программой BRCC32.EXE. Далее я приведу несколько примеров хорошо знакомых вам окон и соответствующих им шаблонов.
1539 DIALOG LOADONCALL MOVEABLE DISCARDABLE 37, 34, 300, 125 STYLE DS_MODALFRAME | 0x6004L | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Настройка принтера" FONT 8, "Helv" { CONTROL "Принтер", 1074, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 4, 6, 230, 67 CONTROL "(Принтер не указан)", 1088, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 18, 30, 208, 9 CONTROL "&Используемый по умолчани\xFE", 1058, "BUTTON", BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 8, 16, 218, 12 CONTROL "&Другой принтер:", 1059, "BUTTON", BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE, 8, 42, 218, 12 CONTROL "", 1136, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_GROUP, 18, 56, 208, 80 CONTROL "Ориентаци\xFF", 1072, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 4, 74, 92, 46 CONTROL "", 1084, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 12, 92, 18, 20 CONTROL "&Книжна\xFF", 1056, "BUTTON", BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 40, 86, 53, 12 CONTROL "&Альбомна\xFF", 1057, "BUTTON", BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE, 40, 102, 53, 12 CONTROL "Бумага", 1073, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 101, 74, 133, 46 CONTROL "&Размер:", 1089, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 106, 88, 29, 9 CONTROL "", 1137, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | | WS_TABSTOP, 137, 86, 92, 80 CONTROL "&Подача:", 1090, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 106, 104, 28, 9 CONTROL "", 1138, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 137, 102, 92, 80 CONTROL "ОК", 1, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 240, 4, 55, 14 CONTROL "Отмена", 2, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 240, 20, 55, 14 CONTROL "&Настройка...", 1024, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 240, 40, 55, 14 CONTROL "&Справка", 1038, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 240, 56, 55, 14 } |
Цветами я пометил здесь различные элементы шаблона
Таким цветом помечены идентификаторы элементов управления (идентификаторы дочерних окон)
Таким цветом помечены опции памяти ресурса
Таким цветом помечены имена класов дочерних окон
Таким цветом помечен стиль окна
Таким цветом
помечены размеры и координаты окон
1541 DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 44, 260, 95 STYLE DS_MODALFRAME | 0x6004L | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Замена" FONT 8, "Helv" { CONTROL "&Образец:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 9, 48, 8 CONTROL "", 1152, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_GROUP | WS_TABSTOP, 54, 7, 125, 12 CONTROL "З&аменить на:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 26, 48, 8 CONTROL "", 1153, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_GROUP | WS_TABSTOP, 54, 24, 125, 12 CONTROL "&Только слово целиком", 1040,"BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 6, 46, 104, 12 CONTROL "С у&четом регистра", 1041, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 62, 91, 12 CONTROL "&Найти далее", 1, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 193, 4, 60, 14 CONTROL "&Заменить", 1024, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 193, 21, 60, 14 CONTROL "Заменить &все", 1025, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 193, 38, 60, 14 CONTROL "Отмена", 2, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 193, 55, 60, 14 CONTROL "&Справка", 1038, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 193, 75, 60, 14 } |
На основе одного ресурса диалогового окна может быть создано как модальное, так и немодальное окно; соответственно различается и способ сопровождения диалогового окна. Далее я отдельно рассмотрю механизм создания модальных и немодальных окон.
Модальные окна — это окна, при появлени которых на экране запрещается доступ к родительскому окну.
Для создания модальных диалоговых окон существует функция DialogBoxParam
function DialogBoxParam(hInstance: HINST; lpTemplateName: PChar; hWndParent: HWND; lpDialogFunc: TFNDlgProc; dwInitParam: LPARAM): Integerгде,
Диалоговая функция (lpDialogProc)
должна иметь заголовок следующего типа:
function DialogProc(hWnd: THandle; Msg: Integer; wParam, lParam : Integer): Bool; stdcall;
В теле этой функции должен стоять не совсем обычный блок обработки сообщений. Вместо сообщения ws_create блок диалога получает сообщение wm_initdialog сразу после создания, но до появления на экране; и именно в обработчике этого сообщения нужно устанавливать начальные значения управляющих элементов диалогового окна (поставить где надо галочку или записать какой-либо текст). Также диалоговая функция не получает сообщение wm_paint.
Получая сообщение wm_InitDialog диалоговая функция должна вернуть ненулевое значение (true), если она обрабатывает это сообщение и нуль (false) в противном случае. Также диалоговая процедура должна вернуть нуль в случае, если она вызывает функцию SetFocus для установки фокуса ввода на каком-либо дочернем элементе. В противном случае функция должна возвратить не нуль, в этом случае Windows установит фокус на первом элементе диалогового окна автоматически.
Хотя диалоговая функция похожа на оконную, она не должна вызывать в своем теле функцию DefWindowProc для обработки ненужных сообщений. Ненужные сообщения обрабатываются автоматически.
Для рассылания сообщений элементам управления блока диалога служит функция SendDlgItemMessage, она работает аналогично SendMessage, но требует в качестве параметров описатель окна блока диалога и числовой идентификатор элемента управления, которому посылается сообщение. Пример
SendDlgItemMessage(wndDialog{описатель диал. окна},100{id элемента}, wm_enable,Integer(false),0);
Для установки текста дочернего окна блока диалога используется функция SetDlgItemText, требующая в качестве параметров описатель окна блока диалога, идентификатор элемена и строку нового текста окна элемента.
function SetDlgItemText(hDlg: HWND; nIDDlgItem: Integer; lpString: PChar): BOOL;
Для закрытия модального диалогового окна нужно использовать только функцию EndDialog
function EndDialog(hDlg: HWND; nResult: Integer): BOOL;где,
Напомню, что модальное окно — это окно, после появления которго на экране доступ к проролившему его окну запрещается. Немодальным (modeless) же называется окно, которое не запрещает доступ к ролительскому.
Сопровождение немодальных диалоговых окон несколько сложне нежели модальных. Для создания немодального окна используется функция CreateDialogParam (на самом деле имеется четыре функции предназначенные для достижения этой цели, однако все они схожи по функциональности, поэтому здесь я рассмотрю только одну из них).
function CreateDialogParam(hInstance: THandle; lpTemplateName: PChar; hWndParent: HWND; lpDialogFunc: TFNDlgProc; dwInitParam: LPARAM): HWND;где,
Интерфейс клавиатуры модального диалогового окна включает в себя поддержку клавиш [Tab], [Enter], [Esc], а также клавиш стрелок, они автоматически становятся доступными сразу после создания окна. Чтобы зваставить так вести немодальное окно, нужно слегка изменить цикл сбора сообщений в вашей программе (здесь всюду ведется разговор только о программах, написанных на WinAPI!!!). Перед изменением цикл сбора сообщений обычно выглядит так:
While GetMessage(Mesg,0,0,0) do begin TranslateMessage(Mesg); DispatchMessage(Mesg); end;после изменения так:
While GetMessage(Mesg,0,0,0) do begin if wndDiaog<>0 then if IsDialogMessage(wndDialog,Mesg) then continue; TranslateMessage(Mesg); DispatchMessage(Mesg); end;
где переменная wndDialog должна содержать описатель немодального диалогового окна и, если окно не существует, нуль.
Назад|Содержание|Вперед |