Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Оконные (каркасные) приложения Windows

Поиск

Главным элементом программы в среде Windows является окно. Окно может содержать элементы управления: кнопки, списки, окна редактирования и др. Эти элементы также являются окнами, но обладающими особым свойством: события, происходящие с этими элементами (и самим окном), приводят к приходу сообщений в процедуру окна. Для каждого окна определяется своя процедура обработки сообщений. Система Windows является многозадачной: каждая задача имеет свое адресное пространство и свою очередь сообщений. Любая процедура в среде Windows может быть запущена как самостоятельная задача.

В структуре каркасного приложения Windows можно выделить следующие разделы, образующие «скелет» программы:

· получение дескриптора приложения;

· регистрация класса окна;

· создание главного окна;

· цикл обработки очереди сообщений;

· процедура главного окна.

Получение дескриптора приложения осуществляется функцией

HMODULE WINAPI GetModuleHandle(__in_opt LPCTSTR lpModuleName);

lpModuleName – имя загруженного модуля (.dll или.exe файла), включая путь; если принимает значение 0, то функция возвращает дескриптор исполняемого.exe – файла.

Регистрация класса окна осуществляется с помощью функции

ATOM RegisterClass(CONST WNDCLASS *lpwcx);

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

WNDCLASS struc

style DD?  ;стиль границ окна и его поведение

; при перерисовке

;CS_VREDRAW    = 0001h

;CS_HREDRAW    = 0002h

;CS_KEYCVTWINDOW = 0004H

;CS_DBLCLKS    = 0008h

;CS_OWNDC      = 0020h

;CS_CLASSDC    = 0040h

;CS_PARENTDC   = 0080h

;CS_NOKEYCVT   = 0100h

;CS_SAVEBITS   = 0800h

;CS_NOCLOSE    = 0200h

;CS_BYTEALIGNCLIENT = 1000h

;CS_BYTEALIGNWINDOW = 2000h

;CS_GLOBALCLASS = 4000h   

lpfnWndProc WNDPROC?;адрес оконной процедуры

;Все окна, созданные на основе этого класса,

;будут обрабатывать посланные им сообщения

cbClsExtra DD?;количество дополнительно

cbWndExtra DD?;резервируемых байт, обычно 0

hInstance DD?;дескриптор приложения, полученный

                   ;GetModulHandleA

hIcon     DD?;дескриптор значка LoadIcon

;IDI_APPLICATION = 32512

;IDI_HAND   = 32513

;IDI_QUESTION = 32514

;IDI_EXCLAMATION = 32515

;IDI_ASTERISK = 32516

hCursor   DD?;дескриптор курсора LoadCursor

;IDC_ARROW  = 32512

;IDC_IBEAM  = 32513

;IDC_WAIT   = 32514

;IDC_CROSS  = 32515

;IDC_UPARROW = 32516

;IDC_SIZE   = 32640

;IDC_ICON   = 32641

;IDC_SIZENWSE = 32642

;IDC_SIZENESW = 32643

;IDC_SIZEWE = 32644

;IDC_SIZENS = 32645

hbrBackground DD?;дескриптор кисти

;WHITE_BRUSH =0

;LTGRAY_BRUSH =1

;GRAY_BRUSH =2

;DKGRAY_BRUSH =3

;BLACK_BRUSH =4

;NULL_BRUSH =5

;HOLLOW_BRUSH =5

Цвет фона окна можно также задать функцией CreateSolidBrush, аргумент которой – это константа, получаемая как комбинация трех цветов (RGB): красного, зеленого и синего. Цвет определяется одним 32-битным числом. В этом числе первый байт - интенсивность красного, второй байт - интенсивность зеленого, третий байт - интенсивность синего цвета. Последний байт равен нулю.

lpszMenuName DD 0;указатель на ASCIIZ строку

;с именем меню

lpszClassName DD?;присвоение данному классу

                   ;уникального имени

ends

Создание окна осуществляется с помощью функции, позволяющей создать экземпляр окна.

HWND CreateWindowEx(

DWORD dwExStyle,

LPCTSTR lpClassName,

LPCTSTR lpWindowName,

DWORD dwStyle,

int x,

int y,

int nWidth,

int nHeight,

HWND hWndParent,

HMENU hMenu,

HINSTANCE hInstance,

LPVOID lpParam);

dwExStyle – определяет дополнительные стили создаваемого окна:

WS_EX_ACCEPTFILES = 10h – поддержка перетаскивания файлов

WS_EX_APPWINDOW = 00040000h – добавление окна на панель задач

WS_EX_CLIENTEDGE = 00000200h – стиль границ окна

WS_EX_COMPOSITED – перерисовка снизу вверх (Windows XP)

WS_EX_CONTEXTHELP =00000400h – значок «?» в строке заголовка окна

WS_EX_CONTROLPARENT=00010000h – окно содержит дочернее окно, использующееся в диалогах

WS_EX_DLGMODALFRAME = 1h – окно с двойной границей

WS_EX_LAYERED=00080000h – «послойное» окно (Windows XP)

WS_EX_LAYOUTRTL=00400000h – начало отсчета по горизонтали – справа

WS_EX_LEFT=00000000h –выравнивание свойств по левому краю (по умолчанию)

WS_EX_LEFTSCROLLBAR = 00004000h – полоса прокрутки слева

WS_EX_LTRREADING= 00000000h – отображение текста слева направо (по умолчанию)

WS_EX_MDICHILD – создание дочернего окна в многооконном интерфейсе (MDI)

WS_EX_NOACTIVATE= 08000000h – созданное окно не активируется

WS_EX_NOINHERITLAYOUT= 00100000h – окно не передает свое положение дочерним окнам

