Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
uchebnik.docx
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
557.61 Кб
Скачать
  1. Приложения Приложение а

Пример простейшего приложения для ОС Windows на языке Visual С++ (разработан в среде Visual Studio 2008)

-----------------------------------------------------------

#include "stdafx.h"

LRESULT CALLBACK WndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam);

BOOL InitApplication (HINSTANCE hInstance);

BOOL InitInstance (HINSTANCE hInstance, int nCmdShow);

LPCSTR szClassName = "CLASS32";

LPCSTR szTitle = "Простейшее 32-х разрядное приложение на Visual C++ (Visual Studio 2008)";

int WINAPI WinMain (

HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

if (!hPrevInstance)

{

if (!InitApplication(hInstance))

return FALSE;

};

if (!InitInstance(hInstance,nCmdShow))

return FALSE;

MSG msg;

while (GetMessage(&msg,NULL,0,0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

};

typedef struct tagMSG

{

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

}

MSG;

return static_cast<int>(msg.wParam);

}

BOOL InitApplication (HINSTANCE hInstance)

{

WNDCLASS wc;

wc.style = CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS;

wc.lpfnWndProc = static_cast<WNDPROC>(WndProc);

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(NULL,IDI_EXCLAMATION);

wc.hCursor = LoadCursor(NULL,IDC_HAND);

wc.hbrBackground = reinterpret_cast<HBRUSH>(2);

wc.lpszMenuName = NULL;

wc.lpszClassName = szClassName;

return RegisterClass(&wc);

}

BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)

{

HWND hWnd;

hWnd = CreateWindowEx (

NULL,

szClassName,

szTitle,

WS_OVERLAPPEDWINDOW,

100,

100,

400,

400,

NULL,

NULL,

hInstance,

NULL);

if (!hWnd)

return(FALSE);

if (ShowWindow(hWnd,SW_SHOW))

return(FALSE);

if (!UpdateWindow(hWnd))

return (FALSE);

return TRUE;

}

LRESULT CALLBACK WndProc(

HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch (message)

{

case WM_LBUTTONDOWN:

MessageBox(NULL,"Нажата левая клавиша мыши","Сообщение",MB_OK);

break;

case WM_RBUTTONDOWN:

MessageBox(NULL,"Нажата правая клавиша мыши","Сообщение",MB_OK);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hwnd, message, wParam, lParam);

}

return 0;

}

----------------------------------------------------------------------------------

Пример простейшего приложения для ОС Windows на языке ассемблера (masm32) [4].

Строка программы

Комментарий

Директивы ассемблеру MASM32

.386P

Младшая модель процессора, поддерживающая представленные в программе команды

.MODEL FLAT, stdcall

Используемая модель памяти, формат передачи параметров в процедуры

Объявления констант

Константы, определяющие коды сообщений посылаемых операционной системой

ЗНАЧЕНИЯ КОНСТАНТ можно найти в заголовочном файле WINUSER.H

WM_DESTROY equ 2

Сообщение приходит при закрытии окна

WM_CREATE equ 1

Сообщение приходит при создании окна

WM_LBUTTONDOWN equ 201h

Код нажатия левой клавиши мыши

WM_RBUTTONDOWN equ 204h

Код нажатия правой клавиши мыши

Константы, определяющие свойства окна (подробное назначение констант можно найти в [Error: Reference source not found], значение констант определяется в заголовочном файле WinUser.h системы программирования Microsoft VisualStudio)

CS_VREDRAW equ 1h

CS_HREDRAW equ 2h

CS_GLOBALCLASS equ 4000h;

style equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

WS_OVERLAPPEDWINDOW equ 000080000H

IDI_EXCLAMATION equ 32515;

идентификатор иконки в заголовке окна

IDC_HAND equ 32649

идентификатор курсора

SW_SHOWNORMAL equ 1

режим показа окна (подробно см. [Error: Reference source not found]):

Прототипы внешних процедур из внешних библиотек, число после @ обозначает количество байт, передаваемых в качестве параметров, ВНИМАНИЕ: команда PUSH передает 2 или 4 байта. Более подробно описание API-функций – в тексте программы

EXTERN MessageBoxA@16: NEAR

Создает и отображает блок диалога, содержащий указанное сообщение и заголовок, а также пpедопpеделенные пиктограммы и текстовые кнопки

