FirstWindow

 
                                    .386  

                                    .model flat,stdcall           ;平坦模式,使用stdcall调用API.

                                    option casemap:none    ;对大小写是否敏感

;include 定义,保护那些头文件

include            windows.inc    ;头文件定义

include            kernel32.inc   ;系统服务功能

include            user32.inc      ;用户接口服务

include            gdi32.inc        ;图形设备借口

includelib         gdi32.lib

includelib        kernel32.lib

includelib        user32.lib

;数据段

                                    .data?

hInstance                 dd    ?      ;定义一个类型为dword名为hinstance的全局变量.

hWinMain                dd     ?      ;定义一个类型为dword名为hWinMain的全局变量.

                                   .const

szCaptionMain       db   'myfirstwindow',0      ;定义窗口属性为myfirstwindow

szClassName       db   'My Class',0                ;类名为My Class

szText                      db   'win32 Assembly',0  ;窗口内容为win32 Assembly.

                                  .code

_ProcWinMain   proc   uses ebx edi esi,hWnd,uMsg,wParam,lparam     ;定义_ProcWinMain子程序.保存ebx,edi,esi的值,uMsg参数,指定的消息有一定的范围,wParam,lparam参数是消息所附带的参数,它随消息的不同而不同,

local @stPs:PAINTSTRUCT                                                                             ;定义局部变量名为@stPs的PAINTSTRUCT绘制结构.

local @stRect:RECT                                                                                          ;定义局部变量名为@stRect的RECT结构.

local @hPc                                                                                                           ;定义局部变量为@hPc的环境句柄,默认类型为DWORD.

mov   eax,uMsg                                                                                                    ;保存uMsg消息类型,

.if    eax== WM_PAINT                                                                                        ;如果eax=绘制消息,

invoke Beginpaint,hWnd,addr @stPs                                                             ;那么调用Beginpaint函数,获取客户区的环境句炳

    Beginpaint 函数解析如下(从MSDN上查阅得知):

Return Value
If the function succeeds, the return value is the handle to a display device context for the specified window.

If the function fails, the return value is NULL, indicating that no display device context is available.

Remarks


An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.





mov   @hDc,eax                                                                                                  ;将eax的值保存在@hDc变量中.

invoke GetClientRect,hWnd,addr @stRect                                                    ;获取客户区的大小,

       GetClientRect函数解析如下(从MSDN上查阅得知):

Return Value
Type: BOOL

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError. 

Remarks
In conformance with conventions for the RECT structure, the bottom-right coordinates of the returned rectangle are exclusive. In other words, the pixel at (right, bottom) lies immediately outside the rectangle.



invoke DrawText,@hDc,offset szText,-1,addr @stRect,DT_SINGLEINE or DT_CENTER or DT_VCENTER  

         DrawText函数解析如下(从MSDN上查阅得知):

Return Value
If the function succeeds, the return value is the height of the text in logical units. If DT_VCENTER or DT_BOTTOM is specified, the return value is the offset from lpRect->top to the bottom of the drawn text

If the function fails, the return value is zero.

Remarks
The DrawText function uses the device context's selected font, text color, and background color to draw the text. Unless the DT_NOCLIP format is used, DrawText clips the text so that it does not appear outside the specified rectangle. Note that text with significant overhang may be clipped, for example, an initial "W" in the text string or text that is in italics. All formatting is assumed to have multiple lines unless the DT_SINGLELINE format is specified.

If the selected font is too large for the specified rectangle, the DrawText function does not attempt to substitute a smaller font.

The text alignment mode for the device context must include the TA_LEFT, TA_TOP, and TA_NOUPDATECP flags.







                                                                                                                                ;将字符串按照取得的大小居中写在客户区'环境中',第1个参数,环境句柄,第2个参数指向被写入字符串的指针,

                                                                                                                                ;第4个参数指向Rect结构,第5个参数,指定了格式化正文的方法,显示正文的同一行,回车和换行符都不能折行,使正文在矩形中水平居中,

invoke EndPaint,hWnd,addr @stPs                                                                ;结束绘画客户区

.elseif   eax==WM_CLOSE                                                                                ;如果eax等于消息关闭.

invoke DestroyWindow,hWinMain                                                                   ;调用DestroyWindow,摧毁窗口.

          DestroyWindow函数解析如下(从MSDN上查阅得知):

If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.

DestroyWindow also destroys modeless dialog boxes created by the CreateDialog function.