WS_EX_NOPARENTNOTIFY = 4h – дочернее окно не передает сообщение WM_PARENTNOTIFY родительскому окну при своем создании/закрытии.

WS_EX_OVERLAPPEDWINDOW=WS_EX_CLIENTEDGE+WS_EX_WINDOW.

WS_EX_PALETTEWINDOW=WS_EX_WINDOWEDGE+WS_EX_TOOLWINDOW+WS_EX_TOPMOST.

WS_EX_RIGHT = 00001000h – выравнивание свойств по правому краю

WS_EX_RIGHTSCROLLBAR = 00000000h – вертикальная полоса прокрутки в правой части окна (по умолчанию)

WS_EX_RTLREADING  =00002000h – размещение текста справа налево

WS_EX_STATICEDGE =00020000h – окно с тркхмерным стилем границ

WS_EX_TOOLWINDOW = 00000080h – окно для плавающей панели инструментов

WS_EX_TOPMOST = 8h – расположение окна перед всеми окнами.

WS_EX_TRANSPARENT = 20h – окно без перерисовки

WS_EX_WINDOWEDGE = 00000100h – «приподнятый» стиль границ окна

lpClassName — указатель на ASCIIZ-строку с именем класса окна.

Можно использовать предопределенные классы для создания элементов окна:

BUTTON – кнопка;

COMBOBOX – набор переключателей;

EDIT – поле редактирования;

LISTBOX – список;

MDICLIENT – MDI-клиент;

RICHEDIT_CLASS – объект Rich Edit 2.0;

SCROLLBAR – полоса прокрутки;

STATIC – надпись.

lpWindowName — указатель на ASCIIZ-строку с именем окна.

dwStyle определяет стиль окна приложения:

WS_OVERLAPPED =000000000h

WS_ICONICPOPUP =0C0000000h

WS_POPUP =080000000h

WS_CHILD =040000000h

WS_MINIMIZE =020000000h

WS_VISIBLE =010000000h

WS_DISABLED =008000000h

WS_CLIPSIBLINGS =004000000h

WS_CLIPCHILDREN =002000000h

WS_MAXIMIZE =001000000h

WS_CAPTION =000C00000h;WS_BORDER | WS_DLGFRAME

WS_BORDER =000800000h

WS_DLGFRAME =000400000h

WS_VSCROLL =000200000h

WS_HSCROLL =000100000h

WS_SYSMENU =000080000h

WS_THICKFRAME =000040000h

WS_HREDRAW =000020000h

WS_VREDRAW =000010000h

WS_GROUP =000020000h

WS_TABSTOP =000010000h

WS_MINIMIZEBOX =000020000h

WS_MAXIMIZEBOX =000010000h

x — координата левого верхнего угла окна

y — координата левого верхнего угла окна

nWidth — ширина окна (по умолчанию CW_USEDEFAULT (80000000h))

nHeight — высота окна (по умолчанию CW_USEDEFAULT (80000000h))

hWndParent — дескриптор родительского окна. Между двумя окнами Windows-приложения можно устанавливать родовидовые отношения. Дочернее окно всегда должно появляться в области родительского окна.

hMenu — дескриптор главного меню окна

hInstance — дескриптор приложения, создающего окно.

lpParam – используется при создании окна для передачи данных или указателя на них в оконную функцию. Все параметры, передаваемые функции CreateWindowEx, сохраняются в создаваемой Windows внутренней структуре CREATESTRUCT. Поля этой структуры идентичны параметрам функции CreateWindowEx. Указатель на структуру CREATESTRUCT передается оконной функции при обработке сообщения WMCREATE. Сам указатель находится в поле lpParam сообщения. Значение параметра lpParam функции CreateWindowEx находится в поле lpCreateParams структуры CREATESTRUCT.

Функция CreateWindowEx возвращает дескриптор окна.

 

Для отображения окна используется функция

BOOL ShowWindow(HWND hWnd, int nCmdShow);

hWnd – дескриптор окна.

nCmdShow – константа, задающая начальный вид окна.

SW_HIDE       =0

SW_SHOWNORMAL =1

SW_NORMAL     =1

SW_SHOWMINIMIZED =2

SW_SHOWMAXIMIZED =3

SW_MAXIMIZE =3

SW_SHOWNOACTIVATE =4

SW_SHOW       =5

SW_MINIMIZE   =6

SW_SHOWMINNOACTIVE =7

SW_SHOWNA     =8

SW_RESTORE    =9

 

Цикл обработки сообщений. После создания данного цикла приложение становится пассивным и начинает взаимодействовать с внешним миром посредством специальным образом оформленных данных — сообщений. Для получения сообщений используется функция GetMessage, выполняющая следующие действия:

· постоянно просматривать очередь сообщений;

· выбирать сообщения, удовлетворяющие заданным в функции параметрам;

· заносит информацию о событии в экземпляр структуры MSG;

· передает управление в цикл обработки сообщений.

BOOL GetMessage(LPMSG lpMsg,

HWND hWnd,

UINT wMsgFilterMin,

UINT wMsgFilterMax);

lpMsg – указатель на экземпляр структуры MSG. Во время работы GetMessageA извлекает сообщение из очереди сообщений приложения и на основе информации в нем инициализирует поля экземпляра структуры MSG. Таким образом, приложение получает полный доступ ко всей информации в сообщении, сформированном Windows.

MSG struc

hwnd DD?;дескриптор окна, которому адресовано сообщение

            ;возвращается функцией CreateWindowEx

mes DD?;идентификатор типа сообщения

            ;все константы начинаются с WM_

wParam DD?;дополнительная информация о сообщении

lParam DD?

time DD?;время помещения сообщения в очередь сообщений

