Глава 1. Создание окна.

Основой любой Windows-программы является окно, даже если программа за все время работы ни разу не появляется на экране. Я сейчас хочу подробно разобрать процесс создания окна на примере простейшей windows-программы, кроме главного окна ничего не имеющей.

Программа winmin

Исходный текст этой программы лежит здесь
program winmin;

uses windows, messages;
{!Модули windows и messages  самые необходимые — они обязательно должны быть 
объявлены в начале каждой Вашей программы!}

var   wc : TWndClassEx;//Переменная шаблона класса окна
 MainWnd : HWND;       //Описатель главного окна
    Mesg : TMsg;       //Переменная для цикла сбора сообщений

{  Далее следует оконная процедура главного окна. Обратите внимание на служебное 
  слово stdcall оно вынуждает компилятор генерировать особый вид кода, который 
  может быть вызван любой windows-программой, без этого служебного слова 
  программа не сможет  работать вообще!}
function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult;
 stdcall;
Begin
{Далее происходит цикл обработки сообщений}
case msg of
wm_destroy ://Сообщение посылаемое при уничтожении окна
  Begin
   postquitmessage(0); exit;
   Result:=0;
  End;

  else Result:=DefWindowProc(wnd,msg,wparam,lparam);
end;

End;
{Переменные xPos,yPos,nWidth,nHeight в принципе не нужны, однако я их завел 
(и вам рекомендую) для лучшей читабельности программы}
var xPos,yPos,nWidth,nHeight : Integer;

begin
{  Далее идет заполнение шаблона класса окна
  подробное описание полей этой записи см. после текста программы}
wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@WindowProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(0,idi_application);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:='WinMin : Main';

RegisterClassEx(wc);//Регистрация нового класса в системе
{  Заполнение переменных xPos,yPos,nWidth,nHeight}
xPos:=100;
yPos:=150;
nWidth:=400;
nHeight:=250;

{  Создание главного окна}
MainWnd:=CreateWindowEx(
0,                  //флаги расширенных стилей
'WinMin : Main',    //имя класса окна, данное при заполнении структуры wc
'Win Min',          //заголовок окна
ws_overlappedwindow,//флаги стилей окна 
{подробнее о стилях см. после текста программы}
xPos,               //горизонтальная позиция окна
yPos,               //вертикальная позиция окна
nWidth,             //ширина окна
nHeight,            //высота окна
0,                  //описатель родительского окна (parent) или окна-владельца (owner) 
0,                  //описатель меню окна (меню нет, нет и описателя)
Hinstance,          //описатель приложения
nil                 //address of window-creation data
);


ShowWindow(MainWnd,CmdShow);//Отображаем окно

//Цикл обработки сообщений
//он может слегка видоизменяться, но эти строчки присутсвуют всегда
While GetMessage(Mesg,0,0,0) do
 begin
  TranslateMessage(Mesg);
  DispatchMessage(Mesg);
 end;

end.

Осталось только уточнить ряд деталей. Во-первых, ВСЁ присутствующее в данной программе (кроме комментариев, разумеется) ОБЯЗАТЕЛЬНО. Укоротить принципиально невозможно, можно, конечно, убрать некоторые переменные, но это сути дела не меняет. Во-вторых, в оконной процедуре могут присутствовать и другие строчки, принимающие сообщения. В-третьих, вызов в оконной процедуре функции DefWindowProc жизненно необходим. DefWindowProc — это оконная процедура по умолчанию, она обеспечивает окну возможность «вести» себя как окну, т.е. перетаскиваться мышкой, сворачиваться, разворачиваться и т.д. Однако не все так плохо, можно писать программы на Win32API не затрачивая таких усилий. Это реализуется при помощи создания приложений, основанных на ресурсах диалоговых окон. Но об этом я подробно напишу позже.


Оконный класс

Коротко о записи TWndClassEx. Эта запись представляет собой шаблон, на основе которого будут создаваться окна. Тип TWndClassEx определен в модуле windows следующим образом
TWndClassExA  = packed record
       cbSize : Integer;
lpszClassName : PChar;
 lpszMenuName : PChar;
  lpfnWndProc : TFNWndProc;//TFNWndProc = Pointer
    hInstance : HINST;     //HINST = Integer
        hIcon : HICON;
      hCursor : HCURSOR;
   cbClsExtra : Integer;
   cbWndExtra : Integer;
        style : Integer;
