⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 见招拆招《windows程序设计》(二) .txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 5 页
字号:
见招拆招《Windows程序设计》(二) 
    作者:Zoologist 于2007-10-15上传   

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

窗口和消息

    在前一章,程序使用函数MessageBox来向使用者输出文字。MessageBox函数会建立一个「窗口」。在Windows中,「窗口」一词有确切的含义。一个窗口就是屏幕上的一个矩形区域,它接收使用者的输入并以文字或图形的格式显示输出内容。
    MessageBox函数建立一个窗口,但这只是一个功能有限的特殊窗口。消息窗口有一个带关闭按钮的标题列、一个选项图标、一行或多行文字,以及最多四个按钮。当然,必须选择Windows提供给您的图标与按钮。
    MessageBox函数非常有用,但下面不会过多地使用它。我们不能在消息框中显示图形,而且也不能在消息框中添加菜单。要添加这些对象,就需要建立自己的窗口,现在就开始。


自己的窗口
    
    建立窗口很简单,只需调用CreateWindow函数即可。我们在MSDN上可以找到这个函数的原形:
    
    HWND CreateWindow(      
        LPCTSTR lpClassName,
        LPCTSTR lpWindowName,
        DWORD dwStyle,
        int x,
        int y,
        int nWidth,
        int nHeight,
        HWND hWndParent,
        HMENU hMenu,
        HINSTANCE hInstance,
        LPVOID lpParam
    );
    
    CreateWindow的第一个参数就是所谓的「窗口类别名称」,并且该窗口类别连接所谓的「窗口消息处理程序」。在我们使用CreateWindow之前,有一点背景知识会对您大有帮助。