pt POINT <>;координаты курсора мыши в момент помещения

MSG ends    ;сообщения в очередь

  

POINT struc

x DD 0

y DD 0

POINT ends

hWnd — в поле передается дескриптор окна, сообщения для которого должны будут выбираться данной функцией. Параметр, позволяет создать своеобразный фильтр, заставляющий функцию GetMessage выбирать из очереди и передавать в цикл обработки сообщений сообщения лишь для определенного окна данного приложения. Если hWnd=0, то GetMessage будет выбирать из очереди сообщения для всех окон;

wMsgFilterMin и wMsgFi1terMax — значения данных параметров также позволяют создавать фильтр для выбираемых функцией GetMessageA сообщений. Они задают диапазон номеров сообщений (поле mes структуры MSG), которые будут выбираться из очереди функцией GetMessage и передаваться в цикл обработки сообщений.

Цикл обработки сообщений состоит из двух функций:

BOOL TranslateMessage(const MSG *lpMsg);

LRESULT DispatchMessage(const MSG *lpmsg);

Эти функции имеют единственный параметр — указатель на экземпляр структуры MSG, предварительно заполненный информацией о сообщении функцией GetMessage.

Функция TranslateMessage предназначена для обнаружения сообщений от клавиатуры для данного приложения. Если приложение не будет самостоятельно обрабатывать ввод с клавиатуры, то эти сообщения передаются для обработки обратно Windows.

Функция DispatchMessage предназначена для передачи сообщения оконной функции. Такая передача производится не напрямую, так как сама DispatchMessage ничего не знает о месторасположении оконной функции, а косвенно — посредством системы Windows. При этом:

- функция DispatchMessage возвращает сообщение операционной системе;

- Windows, используя описание класса окна, передает сообщение нужной оконной функции приложения;

- после обработки сообщения оконной функцией управление возвращается операционной системе;

- Windows передает управление функции DispatchMessage;

-  DispatchMessage завершает свое выполнение.

Так как вызов функции DispatchMessage является последним в цикле, то управление опять передается функции GetMessage. GetMessage выбирает следующее сообщение из очереди сообщений и, если оно удовлетворяет параметрам, заданным при вызове этой функции, то выполняется тело цикла. Цикл обработки сообщений выполняется до тех пор, пока не приходит сообщение, равное 0. Получение этого сообщения — единственное условие, при котором программа может выйти из цикла обработки сообщений.

Таким образом, главная функция будет иметь следующий вид:

.586

.MODEL FLAT, stdcall

include win.inc   ; файл с константами и структурами

 

; сегмент данных

.data

HWND DD 0; дескриптор главного окна

Message MSG <?>

WC   WNDCLASS <?>

HINST DD 0; дескриптор приложения

TITLENAME DB 'Программа',0

CLASSNAME DB 'CLASS32',0

...

 

; сегмент кода

.code

START proc

; получить дескриптор приложения

INVOKE GetModuleHandle, 0

MOV HINST, EAX

REG_CLASS:

; заполнить структуру окна стиль

MOV WC.style, CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

; процедура обработки сообщений

MOV WC.lpfnWndProc, OFFSET WNDPROC

MOV WC.cbClsExtra, 0

MOV WC.cbWndExtra, 0

MOV EAX, HINST

MOV WC.hInstance, EAX

;--------- иконка окна

 INVOKE LoadIcon, 0, IDI_APPLICATION

MOV WC.hIcon, EAX

;---------- курсор окна

 INVOKE LoadCursor, 0, IDC_ARROW

MOV WC.hCursor, EAX

;---------

MOV WC.hbrBackground, GRAY_BRUSH; цвет окна

MOV DWORD PTR WC.lpszMenuName, 0

MOV DWORD PTR WC.lpszClassName, OFFSET CLASSNAME

 INVOKE RegisterClass, OFFSET WC

; создать окно зарегистрированного класса

 INVOKE CreateWindowEx,

0,

    OFFSET CLASSNAME,

    OFFSET TITLENAME,

    WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_GROUP +\

     WS_TABSTOP,

    100,; X — координата левого верхнего угла

    100,; Y — координата левого верхнего угла

    400,; DX - ширина окна

    450,; DY — высота окна

    0, 0, HINST,0

; проверка на ошибку

CMP EAX, 0

JZ END_LOOP

MOV HWND, EAX; дескриптор окна

; --------------------------------------------------

INVOKE ShowWindow, HWND, SW_SHOWNORMAL; показать созданное окно

INVOKE UpdateWindow, HWND;перерисовать видимую часть окна

 

; цикл обработки сообщений

MSG_LOOP:

 INVOKE GetMessage,

     OFFSET Message, 0,0,0

CMP EAX, 0

JE END_LOOP

 INVOKE TranslateMessage, OFFSET Message

 INVOKE DispatchMessageA, OFFSET Message

JMP MSG_LOOP

END_LOOP:

; выход из программы (закрыть процесс)

 INVOKE ExitProcess, Message.wParam

 START endp

...

Для организации адекватной реакции со стороны Windows-приложения на действия пользователя и поддержания в актуальном состоянии того окна приложения, сообщения которого обрабатываются, используется оконная функция. Приложение может иметь несколько оконных функций. Их количество определяется количеством классов окон, зарегистрированных в системе функцией RegisterClass.