Remarks
A thread cannot use DestroyWindow to destroy a window created by a different thread. 

If the window being destroyed is a child window that does not have the WS_EX_NOPARENTNOTIFY style, a WM_PARENTNOTIFY message is sent to the parent.





invoke PostQuitMessage,NULL                                                                      ;调用PostQuitMessage函数,退出消息循环.

         PostQuitMessage函数解析如下(从MSDN上查阅得知):

Indicates to the system that a thread has made a request to terminate (quit). It is typically used in response to a WM_DESTROY message.

Remarks
The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future. 

When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. The exit value returned to the system must be the wParam parameter of the WM_QUIT message.



.else   

invoke DefWindowProc,hWnd,uMsg,wParam,lparam                                 ;该函数调用默认的窗口过程来为应用程序没有处理的任何窗口消息提供默认的处理。hWnd窗口句柄,uMsg信息结构,wParam,lparam指定消息特定的信息,(该参数的内容与Msg参数值有关)

      DefWindowProc函数解析如下(从MSDN上查阅得知):

    Calls the default window procedure to provide default processing for any window messages that an application does not process. This function ensures that every message is processed. DefWindowProc is called with the same parameters received by the window procedure.







ret   

.endif   

xor eax,eax

ret

_ProcWinMain    endp                                                                                         ;子程序结束

_WinMain proc                                                                                                     ;定义子程序名为_WinMain

local @stWndClass:WNDCLASSEx                                                                ;定义一个局部变量WNDCLASSEx数据结构.

local @stMsg:MSG                                                                                              ;定义一个局部变量MSG数据结构.

invoke GetModuleHandle,NULL                                                                       ;调用GetModuleHandle函数,(得到应用程序的句柄)

        GetModuleHandle函数解析如下(从MSDN上查阅得知):

Retrieves a module handle for the specified module. The module must have been loaded by the calling process.

To avoid the race conditions described in the Remarks section, use the GetModuleHandleEx function.

Remarks
The returned handle is not global or inheritable. It cannot be duplicated or used by another process.

If lpModuleName does not include a path and there is more than one loaded module with the same base name and extension, you cannot predict which module handle will be returned. To work around this problem, you could specify a path, use side-by-side assemblies, or use GetModuleHandleEx to specify a memory location rather than a DLL name. 

The GetModuleHandle function returns a handle to a mapped module without incrementing its reference count. However, if this handle is passed to the FreeLibrary function, the reference count of the mapped module will be decremented. Therefore, do not pass a handle returned by GetModuleHandle to the FreeLibrary function. Doing so can cause a DLL module to be unmapped prematurely.

This function must be used carefully in a multithreaded application. There is no guarantee that the module handle remains valid between the time this function returns the handle and the time it is used. For example, suppose that a thread retrieves a module handle, but before it uses the handle, a second thread frees the module. If the system loads another module, it could reuse the module handle that was recently freed. Therefore, the first thread would have a handle to a different module than the one intended.





mov hInstance,eax                                                                                              ;把返回的句柄保存到取名为hinstance的变量里.  

invoke RtlZeroMemory,addr @stWinClass,sizeof @stWndClass             ;用RtlZeroMemory填充为全0

          RtlZeroMemory函数解析如下(从MSDN上查阅得知):

The RtlZeroMemory routine fills a block of memory with zeros, given a pointer to the block and the length, in bytes, to be filled.



Remarks
To zero out a memory buffer to erase security-sensitive data, use RtlSecureZeroMemory instead.

Callers of RtlZeroMemory can be running at any IRQL if the Destination block is in nonpaged pool. Otherwise, the caller must be running at IRQL <= APC_LEVEL.



                                                                                                                                ;注册窗口类

invoke LoadCursor,0,IDC_ARROW                                                                 ;在窗体内用标准型光标.

       LoadCursor函数解析如下(从MSDN上查阅得知):

Loads the specified cursor resource from the executable (.EXE) file associated with an application instance.

Note  This function has been superseded by the LoadImage function.

Remarks
The LoadCursor function loads the cursor resource only if it has not been loaded; otherwise, it retrieves the handle to the existing resource. This function returns a valid cursor handle only if the lpCursorName parameter is a pointer to a cursor resource. If lpCursorName is a pointer to any type of resource other than a cursor (such as an icon), the return value is not NULL, even though it is not a valid cursor handle. 

The LoadCursor function searches the cursor resource most appropriate for the cursor for the current display device. The cursor resource can be a color or monochrome bitmap. 