EXTERN CreateWindowExA@48:NEAR

Создает перекрытое, всплывающее или дочернее окно с расширенным стилем.

EXTERN DefWindowProcA@16:NEAR

Обеспечивает стандартную обработку сообщений для сообщений, которые явно не обрабатываются прикладной задачей.

EXTERN DispatchMessageA@4:NEAR

Передает сообщение оконной функции окна.

EXTERN ExitProcess@4:NEAR

Завершает процесс

EXTERN GetMessageA@16:NEAR

Считывает сообщение, из очереди сообщений прикладной задачи.

EXTERN GetModuleHandleA@4:NEAR

Считывает дескриптор модуля

EXTERN LoadCursorA@8:NEAR

Загружает указанный тип курсора

EXTERN LoadIconA@8:NEAR

Загружает указанный тип пиктограммы

EXTERN PostQuitMessage@4:NEAR

Направляет сообщение wm_Quit, обычно в ответ на сообщение wm_Destroy.

EXTERN RegisterClassA@4:NEAR

Регистрирует класс окна, атрибуты которого определены параметром WndClass, для последующего использования. Класс окна может регистрироваться только один раз

EXTERN ShowWindow@8:NEAR

Отображает или прячет окно образом, указанным параметром CmdShow

EXTERN TranslateMessage@4:NEAR

Пеpеводит комбинации wm_KeyDown/Up в wm_Char или wm_DeadChar и комбинации wm_SysKeyDown/Up в wm_SysChar или wm_SysDeadChar и направляет символьное сообщение в очередь прикладной задачи

EXTERN UpdateWindow@4:NEAR

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

Директивы компоновщику для подключения библиотек

includelib d:\masm32\lib\user32.lib

указывается путь до библиотек, содержащих стандартные функции

includelib d:\masm32\lib\kernel32.lib

Описания структур данных

Структура сообщения, посылаемого ОС приложениям

MSGSTRUCT STRUC

Начало описания структуры данных

MSHWND DD ?

переменная для хранения идентификатора окна, получающего сообщение

MSMESSAGE DD ?

идентификатор сообщения

MSWPARAM DD ?

доп. информация о сообщении

MSLPARAM DD ?

доп. информация о сообщении

MSTIME DD ?

время посылки сообщения

MSPT DD ?

положение курсора, во время посылки сообщения

MSGSTRUCT ENDS

Конец описания структуры данных

Структура данных, описывающая стиль окна

WNDCLASS STRUC

CLSSTYLE DD ?

стиль окна

CLWNDPROC DD ?

указатель на процедуру окна

CLSCSEXTRA DD ?

информация о доп. байтах для данной структуры

CLWNDEXTRA DD ?

информация о доп. байтах для окна

CLSHINSTANCE DD ?

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

CLSHICON DD ?

идентификатор иконы окна

CLSHCURSOR DD ?

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

CLBKGROUND DD ?

идентификатор кисти окна

CLMENUNAME DD ?

имя-идентификатор меню

CLNAME DD ?

специфицирует имя класса окон

WNDCLASS ENDS

Сегмент данных

_DATA SEGMENT DWORD PUBLIC USE32 'DATA'

объявление начала сегмента данных

NEWHWND DD 0 ;

переменная для хранения дескриптора созданного окна

MSG MSGSTRUCT <?> ;

переменная для хранения сообщения

WC WNDCLASS <?>;

переменная для описания окна

HINST DD 0 ;

переменная для хранения дескриптора приложения

TITLENAME DB 'Простейшее 32-битное приложение на Assembler',0

Строка для заголовка окна

CLASSNAME DB 'CLASS32',0;

класс приложения - 32х разрядное

CAP DB 'Сообщение',0;

заголовок окна с сообщением о нажатой клавише

LBUTTON_Text DB 'Нажата левая клавиша',0;

Сообщение о нажатой клавише

RBUTTON_Text DB 'Нажата правая клавиша',0;

Сообщение о нажатой клавише

_DATA ENDS

объявление конца сегмента данных

Сегмент кода

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'

объявление начала сегмента

START:

точка входа в программу

Инициализация приложения:

PUSH 0

CALL GetModuleHandleA@4

MOV [HINST], EAX