Когда для окна Windows-приложения появляется сообщение, операционная система Windows производит вызов соответствующей оконной функции. Сообщения, в зависимости от источника их появления в оконной функции, могут быть двух типов: синхронные и асинхронные. К синхронным сообщениям относятся те сообщения, которые помещаются в очередь сообщений приложения и терпеливо ждут момента, когда они будут выбраны функцией GetMessage. После этого поступившие сообщения попадают в оконную функцию, где и производится их обработка. Асинхронные сообщения попадают в оконную функцию в экстренном порядке, минуя при этом все очереди. Асинхронные сообщения, в частности, инициируются некоторыми функциями Win32 API, такими как CreateWindowEx или UpdateWIndow. Координацию синхронных и асинхронных сообщений осуществляет Windows. Если рассматривать синхронное сообщение, то его извлечение производится функцией GetMessage с последующей передачей его обратно в Windows функцией DispatchMessage. Асинхронное сообщение, независимо от источника, который инициирует его появление, сначала попадает в Windows и затем — в нужную оконную функцию.

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

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

Оконная функция имеет следующие параметры:

1. hWnd — дескриптор окна, которому предназначено сообщение;

2. message — идентификатор сообщения, характеризующий тип сообщения;

3. wParam и lРaram —дополнительные параметры, являющиеся копиями соответствующих полей структуры поступившего сообщения.

Оставшиеся два поля структуры MSG: time и POINT используются достаточно редко, и при необходимости их значения можно извлечь непосредственно из экземпляра структуры сообщения.

Параметры оконной функции Windows помещает в стек.

Основные типы обрабатываемых идентификаторов сообщений

WM_CREATE equ 1h; создание окна

WM_DESTROY equ 2h; закрытие окна

WM_PAINT equ 0Fh  ; перерисовка окна

WM_COMMAND equ 111h  ; обработка команды Windows

 

WM_LBUTTONDOWN equ 201h; нажатие левой кнопки мыши

WM_LBUTTONUP equ 202h; отжатие левой кнопки мыши

WM_LBUTTONDBLCLK equ 203h; двойное нажатие левой кнопки мыши

WM_RBUTTONDOWN equ 204h; нажатие правой кнопки мыши

WM_RBUTTONUP equ 205h; отжатие правой кнопки мыши

WM_RBUTTONDBLCLK equ 206h; двойное нажатие правой кнопки мыши

WM_MBUTTONDOWN equ 207h; нажатие средней кнопки мыши

WM_MBUTTONUP equ 208h; отжатие средней кнопки мыши

WM_MBUTTONDBLCLK equ 209h; двойное нажатие средней кнопки мыши

Структура процедуры окна строится по принципу switch-case, выбирая из списка тип события, которое необходимо обработать.

При перерисовке окна системой посылается сообщение WM_PAINT, именно при получении этого сообщения следует перерисовывать содержимое окна. Это сообщение генерируется системой при разворачивании окна, изменении его размеров, наложении на данное окно других окон с последующим их закрытием. Для того, чтобы осуществить вывод информации в окно, необходимо сначала получить контекст окна (контекст устройства). Это — некоторое число, посредством которого осуществляется связь между приложением и окном. Обычно контекст устройства определяется посредством функции

HDC GetDC(HWND hWnd); передается дескриптор окна

При получении сообщения WM_PAINT контекст устройства получается посредством функции

HDC BeginPaint(

HWND hwnd,       // дескриптор окна

LPPAINTSTRUCT lpPaint); // указатель на структуру PAINTSTRUCT

PAINTSTRUCT STRUCT

hdc DWORD 0; дескриптор контекста окна

fErase DWORD 0; 1 – стирать фон, 0 – оставить фон окна

left DWORD 0; левый

top DWORD 0; верхний

right DWORD 0; правый

bottom DWORD 0; нижний угол прямоугольника для перерисовки

fRes DWORD 0; резервный, используется системой

fIncUp DWORD 0; резервный, используется системой

Reserv DB 32 dup(0); резервный, используется системой

PAINTSTRUCT ENDS

Для вывода текста в окно используется функция

BOOL TextOut(

HDC hdc,      // дескриптор контекста окна

int nXStart,  // координата Х начальной позиции

int nYStart,  // координата Н начальной позиции

LPCTSTR lpString, // указатель на строку символов

int cbString); // количество байт для вывода

Предварительно задать цвет фона и букв можно посредством функций

COLORREF SetBkColor(

HDC hdc,        // дескриптор контекста окна

COLORREF crColor); // цвет фона RGB

COLORREF SetTextColor(

HDC hdc,        // дескриптор контекста окна

COLORREF crColor); // цвет букв RGB

Центр системы координат для окна находится в левом верхнем углу, ось Y направлена вниз, ось Х - вправо. Это общепринятый вариант для графических экранов.

Для окончания перерисовки окна используется функция

BOOL EndPaint(

HWND hWnd,             // дескриптор окна

CONST PAINTSTRUCT *lpPaint // указатель на структуру PAINTSTRUCT

);                  // полученную функцией BeginPaint

Для завершения приложения используется сообщение WM_DESTROY, которое обрабатывается вызовом функции

void PostQuitMessage(int nExitCode);

Аргументом функции является код завершения приложения.

Для обработки нажатия на кнопку как элемент управления окна используется сообщение WM_COMMAND. При его получении программа сравнивает параметр lparam  функции окна последовательно с дескрипторами кнопок и анализирует, с какой кнопкой произведено действие.

Если обработчик для данного типа сообщения не требуется, вызывается обработчик сообщения по умолчанию в виде функции

LRESULT DefWindowProc(

HWND hWnd,  // дескриптор окна

UINT Msg,   // тип сообщения

WPARAM wParam, // параметр сообщения

LPARAM lParam); // параметр сообщения

 

Пример оконной функции, выводящей в окно строку «Привет Всем».

.data

 ...

 hBut DD?; дескриптор кнопки

 hdc DD?; дескриптор контекста окна

 ps      PAINTSTRUCT <?>

 mess db 'Привет всем!',0; надпись в окне

 mess_len equ $-mess-1

