WIN32汇编语言教程:第04章 第一个窗口程序 · 4.1 开始了解窗口(2)

先通过一个简单的例子来说明两种程序设计方式的不同,以DOS下的文件比较命令comp为例,程序运行时先提示输入第一个文件名,然后是输入第二个文件名,程序比较后退出,同时把结果输出在屏幕上。假如有一个窗口版的comp程序,那么运行时会在屏幕上出现一个对话框,上面有两个文本框用来输入两个文件名,还会有个“比较”按钮,按下后开始比较文件,用户可以随时按下“关闭”按钮来退出程序。

两种程序的运行会有相当大的不同,如图4.2所示,DOS程序必须按照顺序运行,当运行到输入第二个文件名时,用户不可能回到第一步修改第一个文件名,这时候用户也不能退出(除非用户强制用Ctrl+C键,但这不是程序的本意);而在窗口程序中用户可以随意选择先输入哪个文件名,同时也可以对窗口进行各种操作,当用户做任何一个操作的时候,相当于发出了一个消息,这些消息没有任何顺序关系,程序中必须随时准备处理不同的消息。


图4.2 不同的程序结构模式

这就决定了窗口程序必定在结构上和DOS程序有很大的不同,窗口程序实现大部分功能的代码应该呆在同一个模块——图中的“消息处理”模块中,这个模块可以随时应付所有类型的消息,只有这样才能随时响应用户的各种操作。

下面先来看一个地地道道的Win32汇编窗口程序。

2. FirstWindow源代码

读者可以在所带光盘的Chapter04\FirstWindow目录中找到源代码,目录里面有两个文件,它们是汇编源文件FirstWindow.asm和nmake工具使用的makefile,汇编源程序如下:

;※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
.586
.model flat,stdcall
option casemap:none
        include        windows.inc
        include        gdi32.inc
        includelib        gdi32.lib
        include        user32.inc
        includelib        user32.lib
        include        kernel32.inc
        includelib        kernel32.lib
.data?
        hInstance        dd        ?
        lpCmdLine        dd        ?
        hWinMain        dd        ?
.const
        szClassName        db        "Win32",0
        szCaptionMain        db        "窗口标题",0
        szText                db        "WIN32位汇编语言程序设计(窗口应用程序源码)",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 uses ebx edi esi,_hInstance,_hPrevInstance,_lpCmdLine,_nCmdShow
        local        @stWc:WNDCLASSEX
        local        @stMsg:MSG
        ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        ; 注册窗口类
        invoke        RtlZeroMemory,addr @stWc,sizeof WNDCLASSEX
        mov        @stWc.cbSize,sizeof WNDCLASSEX
        invoke        LoadCursor,0,IDC_ARROW
        mov        @stWc.hCursor,eax
        push        _hInstance
        pop        @stWc.hInstance
        mov        @stWc.style,CS_HREDRAW or CS_VREDRAW
        mov        @stWc.lpfnWndProc,offset ProcWinMain                ;窗口过程地址
        mov        @stWc.hbrBackground,COLOR_WINDOW + 1
        mov        @stWc.lpszClassName,offset szClassName
        invoke        RegisterClassEx,addr @stWc
        ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        ; 建立并显示窗口
        invoke        CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\
                WS_OVERLAPPEDWINDOW,100,100,480,320,NULL,NULL,hInstance,NULL
        mov        hWinMain,eax
        invoke        ShowWindow,hWinMain,_nCmdShow
        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:
        invoke        GetModuleHandle,NULL
        mov        hInstance,eax
        invoke        GetCommandLine
        mov        lpCmdLine,eax
        invoke        WinMain,hInstance,NULL,lpCmdLine,SW_SHOWNORMAL
        invoke        ExitProcess,NULL
        end        start
;※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

上页:第04章 第一个窗口程序 · 4.1 开始了解窗口(1) 下页:第04章 第一个窗口程序 · 4.1 开始了解窗口(3)

第04章 第一个窗口程序

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号