получение дескриптора приложения с помощью API функции GetModuleHandle. Предварительно в стек записывается указатель на имя модуля (строку, заканчивающуюся 0). Дескриптор приложения формируется ОС и возвращается приложению через регистр EAX.

Регистрация класса окна приложения

REG_CLASS:

заполнить структуру для описания окна:

MOV [WC.CLSSTYLE], style

переменная WC типа WNDCLASS

MOV [WC.CLWNDPROC], OFFSET WNDPROC ;

определяется адрес процедуры обработки сообщений WNDPROC

MOV [WC.CLSCSEXTRA], 0

MOV [WC.CLWNDEXTRA], 0

MOV EAX, [HINST]

MOV [WC.CLSHINSTANCE], EAX

Сохраняется дескриптор приложения

Создание иконки окна

PUSH IDI_APPLICATION

В стек передается строка или имя целочисленного идентификатора или пиктограммы, определенной одной из констант IDI_.

PUSH 0

В стек передается 0, т.к. используется предопределенная пиктограмма (в противном случае передается дескриптор экземпляра модуля, исполнимый файл которого содержит пиктограмму)

CALL LoadIconA@8

Вызов API-функции LoadIcon

MOV [WC.CLSHICON], EAX

В переменную загружается идентификатор пиктограммы

Создание курсора окна

PUSH IDC_CROSS

В стек передается строка или имя целочисленного идентификатора или курсор, определенный одной из констант IDI_.

PUSH 0

В стек передается 0, т.к. используется предопределенный курсор

CALL LoadCursorA@8

Вызов API-функции LoadCursor

MOV [WC.CLSHCURSOR], EAX

В переменную загружается идентификатор курсора

MOV [WC.CLBKGROUND], 2

определяется цвет окна. Например, 0 - белый, 1 - серый (форма), 2 - голубой, 3 - синий, 4 - серый, 7 – черный и т.п.

MOV DWORD PTR [WC.CLMENUNAME], 0;

имя-идентификатор меню

MOV DWORD PTR [WC.CLNAME], OFFSET CLASSNAME;

имя класса

PUSH OFFSET WC

сохраняется адрес самой переменной WC

CALL RegisterClassA@4

Вызов API функции регистрации класса окна

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

PUSH 0

Значение, переданное в TCreateStruct в параметре lParam сообщения wm_Create. Для создания дочернего окна MDI должно быть указателем на структуру TClientCreateStruct.

PUSH [HINST]

Дескриптор модуля

PUSH 0

Идентификатор меню или дочернего окна. Поскольку нет – 0

PUSH 0

Окно владельца (родительского приложения)

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

PUSH 400

DY — высота окна, переменные типа DD

PUSH 400

DX - ширина окна

PUSH 100

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

PUSH 100

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

PUSH WS_OVERLAPPEDWINDOW

формат окна (см. раздел определения констант)

PUSH OFFSET TITLENAME

имя окна

PUSH OFFSET CLASSNAME

имя класса

PUSH 0

идентификатор одного из расширенных стилей окна (0 – по умолчанию)

CALL CreateWindowExA@48

Вызов API функции создания окна

CMP EAX, 0

JZ _ERR

проверка на ошибку, если после выполнения API-функции возвращен 0, значит была какая-то ошибка

MOV [NEWHWND], EAX

сохраняется дескриптор окна

Показ созданного окна

PUSH SW_SHOWNORMAL

константа, определяющая формат отображения окна

PUSH [NEWHWND]

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

CALL ShowWindow@8;

показать созданное окно

Перерисовка окна

PUSH [NEWHWND]

Загружается дескриптор обновляемого окна

CALL UpdateWindow@4

API функция для обновления (перерисовки) видимой части окна

Цикл (петля) обработки сообщений

MSG_LOOP:

метка начала цикла

PUSH 0

0 , поскольку не используется фильтрация сообщений (от клавиатуры или от мыши). Максимальное значение диапазона фильтрации

PUSH 0

0 , поскольку не используется фильтрация сообщений (от клавиатуры или от мыши). Минимальное значение диапазона фильтрации

PUSH 0

0, поскольку для всех окон в прикладной задаче или дескриптор окна назначения сообщений

PUSH OFFSET MSG

адрес переменной, хранящей сообщения

CALL GetMessageA@16

API функция считывает сообщение, в рамках диапазона фильтрации, из очереди сообщений прикладной задачи