.code

...

; --------------------------------------------------

; процедура окна

WNDPROC PROC hW:DWORD, Mes:DWORD, wParam:DWORD, lParam:DWORD

CMP Mes, WM_DESTROY

JE WMDESTROY

CMP Mes, WM_CREATE

JE WMCREATE

CMP Mes, WM_PAINT     

JE WMPAINT

JMP DEFWNDPROC

; создание окна

WMCREATE:

MOV EAX, 0

JMP FINISH

; перерисовка окна

WMPAINT:

INVOKE BeginPaint, hW, offset ps

mov hdc,eax

INVOKE SetBkColor, hdc, RGBW

 

mov eax, mess_len

INVOKE TextOutA,

    hdc,

    10, 20,;x, y

    offset mess,

    eax

 

INVOKE EndPaint, hdc, offset ps

MOV EAX, 0

JMP FINISH

; обработка сообщения по умолчанию

DEFWNDPROC:

 INVOKE DefWindowProc,

hW,

    Mes,

    wParam,

    lParam  

JMP FINISH

WMDESTROY:

 INVOKE PostQuitMessage, 0

MOV EAX, 0

FINISH: ret

WNDPROC ENDP

END START

Пример программы, вычисляющей сумму двух чисел.

; файл win.inc

; директивы компилятору для подключения прототипов функций

include c:\masm32\include\kernel32.inc

include c:\masm32\include\user32.inc

include c:\masm32\include\gdi32.inc

include c:\masm32\include\shlwapi.inc

 

; стандартные дескрипторы окна

IDI_APPLICATION = 32512

IDI_HAND   = 32513

IDI_QUESTION = 32514

IDI_EXCLAMATION = 32515

IDI_ASTERISK = 32516

 

;стандартные дескрипторы курсора

IDC_ARROW  = 32512

IDC_IBEAM  = 32513

IDC_WAIT   = 32514

IDC_CROSS  = 32515

IDC_UPARROW = 32516

IDC_SIZE   = 32640

IDC_ICON   = 32641

IDC_SIZENWSE = 32642

IDC_SIZENESW = 32643

IDC_SIZEWE = 32644

IDC_SIZENS  = 32645

 

; свойства окна

CS_VREDRAW    = 0001h

CS_HREDRAW    = 0002h

CS_KEYCVTWINDOW = 0004H

CS_DBLCLKS    = 0008h

CS_OWNDC      = 0020h

CS_CLASSDC    = 0040h

CS_PARENTDC   = 0080h

CS_NOKEYCVT   = 0100h

CS_SAVEBITS      = 0800h

CS_NOCLOSE    = 0200h

CS_BYTEALIGNCLIENT = 1000h

CS_BYTEALIGNWINDOW = 2000h

CS_GLOBALCLASS = 4000h   

 

; цвет кисти

WHITE_BRUSH   =0;прозрачное окно

LTGRAY_BRUSH =1

GRAY_BRUSH    =2

DKGRAY_BRUSH =3

BLACK_BRUSH   =4

NULL_BRUSH    =5; привычный цвет окна

HOLLOW_BRUSH =5

 

; структура

WNDCLASS STRUCT

style        DD?

lpfnWndProc  DD?

cbClsExtra   DD 0

cbWndExtra   DD 0

hInstance    DD?

hIcon        DD?

hCursor      DD?

hbrBackground DD?

lpszMenuName DD 0

lpszClassName DD?

WNDCLASS ENDS

 

; тип окна

WS_OVERLAPPED =000000000h

WS_ICONICPOPUP =0C0000000h

WS_POPUP =080000000h

WS_CHILD =040000000h

WS_MINIMIZE   =020000000h

WS_VISIBLE    =010000000h

WS_DISABLED   =008000000h

WS_CLIPSIBLINGS =004000000h

WS_CLIPCHILDREN =002000000h

WS_MAXIMIZE   =001000000h

WS_CAPTION    =000C00000h;WS_BORDER | WS_DLGFRAME

WS_BORDER =000800000h

WS_DLGFRAME   =000400000h

WS_VSCROLL    =000200000h

WS_HSCROLL    =000100000h

WS_SYSMENU    =000080000h

WS_THICKFRAME =000040000h

WS_HREDRAW    =000020000h

WS_VREDRAW    =000010000h

WS_GROUP =000020000h

WS_TABSTOP    =000010000h

WS_MINIMIZEBOX =000020000h

WS_MAXIMIZEBOX =000010000h

 

; отображение окна

SW_HIDE       =0

SW_SHOWNORMAL =1

SW_NORMAL =1

SW_SHOWMINIMIZED =2

SW_SHOWMAXIMIZED =3

SW_MAXIMIZE   =3

SW_SHOWNOACTIVATE =4

SW_SHOW       =5

SW_MINIMIZE   =6

SW_SHOWMINNOACTIVE =7

SW_SHOWNA =8

SW_RESTORE    =9

 

; Типы сообщений

WM_NULL                         equ 0h

WM_CREATE                        equ 1h

WM_DESTROY                      equ 2h

WM_MOVE                         equ 3h

WM_SIZE                         equ 5h

WM_ACTIVATE                     equ 6h

WM_SETFOCUS                     equ 7h

WM_KILLFOCUS                    equ 08h

WM_ENABLE                       equ 0Ah

WM_SETREDRAW                    equ 0Bh

WM_SETTEXT                      equ 0Ch

WM_GETTEXT                      equ 0Dh

WM_GETTEXTLENGTH                equ 0Eh

WM_PAINT                        equ 0Fh

WM_CLOSE                        equ 10h

WM_QUIT                         equ 12h

WM_KEYFIRST                     equ 100h

