win32汇编--第一个窗体程序

窗口创建过程  
 

GetModuleHandle->RtlZeroMemory->LoadCursor->RegisterClassEx->CreateWindowsEx->ShowWindow->UpdateWindow

获得模块句柄->结构体初始化(填0)->加载光标->注册窗体类->创建窗体->显示窗体->更新客户区

win32API函数定义

GetModuleHandle,lpModuleName

参数:lpModuleName参数是一个指向含有模块名称字符串的指针;

功能: 是返回指定模块名的句柄,如果为NULL,则返回本模块的句柄。

RtlZeroMemory,lpDestination,bLength

参数:

lpDestination指向一块准备用0来填充的内存区域的开始地址。

bLength准备用0来填充的内存区域的大小,按字节来计算。

RtlZeroMemory只是将指定的内存块清零。

功能:使用结构前清零,而不让结构的成员数值具有不确定性,是一个好的编程习惯。

LoadCursor,hlnstance,LpCursorName

参数:

hlnstance  标识一个模块事例,它的可执行文件包含要载入的光标。

LpCursorName

指向以NULL结束的字符串的指针,该字符串存有等载入的光标资源名。该参数低位字节和高位字节0组成资源标识器也可以由低位字为资源标识符和高位字为零组成。也可以用MAKEINTRESOURCE宏命令创建该值。要使用Win32预定义的一个光标,应用程序必须把hlnstance参数设为NULL。

功能:该函数从一个与应用事例相关的可执行文件(EXE文件)中载入指定的光标资源。该函数已被Loadlmage函数替代。

RegisterClassEx,Ipwcx

参数:

Ipwcx

指向一个WNDCLASSEX结构的指针。在传递给这个函数之前,必须在结构内填充适当的类的属性返回值:如果函数成功,返回这个窗口类型的标识号;如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。

功能:该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类。

WNDCLASSEX      STRUCT

cbSize                   DWORD    ?               ;  结构的字节数

style                      DWORD    ?               ;  类风格

lpfnWndProc       DWORD    ?               ;  窗口过程的地址

cbClsExtra            DWORD    ?

cbWndExtra         DWORD    ?

hInstance             DWORD    ?              ;所属的实例句柄

hIcon                    DWORD    ?             ;窗口图标

hCursor                DWORD    ?             ; 窗口光标

hbrBackground   DWORD    ?             ;背景色

lpszMenuName   DWORD   ?             ;窗口菜单

lpszClassName     DWORD   ?             ;类名字符串的地址

hIconSm              DWORD   ?              ;小图标

WNDCLASSEX      ENDS

CreateWindowsEx,DWORDdwExStyle,\     ;窗口的扩展风格

LPCTSTRlpClassName,\                               ;指向注册类名的指针

LPCTSTRlpWindowName,\                         ;指向窗口名称的指针

DWORDdwStyle,\                                        ;窗口风格

intx,\                                                             ;窗口的水平位置

inty,\                                                             ;窗口的垂直位置

intnWidth,\                                                  ;窗口的宽度

intnHeight,\                                                 ;窗口的高度

HWNDhWndParent,\                                  ;父窗口的句柄

HMENUhMenu,\                                         ;菜单的句柄或是子窗口的标识符

HINSTANCEhInstance,\                              ;应用程序实例的句柄

LPVOIDlpParam                                          ;指向窗口的创建数据

功能: 该函数创建一个具有扩展风格的层叠式窗口、弹出式窗口或子窗口,其他与CreateWindow函数相同。

ShowWindow,hWnd,nCmdShow

参数:

hWnd:指窗口句柄。

nCmdShow:指定窗口如何显示。如果发送应用程序的程序提供了STARTUPINFO结构,则应用程序第一次调用ShowWindow时该参数被忽略。否则,在第一次调用ShowWindow函数时,该值应为在函数WinMain中nCmdShow参数。

功能:该函数设置指定窗口的显示状态

如果窗口之前可见,则返回值为非零。如果窗口之前被隐藏,则返回值为零。

UpdateWindow,hWnd 

参数:

hwnd 要更新的窗口句柄

功能:如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定窗口的客户区。函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。

如果函数调用成功,返回值为非零值。如果函数调用不成功,返回值为零。

消息循环    GetMessage->TranslateMessage->DispatchMessage

从消息队列中获得一条消息->根据键盘按键的扫描码转换为ASCLL值->分发消息给USER.DLL,USER.DLL调用窗体过程处理消息