mov @stWndClass.hCursor,eax                                                                     ;将LoadCursor函数返回值保存到WNDCLASSEx结构的Curosor里.

push hInstance                                                                                                   ;保存句柄   

pop   @stWndClass.hInstance                                                                        ;将@stWndClass.hInstance弹出堆栈.

mov @stWndClass.cbSize,sizeof WNDCLASSEX                                       ;将WNDCLASSEX的字节数赋值给stWndClass.cbsize

mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW                    ;窗口的风格,参数是高度和宽度.

mov @stWndClass.lpfnWndProc,offset _ProcWinMain                              ;获取窗口过程地址.

mov @stWndClass.hbrBackground,COLOR_WINDOW+1                        ;使用WINDOWS预定义的窗体颜色值,规定+1

mov @stWndClass.lpszClassName,offset szClassName                        ;获取MyClass字符串.(这个字段是一个字符串指针.

invoke RegisterClassEx, addr @stWndClass                                               ;调用RegisterClassEx函数,注册窗口.

      RegisterClassEx函数解析如下(从MSDN上查阅得知):

Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.

Remarks
If you register the window class by using RegisterClassExA, the application tells the system that the windows of the created class expect messages with text or character parameters to use the ANSI character set; if you register it by using RegisterClassExW, the application requests that the system pass text parameters of messages as Unicode. The IsWindowUnicode function enables applications to query the nature of each window. For more information on ANSI and Unicode functions, see Conventions for Function Prototypes.

All window classes that an application registers are unregistered when it terminates. 

No window classes registered by a DLL are unregistered when the DLL is unloaded. A DLL must explicitly unregister its classes when it is unloaded. 

                                                                                                                                 ;建立并显示窗口

invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\

WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL

   CreateWindowEx函数解析如下(从MSDN上查阅得知):

Creates an overlapped, pop-up, or child window with an extended window style; otherwise, this function is identical to the CreateWindow function. For more information about creating a window and for full descriptions of the other parameters of CreateWindowEx, see CreateWindow. 

Remarks
The CreateWindowEx function sends WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window being created. 

If the created window is a child window, its default position is at the bottom of the Z-order. If the created window is a top-level window, its default position is at the top of the Z-order (but beneath all topmost windows unless the created window is itself topmost).

For information on controlling whether the Taskbar displays a button for the created window, see Managing Taskbar Buttons. 

For information on removing a window, see the DestroyWindow function.

The following predefined control classes can be specified in the lpClassName parameter. Note the corresponding control styles you can use in the dwStyle parameter. 



                                                                                                                                 ;调用CreateWindowEx,建立窗口 定义了客户区使用立体边框,使用[my class]类建立窗口,使用窗口名称字符串(myfirstwindow),

                                                                                                                                 ;使用普通的重叠式窗口带窗口标题栏左上角的图标并且可以拖动调整大小的边框和有最大化,最小化的按钮,指定窗口最左角的位置,100,100 窗口的宽度是600,高度是400,无菜单,无父窗口,

mov hWinMain,eax                                                                                               ;将窗口句柄保存在hWinMain变量中.

invoke ShowWindow,hWinMain,SW_SHOWNORMAL                                 ;调用ShowWindow函数,显示窗口,参数是窗口句柄,显示并激活窗口,恢复正常大小(初始化的时候用这个参数)

     ShowWindow函数解析如下(从MSDN上查阅得知):

Remarks
To perform certain special effects when showing or hiding a window, use AnimateWindow. 

The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must use one of the values in the given list, instead of the one specified by the WinMain function's nCmdShow parameter. 

As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in the first call to ShowWindow if the program that launched the application specifies startup information in the structure. In this case, ShowWindow uses the information specified in the STARTUPINFO structure to show the window. On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup information provided by the program that launched the application. This behavior is designed for the following situations: 

Applications create their main window by calling CreateWindow with the WS_VISIBLE flag set. 
Applications create their main window by calling CreateWindow with the WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag set to make it visible.


invoke UpdateWindow,hWinMain                                                                     ;调用UpdateWindow函数,绘制客户区,

       UpdateWindow函数解析如下(从MSDN上查阅得知):

The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window, bypassing the application queue. If the update region is empty, no message is sent.



                                                                                                                                ;消息循环

.while TRUE  

invoke GetMessage,addr @stMsg,NULL,0,0                                                 ;调用GetMessage函数,获取消息,addr @stMsg表示指向1个MSG结构,NULL表示获取所有窗口的消息,0,0表示获取所有窗口的编号,

.break .if eax==0                                                                                                   ;终止循环.表示如果获取的消息是WM_QUIT eax的返回值=0,

invoke TranslateMessage,addr @stMsg                                                        ;调用TranslateMessage函数,将MSG结构传给WINDOWS进行一些键盘消息转换,转换为字符消息。字符消息被寄送到调用线程的消息队列里

                                                                                                                                 ;当下一次线程调用函数GetMessage或PeekMessage时被读出.

      TranslateMessage函数解析如下(从MSDN上查阅得知):

Translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue, to be read the next time the thread calls the GetMessage or PeekMessage function.

Remarks
The TranslateMessage function does not modify the message pointed to by the lpMsg parameter. 

WM_KEYDOWN and WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message. WM_SYSKEYDOWN and WM_SYSKEYUP combinations produce a WM_SYSCHAR or WM_SYSDEADCHAR message. 

TranslateMessage produces WM_CHAR messages only for keys that are mapped to ASCII characters by the keyboard driver. 

If applications process virtual-key messages for some other purpose, they should not call TranslateMessage. For instance, an application should not call TranslateMessage if the TranslateAccelerator function returns a nonzero value. Note that the application is responsible for retrieving and dispatching input messages to the dialog box. Most applications use the main message loop for this. However, to permit the user to move to and to select controls by using the keyboard, the application must call IsDialogMessage. For more information, see Dialog Box Keyboard Interface.





invoke DispatchMessage,addr @stMsg                                                         ;调用DispatchMessage函数,该函数的功能是该函数调度一个消息给窗口程序。

      DispatchMessage函数解析如下(从MSDN上查阅得知):

Dispatches a message to a window procedure. It is typically used to dispatch a message retrieved by the GetMessage function.



Remarks
The MSG structure must contain valid message values. If the lpmsg parameter points to a WM_TIMER message and the lParam parameter of the WM_TIMER message is not NULL, lParam points to a function that is called instead of the window procedure. 

Note that the application is responsible for retrieving and dispatching input messages to the dialog box. Most applications use the main message loop for this. However, to permit the user to move to and to select controls by using the keyboard, the application must call IsDialogMessage. For more information, see Dialog Box Keyboard Interface.





                                                                                                                                ;通常调度从GetMessage取得的消息.消息被调度到的窗口程序即是MainProc()函数.

                                                                                                                                ;(由DispatchMessage将消息发送到窗口对应的窗口过程去处理,窗口过程返回后,DispatchMessage才返回,开始下一轮的消息循环.

.endw

ret                                                                                                                          ;返回消息.

_WinMain endp

start:

call _WinMain                                                                                                      ;调用_WinMain子程序.

invoke ExitProcess,NULL                                                                                 ;退出

     ExitProcess函数解析如下(从MSDN上查阅得知):

Ends the calling process and all its threads

Remarks
Use the GetExitCodeProcess function to retrieve the process's exit value. Use the GetExitCodeThread function to retrieve a thread's exit value.

Exiting a process causes the following:

All of the threads in the process, except the calling thread, terminate their execution without receiving a DLL_THREAD_DETACH notification.
The states of all of the threads terminated in step 1 become signaled.
The entry-point functions of all loaded dynamic-link libraries (DLLs) are called with DLL_PROCESS_DETACH. 
After all attached DLLs have executed any process termination code, the ExitProcess function terminates the current process, including the calling thread.
The state of the calling thread becomes signaled.
All of the object handles opened by the process are closed.
The termination status of the process changes from STILL_ACTIVE to the exit value of the process.
The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate.
If one of the terminated threads in the process holds a lock and the DLL detach code in one of the loaded DLLs attempts to acquire the same lock, then calling ExitProcess results in a deadlock. In contrast, if a process terminates by calling TerminateProcess, the DLLs that the process is attached to are not notified of the process termination. Therefore, if you do not know the state of all threads in your process, it is better to call TerminateProcess than ExitProcess. Note that returning from the main function of an application results in a call to ExitProcess.

Calling ExitProcess in a DLL can lead to unexpected application or system errors. Be sure to call ExitProcess from a DLL only if you know which applications or system components will load the DLL and that it is safe to call ExitProcess in this context. 

Exiting a process does not cause child processes to be terminated.

Exiting a process does not necessarily remove the process object from the operating system. A process object is deleted when the last handle to the process is closed.


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值