hbrBackground : HBRUSH;
      hIconSm : HICON;
end;

TWndClassEx = TWndClassExA;

Теперь подробнее о полях этой записи.
cbSize
размер записи. всегда должен быть равен SizeOf(TWndClassEx)
lpszClassName
имя класса. Можно использовать любую понравившуюся вам текстовую ANSI-строку, кроме следующих слов : button, edit, static, listbox, mdiclient, combobox, т.к. они используются для обозначения стандартных элементов управления. По умолчанию, все создаваемые вами оконные классы являются частными (public), т.е. их можно испоьзовать только в создавшей их программе.
lpszMenuName
идентифицирует меню окон данного класса по имени, определенному при проектировании ресурсов для приложения.
lpfnWndProc
определяет функцию, которая отвечает за выдачу сообщений. В это поле записывается указатель на уже существующую функцию с таким заголовком:

function FunctionName(wnd:HWND; Msg : Integer; Wparam : Wparam; 
Lparam : Lparam) : Lresult; stdcall;

hInstance
сообщает Windows, какая программа является создателем данного класса. После завершения работы программы Windows удаляет все связанные с ней классы.
hIcon
описатель пиктограммы окна. Пиктограмма загружается с помощью функции LoadIcon либо из файла ресурсов, либо используется одна из системных пиктограмм (как в случае с нашей программой).
hCursor
описатель курсора окна. В основном используются только системные курсоры. Курсор загружается при помощи LoadCursor.
cbClsExtra и cbWndExtra
обычно не используются. Они нужны, чтобы передавать некоторую информацию при создании класса или окна.
style
содержит набор флагов, определяющих различные особенности класса окна
hbrBackground
содержит описатель кисти, которой закрашивается фон окна
hIconSm
содержит описатель маленькой пиктограммы окна (16x16).
Рассмотрим самые важные из стилей класса окна подробнее
CS_VREDRAW CS_HREDRAW
определяют, будет ли окно перерисовано при изменении вертикального или горизонтального размеров сооответсвенно. Наличие этих флагов может вызвать мерцание при изменении размеров окна
CS_DBLCLKS
этот бит производит установку таймера, в результате чего окно будет способно воспринимать двойной щелчок мыши
CS_NOCLOSE
удаляет из системного меню пункт Close (Закрыть)
CS_SAVEBITS
окно с таким установленным битом при возникновении запоминает битовый образ того места, где оно появится, и при закрытии копирует эти биты на место (так поступает, например, меню
CS_GLOBALCLASS
используется для создания «глобального» класса, т.е. класса, доступного из любой программы

Функция CreateWindowEx

Заголовок функции CreateWindowEx выглядит так:

function CreateWindowEx(
      dwExStyle: Integer;
    lpClassName: PChar;
   lpWindowName: PChar; 
        dwStyle: Integer; 
          X, Y : Integer;
nWidth, nHeight: Integer;
     hWndParent: HWND; 
          hMenu: HMENU; 
      hInstance: HINST; 
        lpParam: Pointer): HWND;
Коротко о назначении параметров этой функции.
dwExStyle
набор расширенных стилей окна (констант, начинающиxся на WS_EX_). Список см. ниже
lpClassName
имя оконноо класса, на основе которого будет создано окно
lpWindowName
первоначальный текст окна, например, для кнопки это будет надпись на ней
dwStyle
список стилей окна (констант, начинающихся на WS_). Подробнее о стилях см. ниже
X , Y
координаты верхнего левого угла окна
nWidth , nHeight
ширина и высота окна
hWndParent
описатель родительского окна для создаваемого окна
hMenu
это поле имеет два значения. Для недочерних окон определяет описатель главного меню окна. Как легко заметить, можно меню определять как в этом поле, так и в описании класса окна, разница заключается в том, что в первом случае вы можете создавать на основе одного класса окна с разными меню. А для дочерних окон (т.е. для окон с установленным флагом стиля WS_CHILD) содержит идентификатор этого окна (этот идентификатор нужен, например, при использовании сообщения WM_COMMAND)
hInstance
содержит описатель экземпляра приложения. В этот парметр нужно передавать встроенную переменную HINSTANCE
lpParam
это поле может содержать указатель на какие-либо данные, значение этого поля передаетс в оконную функцию в составе сообщения WM_CREATE
Стили окна

Ниже приведен список флагов оконных стилей — констант WS_ и описание того, на что влияет добавление этого флага. Напомню, что общий стиль окна получается соединением флагов при помощи операции OR

WS_OVERLAPPED
создается окно с рамкой заголовком, но без системного меню и кнопок «Свернуть», «Развернуть» и т.д.
WS_OVERLAPPEDWINDOW
создается окно имеющее заголовок, изменяемый рвзмер, системное меню, и кнопки управлением окна, короче говоря, обычное окно. Данный флаг является коибинацией нескольких других.
WS_POPUP
флаг, обратный к WS_OVERLAPPED. Создается окно не имеющее ничего, кроме поверхности. Для добавления строки заголовка нужно добавить флаг WS_CAPTION.
WS_BORDER
создается окно с простой тонкой рамкой, причем пользователь не может поменять размер окна.
WS_THICKFRAME
создается окно с толстой рамкой, позволяющее пользователю менять размер окна.
WS_HSCROLL
создается окно с горизонтальной полосой прокрутки
WS_VSCROLL
создается окно с вертикальной полосой прокрутки
WS_SYSMENU
создается окно имеющее системное меню. Для того, чтобы данный флаг заработал, окно должно иметь установленным один из флагов рамки — WS_THICKFRAME или WS_BORDER
WS_MAXIMIZEBOX
создается окно с кнопкой максимизации
WS_MINIMIZEBOX
создается окно с кнопкой минимизации
WS_DISABLED
создается окно, с первоначально запрещенным доступом к нему
WS_MAXIMIZE
создаваемое окно, сразу после создания максимизируется
WS_MINIMIZE
то же самое, только окно минимизируется
WS_VISIBLE
окно создается первоначально видимым. Это очень важный флаг! Если вы не укажете его, то вам придется самостоятельно делать окно видимым при помощи функции ShowWindow. Обычно этот флаг устанавливается вместе с флагом WS_CHILD

Это основные флаги стиля, все остальные можно посмотреть в справке по Delphi

Флаги расширенного стиля окна

Потребность в расширенных стилях возникла из-за того, что стало не хватать флагов обычного стиля (напомню , что их возможно всего 32 штуки). Все флаги расширенного стиля представляют собой константы вида WS_EX_. Список самых важных из них дан ниже

WS_EX_ACCEPTFILES
определяет окно, способное принимать перетаcкиваемые на него файлы из «Проводника Windows»
WS_EX_CONTEXTHELP
определяет окно, с кнопкой контекстного поиска в заголовке окна (кнопка со знаком вопрса внутри). Как использовать эту кнопку — это уже другой вопрос.
WS_EX_TOPMOST
создается окно, располагающееся всегда поверх остальных окон, даже в неактивном состоянии.
WS_EX_TOOLWINDOW
создается окно с тонкой строкой заголовка, обычно используется для панелей инструментов.
WS_EX_CLIENTEDGE
создается окно с «утопленной» клиентской областью

Об остальных стилях см. в справке по Delphi


Цикл сбора сообщений

 Для того, чтобы ваша программа могла принимать сообщения, необходимо организовать специальный цикл — цикл сбора сообщений. Обычно он выглядит так:

While GetMessage(Mesg,0,0,0) do
 begin
  TranslateMessage(Mesg);
  DispatchMessage(Mesg);
 end;

 Однако в отдельных случаях ( когда приложение использует акселераторы либо немодальные диалоговые окна) его вид может изменяться, но об этом будет сказано особо.

 Функция GetMessage извлекает сообщения из системной очереди сообщений, либо из очереди сообщений данной программы, она всегда возвращает True, кроме одного случая — сообщения WM_QUIT. Когда функция натыкается на данное сообщение, цикл (а вместе с ним и программа) завершается. Если вы хотите самостоятельно отлавливать сообщение wm_quit, используйте вместо GetMessage PeekMessage.

 Функция TranslateMessage выполняет только одну функцию — она отлавливает аппаратные сообщения wm_keydown и wm_sysKeyDown о нажатых клавишах, и если для данной клавиши существует её ascii код, формирует сообщение WM_CHAR и вставляет его в очередь сообщений данного процесса.

 Функция DispachMessage отправляет сообщение в оконную функцию.
Назад|Содержание|Вперед

Хостинг от uCoz