GetMessage,lpMsg,hWnd,wMsgFilterMin,wMsgFilterMax

参数:

lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息。

hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。

wMsgFilterMin:指定被检索的最小消息值的整数。

wMsgFilterMax:指定被检索的最大消息值的整数。

功能: 函数GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMesssge寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。

返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多的错误信息,请调用GetLastError函数。

TranslateMessage,lpMsg

参数:IpMsg   指向含有消息的MSG结构的指针,该结构里含有用函数GetMessage或PeekMessage从调用线程的消息队列里取得的消息信息。

函数功能:该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。

返回值:如果消息被转换(即,字符消息被寄送到调用线程的消息队列里),返回非零值。如果消息是WM_KEYDOWN,WM_KEYUP
WM_SYSKEYDOWN或WM_SYSKEYUP,返回非零值,不考虑转换。如果消息没被转换(即,字符消息没被寄送到调用线程的消息队列里),返回值是零。

DispatchMessage,lpmsg

参数:lpmsg   指向含有消息的MSG结构的指针。

功能:  该函数分发一个消息给窗口程序。通常消息从GetMessage函数获得。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息

返回值:返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。

窗口过程    BeginPaint->GetClientRect->DrawText->EndPaint

进行窗口绘制工作->获得窗体客户区->写入文本->结束绘制

BeginPaint,hwnd,lpPaint

hwnd:[输入]被重绘的窗口句柄

lpPaint:[输出]指向一个用来接收绘画信息的PAINTSTRUCT结构

功能:BeginPaint函数为指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到一个

PAINTSTRUCT结构中。

如果函数成功,返回值是指定窗口的“显示设备描述表”句柄。如果函数失败,返回值是NULL,表明没有得到显示设备的内容。

GetClientRect,hWnd,lpRect

参数:

hWnd:是程序窗口的句柄。

lpRect:是一个指针,指向一个RECT类型的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。

GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0。right和bottom字段设定为显示区域的宽度和高度(像素点数)。 也可以是一个CRect对象指针。CRect对象有多个参数,与RECT用法相同。

功能: 该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)。这里应该注意一下:坐标包含两种:屏幕坐标与客户区坐标。严格区分这两种坐标对于理解Windows编程是很重要的。

作用总的来说就是把客户区的大小写进第二个参数所指的Rect结构当中。

DrawText,hDC,lpString,nCount,lpRect,uFormat 

hdc:[输入]设备环境句柄。

lpString:[输入]指向将被写入的字符串的指针,如果参数nCount是-1,则字符串必须是以\0结束的。 如果uFormat包含DT_MODIFYSTRING,则函数可为此字符串增加4个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符。

nCount:[输入]指向字符串中的字符数。如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,DrawText会自动计算字符数。

lpRect:[输入/输出]指向结构RECT的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标)。

uFormat:[输入]指定格式化文本的方法。

功能:该函数的功能是在指定的矩形里写入格式化文本,根据指定的方法对文本格式化(扩展的制表符,字符对齐、折行等)

要指定额外的格式化选项,请使用DrawTextEx函数。

返回: 如果函数调用成功,返回值是正文的高度(逻辑单位)。如果指定了DT_VCENTER或DT_BOTTOM,返回值是lpRect->top到绘制的正文的底部的偏移值。如果函数调用失败,返回值是0

EndPaint,hWnd,lpPaint

hWnd:[输入]已经被重画的窗口的HANDLE

lpPaint:[输入]指向一个PAINTSTRUCT结构,该结构包含了绘画信息,是BeginPaint函数返回的返回值:

返回值:返回值始终是非0

功能:EndPaint函数标记指定窗口的绘画过程结束;这个函数在每次调用BeginPaint函数之后被请求,但仅仅在绘画完成以后。

PAINTSTRUCT 结构体包含了用于绘制窗口客户区的信息。

PAINTSTRUCT  STRUCT

hdc                    DWORD        ?                      ; 用于绘制的句柄

fErase                DWORD        ?                      ;如果为非零值则擦除背景,否则不擦除背景

rcPaint              DWORD        ?                       ;通过制定左上角和右下角的坐标确定一个要绘制的矩形范围,该矩形单位相对于客户区左上角。

fRestore            DWORD        ?                       ;后面三个参数都是系统预留的,编程一般用不到。