WM_KEYDOWN                      equ 100h

WM_KEYUP                        equ 101h

WM_CHAR                         equ 102h

WM_INITDIALOG                   equ 110h

WM_COMMAND                      equ 111h

WM_SYSCOMMAND                   equ 112h

WM_TIMER                        equ 113h

WM_HSCROLL                      equ 114h

WM_VSCROLL                      equ 115h

WM_MOUSEMOVE                    equ 200h

WM_LBUTTONDOWN                  equ 201h

WM_LBUTTONUP                    equ 202h

WM_LBUTTONDBLCLK                equ 203h

WM_RBUTTONDOWN                  equ 204h

WM_RBUTTONUP                    equ 205h

WM_RBUTTONDBLCLK                equ 206h

WM_MBUTTONDOWN                  equ 207h

WM_MBUTTONUP                    equ 208h

WM_MBUTTONDBLCLK                equ 209h

WM_WINDOWPOSCHANGING            equ 46h

WM_WINDOWPOSCHANGED             equ 47h

WM_SIZING              equ 214h

 

 

; структура сообщения

POINT STRUCT

x DD?

y DD?

POINT ENDS

 

MSG STRUCT

hwnd DD?

message DD?

wParam DD?

lParam DD?

time DD?

pt   POINT <>

MSG ENDS

 

PAINTSTRUCT STRUCT

hdc DWORD 0; дескриптор контекста окна

fErase DWORD 0; 1 – стирать фон, 0 – оставить фон окна

left DWORD 0; левый

top DWORD 0; верхний

right DWORD 0; правый

bottom DWORD 0; нижний угол прямоугольника для перерисовки

fRes DWORD 0; резервный, используется системой

fIncUp DWORD 0; резервный, используется системой

Reserv DB 32 dup(0); резервный, используется системой

PAINTSTRUCT ENDS

 

RECT STRUCT

left dd 0

top dd 0

right dd 0

bottom dd 0

RECT ENDS

 

SRCCOPY                         equ 0CC0020h

SRCPAINT                        equ 0EE0086h

SRCAND                          equ 8800C6h

SRCINVERT                       equ 660046h

SRCERASE                        equ 440328h

 

PATCOPY                         equ 0F00021h

PATPAINT                        equ 0FB0A09h

PATINVERT                       equ 5A0049h

DSTINVERT                       equ 550009h

BLACKNESS                       equ 42h

WHITENESS                       equ 0FF0062h

 

PS_SOLID                        equ 0

PS_DASH                         equ 1

PS_DOT                          equ 2

PS_DASHDOT                      equ 3

PS_DASHDOTDOT                   equ 4

PS_NULL                         equ 5

PS_INSIDEFRAME                  equ 6

PS_USERSTYLE                    equ 7

PS_ALTERNATE                    equ 8

PS_STYLE_MASK                   equ 0Fh

PS_ENDCAP_ROUND                 equ 0h

PS_ENDCAP_SQUARE                equ 100h

PS_ENDCAP_FLAT                  equ 200h

PS_ENDCAP_MASK                  equ 0F00h

PS_JOIN_ROUND                   equ 0h

PS_JOIN_BEVEL                   equ 1000h

PS_JOIN_MITER                   equ 2000h

PS_JOIN_MASK                    equ 0F000h

PS_COSMETIC                          equ 0h

PS_GEOMETRIC                    equ 10000h

PS_TYPE_MASK                    equ 0F0000h

 

 

SM_CXSCREEN                     equ 0

SM_CYSCREEN                     equ 1

SM_CXVSCROLL                    equ 2

SM_CYHSCROLL                    equ 3

SM_CYCAPTION                    equ 4

SM_CXBORDER                     equ 5

SM_CYBORDER                     equ 6

SM_CXDLGFRAME                   equ 7

SM_CYDLGFRAME                   equ 8

SM_CYVTHUMB                     equ 9

SM_CXHTHUMB                     equ 10

SM_CXICON                       equ 11

SM_CYICON                       equ 12

SM_CXCURSOR                     equ 13

SM_CYCURSOR                     equ 14

SM_CYMENU                       equ 15

SM_CXFULLSCREEN                 equ 16

SM_CYFULLSCREEN                 equ 17

SM_CYKANJIWINDOW                equ 18

SM_MOUSEPRESENT                 equ 19

SM_CYVSCROLL                    equ 20

SM_CXHSCROLL                    equ 21

SM_DEBUG                        equ 22

SM_SWAPBUTTON                   equ 23

SM_RESERVED1                    equ 24

SM_RESERVED2                    equ 25

SM_RESERVED3                       equ 26

SM_RESERVED4                    equ 27

SM_CXMIN                        equ 28

SM_CYMIN                        equ 29

SM_CXSIZE                       equ 30

SM_CYSIZE                       equ 31

SM_CXFRAME                      equ 32

SM_CYFRAME                      equ 33

SM_CXMINTRACK                   equ 34

SM_CYMINTRACK                   equ 35

SM_CXDOUBLECLK                  equ 36

SM_CYDOUBLECLK                  equ 37

SM_CXICONSPACING                equ 38

SM_CYICONSPACING                equ 39

SM_MENUDROPALIGNMENT            equ 40

SM_PENWINDOWS                   equ 41

SM_DBCSENABLED                  equ 42

SM_CMOUSEBUTTONS                equ 43

SM_CXFIXEDFRAME                 equ SM_CXDLGFRAME

SM_CYFIXEDFRAME                 equ SM_CYDLGFRAME

SM_CXSIZEFRAME                  equ SM_CXFRAME

SM_CYSIZEFRAME                  equ SM_CYFRAME

SM_SECURE                       equ 44

SM_CXEDGE                       equ 45

