Решил написать про программирование на асме под Win32.
И так сегодня в номере мы разберем создание окна и всё
Мы разберем простую программу, которая выводит только окно.
Я взял пример программы Wap32.asm из пакета TASM и несколько упростил ее.
.386
.model flat, stdcall
include win32.inc
extrn CreateWindowExA:PROC
extrn DefWindowProcA:PROC
extrn DispatchMessageA:PROC
extrn ExitProcess:PROC
extrn GetMessageA:PROC
extrn GetModuleHandleA:PROC
extrn LoadCursorA:PROC
extrn LoadIconA:PROC
extrn PostQuitMessage:PROC
extrn RegisterClassA:PROC
extrn ShowWindow:PROC
extrn TranslateMessage:PROC
extrn UpdateWindow:PROC
.data
newhwnd dd 0
msg MSGSTRUCT <?>
wc WNDCLASS <?>
hInst dd 0
szTitleName db 'Win32 Assembly Program',0
szClassName db 'ASMCLASS32',0
.code
start:
push 0
call GetModuleHandleA
mov [hInst], eax
mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
mov [wc.clsLpfnWndProc], offset WndProc
mov [wc.clsCbClsExtra], 0
mov [wc.clsCbWndExtra], 0
mov eax, [hInst]
mov [wc.clsHInstance], eax
push IDI_APPLICATION
push 0
call LoadIconA
mov [wc.clsHIcon], eax
push IDC_ARROW
push 0
call LoadCursorA
mov [wc.clsHCursor], eax
mov [wc.clsHbrBackground], COLOR_WINDOW + 1
mov dword ptr [wc.clsLpszMenuName], 0
mov dword ptr [wc.clsLpszClassName], offset szClassName
push offset wc
call RegisterClassA
push 0
push [hInst] ; дескриптор окна
push 0
push 0
push CW_USEDEFAULT ; высота
push CW_USEDEFAULT ; ширина
push CW_USEDEFAULT ; y
push CW_USEDEFAULT ; x
push WS_OVERLAPPEDWINDOW ; стиль
push offset szTitleName ; заголовок окна
push offset szClassName ; имя класса
push 0 ; дополнительный стиль
call CreateWindowExA
mov [newhwnd], eax
push SW_SHOWNORMAL
push [newhwnd]
call ShowWindow
push [newhwnd]
call UpdateWindow
msg_loop:
push 0
push 0
push 0
push offset msg
call GetMessageA
cmp ax, 0
je end_loop
push offset msg
call TranslateMessage
push offset msg
call DispatchMessageA
jmp msg_loop
end_loop:
push [msg.msWPARAM]
call ExitProcess
WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD,
wparam:DWORD, lparam:DWORD
cmp [wmsg], WM_DESTROY
je wmdestroy
push [lparam]
push [wparam]
push [wmsg]
push [hwnd]
call DefWindowProcA
jmp finish
wmdestroy:
push 0
call PostQuitMessage
mov eax, 0
finish:
ret
WndProc endp
ends
end start
Сегодня я напишу о работе с клавиатурой.
Как привило, у каждого компьютера есть только одна клавиатура, поэтому все запущенные Windows программы должны разделять её между всеми. Windows ответственна за то, чтобы отсылать информацию о нажатых клавишах активному в данный момент окну.
Хотя на экране может быть сразу несколько окон, только одно из них имеет фокус ввода, и только оно может получать сообщения от клавиатуры. Вы можете отличить окно, которое имеет фокус ввода от окна, которое его не имеет, посмотрев на его title bar - он будет подсвечен, в отличии от других.
В действительности, есть два типа сообщений от клавиатуры, зависящих от того, чем вы считаете клавиатуру. Вы можете считать ее набором кнопок. В этом случае, если вы нажмете кнопку, Windows пошлет сообщение WM_KEYDOWN активному окну, уведомляя о нажатии клавиши. Когда вы отпустите клавишу, Windows пошлет сообщение WM_KEYUP. Вы думаете о клавише как о кнопке. Другое взгляд на клавиатуру предполагает, что это устройство ввода символов. Тогда, Windows шлет сообщения WM_KEYDOWN или WM_KEYUP окну, в котором есть фокус ввода, и эти сообщения будут транслиpованы в сообщение WM_CHAR функцией TranslateMessage. Процедура окна может обрабатывать все три сообщения или только то, в котором оно заинтересовано. Большую часть времени вы можете игнорировать WM_KEYDOWN и WM_KEYUP, так как вызов функции TranslateMessage в цикле обработки сообщений транслирует сообщения WM_KEYDOWN и WM_KEYUP в WM_CHAR. Мы будем опираться именно на это сообщение в данном уроке.
.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
char WPARAM 20h ; the character the program
receives from keyboard
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc
hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc,0,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
char WPARAM 20h ; символ, который программа получает от клавиатуры
.ELSEIF uMsg==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
InvalidateRect proto hWnd:HWND, lpRect:DWORD, bErase:DWORD
invoke TextOut,hdc,0,0,ADDR char,1
Можешь про работу с реестром??? Создание, редактирование, сравнение ключей...
Написать про работу с реестром к сожалению не успею, т.к. сейчас сильно занят и инета лишусь с 07.08.04 на неопределенный срок
Однако завалялся у меня на винте файлик
Посмотри может что найдешь для себя.
Прикрепленные файлы
registry.zip ( 3.42 килобайт )
Кол-во скачиваний: 849
И так... начнем.
Эта статья посвящена некоторым приемам, позволяющим эффективно использовать графический интерфейс Windows.
Нет ничего проще, чем нарисовать что-либо в Windows. Это даже проще, чем использование библиотеки BGI от Borland для DOS. Особенно просто работать с графикой с помощью специальных классов, предлагаемых объектными библиотеками. И в то же время многие действительно мощные возможности остаются зачастую не использованными.
Начнем с примера (дурного). Допустим мы хотим вывести в клиентской части окна график функции sin(x). Вот участок кода для C++Builder, реализующий задачу:
void __fastcall TForm1::FormPaint(TObject *Sender)
{
Canvas -> MoveTo(10, 0);
Canvas -> LineTo(10, ClientHeight);
Canvas -> MoveTo(0, ClientHeight/2);
Canvas -> LineTo(ClientWidth, ClientHeight/2);
Canvas -> MoveTo(10, ClientHeight/2);
for (int i = 0; i < ClientWidth - 10; i += 2)
Canvas -> LineTo(i + 10, ClientHeight/2*sin(i*4*3.1416/ClientWidth) + ClientHeight/2 );
}
#define W 500
#define H 500
SetMapMode(hdc, MM_ANISOTROPIC);
SetWindowExtEx(hdc, W, H, 0);
SetViewportExtEx(hdc, ClientWidth, -ClientHeight, 0);
SetViewportOrgEx(hdc, 0, ClientHeight/2, 0);
MoveToEx(hdc, 0, -H/2, 0);
LineTo(hdc, 0, H/2);
MoveTo(hdc, 0, 0);
LineTo(hdc, W, 0);
MoveToEx(hdc, 0, 0, 0);
for (int i = 0; i < W; i += 2) LineTo(hdc, i, H/2*sin(i*4*3.1416/W));
#define W 500
#define H 500
HDC hPrint;
//Каким либо образом получаем дескриптор котекста принтера - например с помощью CreateDC или
//PrintDlg()
int pix_prn_x = GetDeviceCaps(hPrint, HORZRES );
int pix_prn_y = GetDeviceCaps(hPrint, VERTRES );
SetMapMode(hPrint, MM_ANISOTROPIC);
SetWindowExtEx(hPrint, W, H, 0);
SetViewportExtEx(hPrint, pix_prn_x, -pix_prn_y, 0);
SetViewportOrgEx(hPrint, 0, pix_prn_y/2, 0);
MoveToEx(hPrint, 0, -H/2, 0);
LineTo(hPrint, 0, H/2);
MoveToEx(hPrint, 0, 0, 0);
LineTo(hPrint, W, 0);
MoveToEx(hPrint, 0, 0, 0);
for (int i = 0; i < W; i += 2) LineTo(hPrint, i, H/2*sin(i*4*3.1416/W));
HDC hPrint;
//Каким либо образом получаем дескриптор контекста принтера - например с помощью CreateDC или
//PrintDlg()
int pix_prn_x = GetDeviceCaps(hPrint, HORZRES );
int pix_prn_y = GetDeviceCaps(hPrint, VERTRES );
int mm_prn_x = GetDeviceCaps(hPrint, HORZSIZE );
int mm_prn_y = GetDeviceCaps(hPrint, VERTSIZE );
int W = mm_prn_x*72/25.4;
int H = mm_prn_y*72/25.4;
HFONT hFont = CreateFont(14, 0, 0, 0, FW_MEDIUM , false, false, false,
DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HFONT hOldFont = SelectObject(hPrint, hFont);
SetMapMode(hPrint, MM_ANISOTROPIC);
SetWindowExtEx(hPrint, W, H, 0);
SetViewportExtEx(hPrint, pix_prn_x, pix_prn_y, 0);
SetViewportOrgEx(hPrint, 0, 0, 0);
TextOut(hPrint, 10, i*H/50 + 10, "1234567890 Проверка Test", 24);
SelectObject(hPrint, hOldFont);
DeleteObject(hFont);
HDC hdc;
//Каким либо образом получаем дескриптор контекста - BeginPaint, GetDC и.т.д
HFONT hFont = CreateFont(50, 20, 0, 0, FW_BOLD, false, false, false,
DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HFONT hOldFont = SelectObject(hdc, hFont);
SetBkMode(hdc, TRANSPARENT);
BeginPath(hdc);
TextOut(hdc, 100, 100, "FADE", 4);
EndPath(hdc);
SelectClipPath(hdc, RGN_COPY);
SIZE s;
GetTextExtentPoint32(hdc, "FADE", 4, &s);
HBRUSH hbr;
RECT R = {100, 0, 100 + s.cx, 0};
int clr = 0;
for (int i = 100; i < 100 + s.cy; i+= 2)
{
hbr = CreateSolidBrush( RGB(clr, clr, clr));
clr += 10;
R.top = i;
R.bottom = i + 2;
FillRect(hdc, &R, hbr);
DeleteObject(hbr);
}
SelectObject(hdc, hOldFont);
DeleteObject(hFont);
//Обязательно нужно освободить контекст EndPaint, ReleaseDC - смотря, как он был получен!
Хотя конечно интересный факт =) что на форуме паскаля в теме асм пишут на си :D :D
Но я не в обиде, так держать!
Сам могу добавить НЕ МОИ уроки, там МНОГО чего
К сожалению - тоже на СИ, на выжл си
Между прочим, мне не сложно переделать их на Дельфи. Надо???
Вот только темы которые там
01 - Первая программа Win32
02 - Контекст устройства
03 - Цветной текст
04 - Ввод с клавиатуры
05 - Ввод с клавиатуры часть 2
06 - Ввод с помощью мыши
07 - Ввод с помощью мыши часть 2
08 - Ввод мышью и цвет фона
09 - HPENs
10 - HBRUSHs
11 - Рисование контуров
12 - Полный экран
13 - Полный экран часть 2
14 - Горизонтальная прокрутка
15 - Установка значка
16 - Установка курсора
17 - Меню
18 - Меню часть 2
19 - Диалоговые окна
Я бы с интересом почитал:
06 - Ввод с помощью мыши
07 - Ввод с помощью мыши часть 2
08 - Ввод мышью и цвет фона
09 - HPENs
10 - HBRUSHs
11 - Рисование контуров
14 - Горизонтальная прокрутка
15 - Установка значка
16 - Установка курсора
17 - Меню
18 - Меню часть 2
Ну, а мне очень хочется про процессы, треды.... Побольше узнать. Я могу оформить по поиску адресов АПИшек (изъезженная тема), или поиск Кернела.
Так, народ - давайте поподробнее что кому надо =)
Можно и директ икс конечно. Вот только кому что интересно
[то, что просили выше - частично перевел, но тока щас я не дома]
Dark, по-моему тут асм многим imhо мало нужен. Я б про директ Х почитал бы. Потом бы пару примеров накодил (в случае, если то, что прочитаю будет информативно).
Direct X
это директ драв или сразу в 3D??
По моему эта тема уже может давно перейти из раздела асм в раздел виндовс программирование, но я не против того что она здесь.
Что-то давненько ничешо нету в моей теме...
Что же делать, что делать...
Ох как неохота писать...