fIncUpdate       DWORD        ?

rgbReserved     DWORD        ?

PAINTSTRUCT  ENDS

完整的程序Fwindow.asm

				.386
                .model flat,stdcall
                option casemap:none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 文件定义

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include         windows.inc
include         gdi32.inc
includelib      gdi32.lib
include         user32.inc
includelib      user32.lib
include         kernel32.inc
includelib      kernel32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .data?
hInstance       dd      ?
hWinMain        dd      ?

                .const
szClassName     db      'MyClass',0
szCaptionMain   db      'My first Window!',0
szText          db      'Win32 Assembly, Simple and powerful!',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain    proc uses ebx edi esi, hWnd, uMsg, wParam, lParam
                local @stPs:PAINTSTRUCT
                local @stRect:RECT
                local @hDc
                mov eax,uMsg
;*************************************************************************
                .if     eax == WM_PAINT
                        invoke     BeginPaint,hWnd,addr @stPs
                        mov     @hDc,eax
                        invoke GetClientRect,hWnd,addr @stRect
                        invoke    DrawText,@hDc,addr szText,-1,                                 addr @stRect,                                 DT_SINGLELINE or DT_CENTER or DT_VCENTER
                        invoke     EndPaint, hWnd, addr @stPs
;***************************************************************************
                .elseif eax == WM_CLOSE
                        invoke     DestroyWindow,hWinMain
                        invoke     PostQuitMessage,NULL
;***************************************************************************
                .else
                        invoke     DefWindowProc,hWnd,uMsg,wParam,lParam
                        ret
                .endif
;***************************************************************************
                xor     eax,eax
                ret
_ProcWinMain    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain        proc
                local   @stWndClass:WNDCLASSEX
                local   @stMsg:MSG
                invoke     GetModuleHandle,NULL
                mov     hInstance,eax
                invoke     RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;**************************************************************************
; 注册窗口类
;**************************************************************************
                invoke     LoadCursor,0,IDC_ARROW
                mov     @stWndClass.hCursor,eax
                push    hInstance
                pop     @stWndClass.hInstance
                mov     @stWndClass.cbSize, sizeof WNDCLASSEX
                mov     @stWndClass.style, CS_HREDRAW or CS_VREDRAW
                mov     @stWndClass.lpfnWndProc, offset _ProcWinMain
                mov     @stWndClass.hbrBackground,COLOR_WINDOW + 1
                mov     @stWndClass.lpszClassName, offset szClassName
                invoke     RegisterClassEx, addr @stWndClass
;***************************************************************************
; 建立并显示窗口
;***************************************************************************
                invoke     CreateWindowEx, WS_EX_CLIENTEDGE,                         offset szClassName, offset szCaptionMain,                         WS_OVERLAPPEDWINDOW,                         100, 100, 600, 400,                         NULL, NULL, hInstance, NULL
                mov     hWinMain,eax
                invoke     ShowWindow,hWinMain,SW_SHOWNORMAL
                invoke     UpdateWindow,hWinMain
;**************************************************************************
; 消息循环
;**************************************************************************
                .while TRUE
                        invoke     GetMessage, addr @stMsg, NULL, 0, 0
                        .break     .if eax == 0
                        invoke     TranslateMessage, addr @stMsg
                        invoke     DispatchMessage, addr @stMsg
                .endw
                ret
_WinMain        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
                call    _WinMain
                invoke ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                end start

时间: 2024-10-11 13:08:23

win32汇编--第一个窗体程序的相关文章

【win32汇编】0x04 第一个窗口程序

第一个win32汇编窗口程序,主要来自 win32汇编语言程序设计,然后加上了自己查阅msdn文档的一些理解,基本过程: start入口地址 --> _WinMain主函数 --> 定义一些需要用的消息实体和类实体 --> 注册窗口类 --> 建立并显示窗口 --> 消息循环 ( _ProcMain主要用于处理程序接受的消息 ) 1 ;模式定义 2 ;>>>>>>>>>>>>>>>>

win32汇编实现一个简单的TCP服务端程序(WinSock的简单认知应用)

Windows网络编程,相信好多人都知道,但是我们一般都是用其他语言编写,例如C,C++,JAVA,python等等,这些语言都可以,但是汇编语言比较底层,利用它,我们可以更清晰的了解到网络编程的内在部分,这是其他语言不能相比的,好了,废话不多说,这其实就是这次的目的(毕竟水平欠缺,还是先来按照罗云斌老师的WIN32汇编书上的例子加以学习,举一反三吧). 说道网络编程,现在我所接触到的程序开发,工具软件的使用,库等等都是基于Windows平台的,想要了解Windows的网络编程就必须要知道Win