SM_CYEDGE                       equ 46

SM_CXMINSPACING                 equ 47

SM_CYMINSPACING                 equ 48

SM_CXSMICON                     equ 49

SM_CYSMICON                     equ 50

SM_CYSMCAPTION                  equ 51

SM_CXSMSIZE                     equ 52

SM_CYSMSIZE                     equ 53

SM_CXMENUSIZE                   equ 54

SM_CYMENUSIZE                   equ 55

SM_ARRANGE                      equ 56

SM_CXMINIMIZED                  equ 57

SM_CYMINIMIZED                  equ 58

SM_CXMAXTRACK                   equ 59

SM_CYMAXTRACK                   equ 60

SM_CXMAXIMIZED                  equ 61

SM_CYMAXIMIZED                  equ 62

SM_NETWORK                      equ 63

SM_CLEANBOOT                    equ 67

SM_CXDRAG                       equ 68

SM_CYDRAG                       equ 69

SM_SHOWSOUNDS                   equ 70

SM_CXMENUCHECK                  equ 71

SM_CYMENUCHECK                  equ 72

SM_SLOWMACHINE                  equ 73

SM_MIDEASTENABLED               equ 74

SM_MOUSEWHEELPRESENT            equ 75

SM_CMETRICS                     equ 75

SM_XVIRTUALSCREEN             equ 76

SM_YVIRTUALSCREEN             equ 77

SM_CXVIRTUALSCREEN            equ 78

SM_CYVIRTUALSCREEN            equ 79

SM_CMONITORS                  equ 80

 

; файл с текстом программы

.586

.MODEL FLAT, stdcall

RGBW  equ 00CCCCCCh; цвет фона окна

include win.inc

include console.inc[1]

 

.data

HWND DD 0; дескриптор главного окна

HINST DD 0; дескриптор приложения

TITL DB "Программа",0

CLASSNAME DB 'CLASS32',0

Message MSG <?>

WC   WNDCLASS <?>

 

CPBUT db 'Рассчитать',0

CLSBTN db 'BUTTON',0

CLSEDT db 'EDIT',0

CAP db 'Сообщение',0

TEXTA db 20 dup(0); текст в полях редактирования

TEXTB db 20 dup(0)

summa dd 0

 

hBut DD?; дескриптор кнопки

hedt1 DD?; дескриптор поля 1

hedt2 DD?; дескриптор поля 2

 hdc DD?; дескриптор контекста окна

 ps PAINTSTRUCT <?>

 mess1 db 'Посчитать сумму двух чисел: ',0; надпись в окне

 mess1_len equ $-mess1-1

 mess2 db '=',10 dup(' '),0; результат суммы строковый

 sum_len equ $-mess2-1

    

.code

START proc

; получить дескриптор приложения

INVOKE GetModuleHandle, 0

MOV HINST, EAX

; заполнить структуру окна стиль

MOV WC.style, CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

; процедура обработки сообщений

MOV WC.lpfnWndProc, OFFSET WNDPROC

MOV EAX, HINST

MOV WC.hInstance, EAX

INVOKE LoadIcon, 0, IDI_APPLICATION

MOV WC.hIcon, EAX

INVOKE LoadCursor, 0, IDC_ARROW

MOV WC.hCursor, EAX

INVOKE CreateSolidBrush, RGBW

MOV WC.hbrBackground, EAX

MOV DWORD PTR WC.lpszMenuName, 0

MOV DWORD PTR WC.lpszClassName, OFFSET CLASSNAME

INVOKE RegisterClass, OFFSET WC

; создать окно зарегистрированного класса

 INVOKE CreateWindowEx, 0,

    OFFSET CLASSNAME,

    OFFSET TITL,

WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_GROUP + WS_TABSTOP,

    100,; X — координата левого верхнего угла

    100,; Y — координата левого верхнего угла

    400,; DX - ширина окна

    450,; DY — высота окна

    0, 0, HINST,0

CMP EAX, 0   ; проверка на ошибку

JZ END_LOOP

MOV HWND, EAX; дескриптор окна

 

INVOKE ShowWindow, HWND, SW_SHOWNORMAL; показать созданное окно

INVOKE UpdateWindow, HWND;перерисовать видимую часть окна

;-------------------------------------------------------------------

; цикл обработки сообщений

MSG_LOOP:

INVOKE GetMessage, OFFSET Message, 0,0,0

CMP EAX, 0

JE END_LOOP

INVOKE TranslateMessage, OFFSET Message

INVOKE DispatchMessageA, OFFSET Message

JMP MSG_LOOP

END_LOOP:

INVOKE ExitProcess, Message.wParam; выход из программы

START endp

; --------------------------------------------------

; процедура окна

WNDPROC PROC hW:DWORD, Mes:DWORD, wParam:DWORD, lParam:DWORD

CMP Mes, WM_DESTROY

JE WMDESTROY

CMP Mes, WM_CREATE

JE WMCREATE

CMP Mes, WM_COMMAND   

JE WMCOMMAND

CMP Mes, WM_PAINT     

JE WMPAINT

JMP DEFWNDPROC

;------------------------------------------------------------------

WMCREATE:                       ; создание окна