CMP EAX, 0

0 – если выход, в противном случае какое-то иное сообщение

JE END_LOOP

переход если равно 0

PUSH OFFSET MSG

Загружается в стек адрес переменной, хранящей сообщения

CALL TranslateMessage@4

Перевод комбинации в символьные сообщения и направляет их в очередь прикладной задачи

PUSH OFFSET MSG

Загружается в стек адрес переменной, хранящей сообщения

CALL DispatchMessageA@4

Передает в Msg сообщение оконной функции окна.

JMP MSG_LOOP

возврат на начало цикла

END_LOOP:

метка конца цикла

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

PUSH [MSG.MSWPARAM]

CALL ExitProcess@4

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

_ERR:

метка, для перехода по ошибке

JMP END_LOOP

переход на конец цикла

Можно было сразу по ошибке переходить на конец цикла, однако по метке _ERR можно вставить процедуру обработки ошибок

Процедура окна

Расположение параметров в стеке:

[EBP+014H] – LPARAM

[EBP+10H] – WAPARAM

[EBP+0CH] – MES

[EBP+08H] – HWND

WNDPROC PROC

объявление оконной процедуры

PUSH EBP

MOV EBP, ESP

инициализация указателя стека

PUSH EBX

PUSH ESI

PUSH EDI

сохранение регистров

Обработка сообщений

CMP DWORD PTR [EBP+0CH], WM_DESTROY

если пришло сообщение на закрытие окна

JE WMDESTROY;

переход на закрытие окна

CMP DWORD PTR [EBP+0CH], WM_CREATE

если пришло сообщение на создание окна

JE WMCREATE;

переход на создание окна

CMP DWORD PTR [EBP+0CH] ,WM_LBUTTONDOWN

Если нажата левая кнопка

JE LBUTTON;

переход на обработку нажатия левой клавиши мыши

CMP DWORD PTR [EBP+0CH] ,WM_RBUTTONDOWN

Если нажата правая кнопка

JE RBUTTON;

переход на обработку нажатия правой клавиши мыши

JMP DEFWNDPROC;

переход на вызов API-функции, возвращающей сообщение обратно ОС

Вывод сообщения по нажатию левой кнопки мыши

LBUTTON:

PUSH 00000000h ;

загружается тип окна (с кнопкой «Ок»)

PUSH OFFSET CAP

адрес заголовка окна с сообщением

PUSH OFFSET LBUTTON_Text

адрес выводимого сообщения

PUSH DWORD PTR [EBP+08H]

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

CALL MessageBoxA@16

API функция вывода окна сообщения

MOV EAX, 0

Загружается код выхода

JMP FINISH

Переход на конец оконной процедуры

Вывод сообщения по нажатию правой кнопки мыши

RBUTTON:

PUSH 00000000h

загружается тип окна (с кнопкой «Ок»)

PUSH OFFSET CAP

адрес заголовка окна с сообщением

PUSH OFFSET RBUTTON_Text

адрес выводимого сообщения

PUSH DWORD PTR [EBP+08H]

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

CALL MessageBoxA@16

API функция вывода окна сообщения

MOV EAX, 0

Загружается код выхода

JMP FINISH

Переход на конец оконной процедуры

WMCREATE:

метка перехода на создание окна

MOV EAX, 0

поскольку окно уже создано

JMP FINISH

переход на конец

DEFWNDPROC:

метка перехода на вызов API-функции, возвращающей сообщение обратно ОС

PUSH DWORD PTR [EBP+14H]

PUSH DWORD PTR [EBP+10H]

PUSH DWORD PTR [EBP+0CH]

PUSH DWORD PTR [EBP+08H]

загружаются параметры текущей задачи

CALL DefWindowProcA@16

вызов API функции

JMP FINISH

переход на конец

WMDESTROY:

метка закрытия окна

PUSH 0

код выхода приложения, без ошибок – 0

CALL PostQuitMessage@4

вызов функции посылки сообщения об окончании работы

MOV EAX, 0

FINISH:

POP EDI

POP ESI

POP EBX

POP EBP

восстановление значений регистров

RET 16

возврат из процедуры с освобождением 16 байт

WNDPROC ENDP

конец оконной процедуры

_TEXT ENDS

конец сегмента

END START

конец программы

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]