总体结构

    进行Windows程序设计,实际上是在进行一种对象导向的程序设计(OOP)。这点在Windows中使用得最多的对象上表现最为明显。这种对象正是Windows之所以命名为「Windows」的原因,它具有人格化的特征,甚至可能会在您的梦中出现,这就是那个叫做「窗口」的东西。

    桌面上最明显的窗口就是应用程序窗口。这些窗口含有显示程序名称的标题列、菜单甚至可能还有工具列和滚动条。另一类窗口是对话框,它可以有标题列也可以没有标题列。

    装饰对话框表面的还有各式各样的按键、单选按钮、复选框、清单方块、滚动条和文字输入区域。其中每一个小的视觉对象都是一个窗口。更确切地说,这些都称为「子窗口」或「控件窗口」或「子窗口控件」。

    作为对象,使用者会在屏幕上看到这些窗口,并通过键盘和鼠标直接与它们进行交互操作。更有趣的是,程序写作者的观点与使用者的观点极其类似。窗口以「消息」的形式接收窗口的输入,窗口也用消息与其它窗口通讯。对消息的理解将是学习如何写作Windows程序所必须越过的障碍之一。
    
    这有一个Windows的消息范例:我们知道,大多数的Windows程序都有大小合适的应用程序窗口。也就是说,您能够通过鼠标拖动窗口的边框来改变窗口的大小。通常,程序将通过改变窗口中的内容来响应这种大小的变化。您可能会猜测(并且您也是正确的),是Windows本身而不是应用程序在处理与使用者重新调整窗口大小相关的全部杂乱程序。由于应用程序能改变其显示的样子,所以它也「知道」窗口大小改变了。
    
    应用程序是如何知道使用者改变了窗口的大小的呢?由于程序写作者习惯了往常的文字模式程序,操作系统没有设置将此类消息通知给使用者的机制。问题的

    关键在于理解Windows所使用的架构。当使用者改变窗口的大小时,Window给程序发送一个消息指出新窗口的大小。然后程序就可以调整窗口中的内容,以响应大小的变化。
    
    「Windows给程序发送消息。」我们希望读者不要对这句话视而不见。它到底表达了什么意思呢?我们在这里讨论的是程序代码,而不是一个电子邮件系统。操作系统怎么给程序发送消息呢?
    
    其实,所谓「Windows给程序发送消息」,是指Windows呼叫程序中的一个函数,该函数的参数描述了这个特定消息。这种位于Windows程序中的函数称为「窗口消息处理程序」。
    
    无疑,读者对程序呼叫操作系统的做法是很熟悉的。例如,程序在打开磁盘文件时就要使用有关的系统呼叫。读者所不习惯的,可能是操作系统呼叫程序,而这正是Windows对象导向架构的基础。
    
    程序建立的每一个窗口都有相关的窗口消息处理程序。这个窗口消息处理程序是一个函数,既可以在程序中,也可以在动态链接库中。Windows通过呼叫窗口消息处理程序来给窗口发送消息。窗口消息处理程序根据此消息进行处理,然后将控制传回给Windows。
    
    更确切地说,窗口通常是在「窗口类别」的基础上建立的。窗口类别标识了处理窗口消息的窗口消息处理程序。使用窗口类别使多个窗口能够属于同一个窗口类别,并使用同一个窗口消息处理程序。例如,所有Windows程序中的所有按钮均依据同一个窗口类别。这个窗口类别与一个处理所有按钮消息的窗口消息处理程序(位于Windows的动态链接库中)联结。
    
    在对象导向的程序设计中,对象是程序与数据的组合。窗口是一种对象,其程序是窗口消息处理程序。数据是窗口消息处理程序保存的信息和Windows为每个窗口以及系统中那个窗口类别保存的信息。
    
    窗口消息处理程序处理给窗口发送消息。这些消息经常是告知窗口,使用者正使用键盘或者鼠标进行输入。这正是按键窗口知道它被「按下」的奥妙所在。在窗口大小改变,或者窗口表面需要重画时,由其它消息通知窗口。
    
    Windows程序开始执行后,Windows为该程序建立一个「消息队列」。这个消息队列用来存放该程序可能建立的各种不同窗口的消息。程序中有一小段程序代码,叫做「消息循环」,用来从队列中取出消息,并且将它们发送给相应的窗口消息处理程序。有些消息直接发送给窗口消息处理程序,不用放入消息队列中。
    
    如果您对这段Windows架构过于简略的描述将信将疑,就让我们去看看在实际的程序中,窗口、窗口类别、窗口消息处理程序、消息队列、消息循环和窗口消息是如何相互配合的。这或许会对您有些帮助。

    HELLOWIN程序
    
    建立一个窗口首先需要注册一个窗口类别,那需要一个窗口消息处理程序来处理窗口消息。处理窗口消息对每个Windows程序都带来了些负担。程序3-1所示的HELLOWIN程序中整个做的事情差不多就是料理这些事情。
    
    程序3-1 HELLOWIN.ASM 
            
    ;MASMPlus 代码模板 - 普通的 Windows 程序代码
    .386
    .Model Flat, StdCall
    Option Casemap :None

    Include windows.inc
    Include user32.inc
    Include kernel32.inc
    Include gdi32.inc
    Include winmm.inc

    includelib gdi32.lib
    IncludeLib user32.lib
    IncludeLib kernel32.lib
    IncludeLib winmm.lib
    include macro.asm
        
        WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
        WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
        
    .DATA
        szAppName   db "HelloWin",0
        
    .DATA?
        hInstance   dd ?
        
    .CODE
    START:   ;从这里开始执行

        invoke GetModuleHandle,NULL
        mov hInstance,eax
        invoke WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
        invoke ExitProcess,0

    WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
        LOCAL wndclass :WNDCLASSEX
        LOCAL msg       :MSG
        local hWnd      :HWND
        mov wndclass.cbSize,sizeof WNDCLASSEX   
        mov wndclass.style,CS_HREDRAW or CS_VREDRAW 
        mov wndclass.lpfnWndProc,offset WndProc

        mov wndclass.cbClsExtra,0
        mov wndclass.cbWndExtra,0
        
        push hInst
        pop wndclass.hInstance
        
        invoke LoadIcon,NULL,IDI_APPLICATION
        mov wndclass.hIcon,eax  
        
        invoke LoadCursor,NULL,IDC_ARROW
        mov wndclass.hCursor,eax    
        
        invoke GetStockObject,WHITE_BRUSH
        mov wndclass.hbrBackground,EAX
        
        mov wndclass.lpszMenuName,NULL
        mov wndclass.lpszClassName,offset szAppName

        mov wndclass.hIconSm,0
        
        invoke RegisterClassEx, ADDR wndclass
        .if (EAX==0)
             invoke MessageBox,NULL,CTXT("This program requires Windows NT!"),addr szAppName,MB_ICONERROR       
             ret
        .endif
            
        invoke CreateWindowEx,
                        NULL,
                ADDR szAppName,                         ;window class name
                CTXT("http://www.aogosoft.com"), ;window caption
                WS_OVERLAPPEDWINDOW,                    ;window style
                200,                                        ;initial x position
                200,                                        ;initial y position
                400,                                        ;initial x size
                200,                                        ;initial y size
                NULL,                                   ;parent window handle
                NULL,                                       ;window menu handle
                hInst,                              ;program instance handle
                NULL                                ;creation parameters
        mov hWnd,eax
        
        invoke ShowWindow,hWnd,SW_SHOWNORMAL
        invoke UpdateWindow,hWnd
        
        StartLoop:
            invoke GetMessage,ADDR msg,NULL,0,0
                cmp eax, 0
                je ExitLoop
                    invoke TranslateMessage, ADDR msg
                    invoke DispatchMessage,  ADDR msg
                jmp StartLoop
        ExitLoop:
        
    mov eax,msg.wParam
    ret
    WinMain endp

    WndProc proc hWin:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -