• 6.windows消息机制(一)


    1.所谓程序执行机制分为:

      过程驱动:程序的执行过程总是按照预定好的顺序执行。

      事件驱动:程序的执行是无序的,用户可以根据需要随机出发相应的事件。

      win32窗口程序就是采用事件驱动方式执行,也就是消息机制。

    2.什么是消息?

      当系统通知窗口工作时,DispatchMessage函数就采用消息的方式派发给窗口处理函数。

      消息的组成:(windows平台下消息必须由这6个部分组成)

        窗口句柄

        消息ID

        消息的两个参数(两个附带信息)

        消息的产生时间

        消息产生时的鼠标位置

    3.DispatchMessage( &nMsg )是怎么派发消息?(其实就是调用我们的窗口处理函数来处理这个消息)

      通过nMsg.hWnd保存窗口数据的内存,然后找到窗口对应的窗口类名称,用这个名称去匹配每个窗口类名称。

      一旦匹配成功,就直接调用我们自己定义的窗口处理函数。

      然后给我们的窗口处理函数传参:WndProc(nMsg.hWnd, nMsg.message, nMsg.wParam, nMsg.lParam)

    4.窗口处理函数

      (1)每个窗口都必须具有窗口处理函数

        LRESULT CALLBACK WindowProc( HWND      hWnd,     //窗口句柄

                                                                 UINT        uMsg,      //消息ID

                                                                 WPARAM  wParam,   //消息参数

                                                          LPARAM    lParam);  //消息参数

        当系统通知窗口时,会调用窗口处理函数,同时将参数(窗口句柄、消息ID、消息两个参数)传递给窗口处理函数。

        在窗口处理函数中,不处理的消息,使用缺省窗口处理函数,例如DefWindowProc。

    5.消息相关函数

      (1)GetMessage - 获取本进程的消息

        BOOL GetMessage( LPMSG  lpMsg,                //存放获取到的消息buffer

                                HWND   hWnd,                //窗口句柄

                                UINT     wMsgFilterMin,      //获取消息的最小ID

                                    UINT     wMsgFilterMax); //获取消息的最大ID

        lpMsg - 获取到消息后,将消息的参数存放到MSG结构中

        hWnd - 获取到hWnd所指窗口的消息,不获取其他窗口消息;如果为NULL,任意窗口的消息都获取。

        wMsgFilterMin和wMsgFilterMax - 只能获取到由它指定的消息范围内的消息,如果都为0,表示没有范围。

        如果抓取到的消息是WM_QUIT,那么返回值为0;否则,返回非0。

      (2)TranslateMessage - 翻译消息,将按键消息翻译成字符消息

        BOOL TranslateMessage( CONST MSG *lpMsg);  //消息的地址

        检查消息是否是按键的消息,如果不是按键消息,不做任何处理继续执行。

        为什么只翻译按键消息,不翻译其他消息呢?因为键盘中的可见字符按键有多种状态(比如大小写)。

      (3)DispatchMessage - 派发消息,将消息派发到该消息所属窗口的窗口处理函数上

        LRESULT DispatchMessage( CONST MSG *lpMsg);  //消息的地址

     6.Windows常用消息

      (1)WM_DESTROY - 窗口被销毁(保存窗口数据的内存释放)时的消息,无消息参数。常用于在窗口被销毁之前,做相应的善后处理,

                                         例如资源、内存等。

      (2)WM_SYSCOMMAND - 系统命令消息,当点击窗口的最大化、最小化、关闭等命令时,收到这个消息,常用在窗口关闭时,提示用户处理。

          wPARAM- 具体点击位置,例如关闭SC_CLOSE等。

          lPARAM - 鼠标位置:LOWORD - 水平位置,HIWORD - 垂直位置。

      (3)WM_CREATE - 在窗口创建成功还未显示之前,收到这个消息。常用于初始化窗口的参数、资源等,包括创建子窗口等。

          WPARAM - 不使用。

          LPARAM - 是CREATESTRUCT结构指针,保存了CreateWindowEx中的12个参数。

      (4)WM_SIZE - 在窗口的大小发生变化后,会收到这个消息。常用于窗口大小变化后,调整窗口内各个部分的布局。

          wPARAM - 窗口大小变化的原因。

          lPARAM - 变化窗口客户区的大小:LOWORD - 变化后的宽度,HIWORD - 变化后的高度。

      (5)WM_QUIT - 用于结束消息循环处理

          wPARAM  - PostQuitMessage函数传递的参数

          lPARAM - 不使用

          当GetMessage收到这个消息后,会返回FALSE,结束while处理,退出消息循环。

      (6)WM_PAINT - 绘图消息

      (7)键盘消息

      (8)鼠标消息

      (9)定时器消息

    下面是示例代码:

    #include "stdafx.h"
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_SYSCOMMAND:
            if (SC_CLOSE == wParam)
            {
                int nRet = MessageBox(NULL, "是否退出", "Info", MB_YESNO);
                if (IDNO == nRet)
                {
                    return 0;
                }
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hIconSm = NULL;
        wce.hInstance = g_hInstance;
        wce.lpfnWndProc = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName = NULL;
        wce.style = CS_HREDRAW | CS_VREDRAW;
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }//显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
        return 0;
    }
    View Code

    运行结果:

      

  • 相关阅读:
    和园友们聊聊天
    php编写验证码
    面试题复习记录(二)
    面试题复习记录(一)
    正则表达式学习小记
    javascript学习小记(一)
    大四
    Java小应用程序
    明白这十个故事-->你也就参悟了人生
    Hibernate懒加载深入分析
  • 原文地址:https://www.cnblogs.com/csqtech/p/5576098.html
Copyright © 2020-2023  润新知