INVOKE CreateWindowExA, 0,; поле редактирования 1

     offset CLSEDT,       ;имя класса окна

     offset TEXTA,        ;надпись в поле

     WS_CHILD+WS_VISIBLE,;стиль окна

     10, 50,          ;x, y

     60, 20,          ;длина, ширина

     hW,              ;дескриптор окна

     0,               ;дескриптор меню

     HINST,           ;дескриптор приложения

     0                ;lpParam

    mov hedt1,eax; сохранение дескриптора

    mov eax,0

 INVOKE ShowWindow, hedt1, SW_SHOWNORMAL

 INVOKE CreateWindowExA, 0,; поле редактирования 2

     offset CLSEDT,       ;имя класса окна

     offset TEXTB,        ;надпись в поле

     WS_CHILD+WS_VISIBLE, ;стиль окна

     90, 50,          ;x, y

     60, 20,               ;длина, ширина

     hW,                  ;дескриптор окна

     0,                   ;дескриптор меню

     HINST,               ;дескриптор приложения

     0                    ;lpParam

    mov hedt2,eax    ; сохранение дескриптора

    mov eax,0

 INVOKE ShowWindow, hedt2, SW_SHOWNORMAL

 INVOKE CreateWindowExA, 0,; кнопка

     offset CLSBTN,       ;имя класса окна

     offset CPBUT,    ;надпись на кнопке

     WS_CHILD+WS_VISIBLE,;стиль окна кнопки

     10, 90,         ;x, y

     100, 20,    ;длина, ширина

     hW,              ;дескриптор окна

     0,              ;дескриптор меню

     HINST,          ;дескриптор приложения

     0               ;lpParam

    mov hBut,eax     ; сохранение дескриптора

    mov eax,0

 INVOKE ShowWindow, hBut, SW_SHOWNORMAL

MOV EAX, 0

JMP FINISH

;------------------------------------------------------------------

WMCOMMAND:        ; обработка нажатия кнопки

 mov eax, hBut

 cmp lParam,eax   

 jne COM_END ; команда не соответствует нажатию кнопки

 

INVOKE SendMessage, hedt1, WM_GETTEXT, 20, offset TEXTA

INVOKE SendMessage, hedt2, WM_GETTEXT, 20, offset TEXTB

 

INVOKE StrToInt, offset TEXTA

mov summa, eax

INVOKE StrToInt, offset TEXTB

add summa, eax

 

mov eax, sum_len  

INVOKE TextOutA,; стирание строки результата в окне

    hdc, 180, 50, offset mess2, eax

INVOKE IntToStr, summa, offset mess2+1

INVOKE LENSTR, offset mess2; определение длины результата

push eax

INVOKE TextOutA,; вывод результата

    hdc, 180, 50, offset mess2, eax

pop ecx      ; очистка строки

inc ecx

mov al,' '

mov edi, offset mess2+1

CLR: mov [edi],al

inc edi

loop CLR

COM_END:

 MOV EAX, 0

JMP FINISH

;------------------------------------------------------------------

WMPAINT:                   ; перерисовка окна

INVOKE BeginPaint, hW, offset ps

mov hdc,eax

INVOKE SetBkColor, hdc, RGBW

 

mov eax, mess1_len

INVOKE TextOutA, hdc, 10, 20, offset mess1, eax

INVOKE EndPaint, hdc, offset ps

MOV EAX, 0

JMP FINISH

;------------------------------------------------------------------

DEFWNDPROC:  ; обработка сообщения по умолчанию

INVOKE DefWindowProc,

hW, Mes, wParam, lParam

JMP FINISH

;------------------------------------------------------------------

WMDESTROY:   ; выход из цикла обработки сообщений

INVOKE PostQuitMessage, 0

MOV EAX, 0

FINISH: ret

WNDPROC ENDP

END START

В результате работы программы получим окно:

 Графика в оконных приложениях Windows

Система координат для вывода графических образов такая же, как и для ввода текстовой информации. Координаты измеряются в логических единицах, которые по умолчанию совпадают с пикселями. Начало отсчета – верхний левый угол окна.

Для создания графических образов используются 3 основных объекта: точка (пиксел), перо, кисть.

Цвет точки задается с помощью функции

COLORREF SetPixel(

HDC hdc,          // дескриптор контекста окна

int X,            // x-координата точки

int Y,            // y-координата точки

COLORREF crColor); // цвет точки

Перо используется для рисования линий и контуров замкнутых фигур. Цвет пера задается при помощи функции

HPEN CreatePen(

int fnPenStyle,     // стиль пера

// PS_SOLID =0 

// PS_DASH =1 

// PS_DOT =2 

// PS_DASHDOT =3 

// PS_DASHDOTDOT =4

// PS_NULL =5 невидимое перо

int nWidth,       // ширина пера

COLORREF crColor); // цвет пера

Кисть используется для закрашивания замкнутых объектов. Цвет кисти задается с помощью функции

HBRUSH CreateSolidBrush(COLORREF crColor); // цвет кисти

Можно заранее создать несколько кистей и перьев, а затем выбирать нужные с помощью функции

HGDIOBJ SelectObject(

HDC hdc,     // дескриптор контекста окна

HGDIOBJ hgdiobj); // дескриптор объекта

Обновление информации в окне программы происходит по получению сообщения WM_PAINT. В реальных программах вывод информации в окно может происходить по различным событиям и из различных процедур. Кроме того, если информации в окне много, то непосредственный вывод при помощи функции TextOut достаточно медленный. Чтобы воспроизводить содержимое окна, необходимо где-то запомнить это содержимое. Возникает проблема сохранения информации (и не только текстовой), находящейся в окне.

В операционной системе Windows образуется виртуальное окно, и весь вывод информации производится туда. Затем по приходе сообщения WM_PAINT содержимое виртуального окна копируется на реальное окно. В целом общая схема такова:

1. При создании окна

- создается совместимый контекст устройства функцией

HDC CreateCompatibleDC(HDC hdc); // дескриптор контекста окна

Полученный контекст следует запомнить.

- создается карта бит, совместимая с данн<



Поделиться:


Последнее изменение этой страницы: 2020-12-09; просмотров: 414; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.149.29.192 (0.011 с.)