win32汇编实现阶乘和斐波那契数列

win32阶乘程序 .486 ;使用486处理器.model flat,stdcall include \masm32\include\msvcrt.inc includelib \masm32\lib\msvcrt.lib .data result0 dd 1;存储最终结果 inputdata dd ?;输入的阶乘的最大值 type0 db '%d',0 data4 db '请输入阶乘最大值ddddd: ',0 data1 db '请输入阶乘最大值: ',0 data2 db '阶乘结果为:

VS2008下C++窗体程序显示控制台的方法

老蔡写了一个基于QT的窗体程序,而过去写的类的调试信息都是用cout显示的,苦于窗体程序无法显示cout信息很多信息都看不到,于是就想到让控制台和窗体同时显示.显示控制台方法如下 1.项目(或者叫“工程”,或者project) 2.连接器(linker) 3.系统(system) 4.将第一项选成控制台(Console).不过务必要记得选择控制台前是在什么选项上,等调试结束后选回去,不然程序编译出来,就带着那个黑框框的控制台了. 打完收工.希望调试C++看不到控制台的天使们看到这篇文章后不再继续

PyQt5创建第一个窗体(正规套路)

一.Pyqt5 创建第一个窗体 很多人写窗体程序都是直接敲代码,不使用设计器,我个人不是很赞成这种做法.使用设计器的好处是直观.维护方便,尤其开发复杂窗体的效率高. 但是每次修改ui文件后,需要重新生成py文件,会将原来的内容覆盖掉,为了避免这种情况,引入了一个中间类.主要步骤如下: 1使用QtDesigner创建一个简单的对话框,保存成simpleDialog.ui. 2使用cmd,进入simpleDialog.ui文件所在的目录,运行命令pyuic5 simpleDialog.ui >ui_

谈Win32汇编

最近接触到Win32汇编,才知道汇编必须是和平台相关的,如做应用则和操作系统和CPU类型相关,而做操作系统就和只和的CPU类型有关.对于<微机原理>里面的汇编,那是DOS汇编,而Win32汇编是基于Windows的汇编.DOS和Windows是两个完全不同的操作系统了. DOS汇编功能的实现依靠的是DOS系统提供的软中断,DOS程序是面向过程的单任务的:而Win32汇编功能的实现依靠的是WinAPI,基本的元素是与具体CPU类型有关的汇编指令(一般都是X86啦,因为微软就支持这个~~).然后记

【win32汇编】0x01 开篇一些乱七八糟的话

之前弄完了16位汇编,现在正式学习win32汇编,首先就是一些原理了,其实就是在16位的基础上增加了一些内容,其程序主要的结构记录如下 (1)指令集    .386     这是指定指令集 必须工作在80386的处理器上    mov cr0,eax    这类指令在特权级0上运行,编译到这个就报错    如果要写VxD等驱动程序,中间要用到特权指令.必须定义.386p    但是在正常情况只要.386就可以了,这个是运行在特权级3上面的    Pentium MMX中增加了mmx指令     

第一章 Windows程序内部运行机制(4)WinMain函数

WinMain函数相当于main函数,作为Windows程序的入口函数.当WinMain结束或返回时,Windows程序结束. 一个win32应用程序,该程序创建一个窗口并在窗口中响应键盘与鼠标消息,程序的实现步骤为: 1.WinMain函数的定义:2.创建一个窗口:3.进行消息循环:4.编写窗口过程 WinMain函数的定义: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, in

Win32汇编基础1

1.关于寄存器Windows 在内部频繁使用 ESI,EDI,EBP,EBX 寄存器,而且并不去检测这些寄存器的值是否被更改,所以如果要使用这些寄存器时必须先保存它们的值,待用完后再恢复它们 eax 是WIN32 API 默认的返回值存放处.ecx 是LOOP指令自动减一的寄存器,也就是一半用来计数,比如使用rep指令时,也是比较CX的值.esp 是堆栈指针,指向栈顶.ebp 经常用来在堆栈中寻址.esi 好像常常用在指针寻址中. edi 是目的地址寄存器. 2.关于堆栈 Windows为每个程