zoukankan      html  css  js  c++  java
  • Windows常用消息处理与自定义消息

    Windows消息简介

    windows消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做TMsg。

    Windows程序都是通过消息机制驱动运行的。

    消息分类:

    一般根据消息是否进入消息队列可分为两类:

    不进队列消息:指由Windows直接调用消息处理函数,把消息直接交给其处理。如 WM_CREATE,WM_SIZE等。

        //WS: Window Style
        HWND hWnd = CreateWindow(
            szAppClassName,                                                            //窗口类型名
            TEXT("这是我的第一个Windows窗口程序"),                                        //窗口左上角标题
            WS_BORDER | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU,    //窗口的风格
            200, 300,                                                                //窗口左上角坐标
            800, 600,                                                                //窗口的宽和高
            NULL,                                                                    //父窗口句柄
            NULL,                                                                    //菜单句柄
            hInstance,                                                                //应用程序实例句柄
            (void*)100                                                                //创建窗口的附加参数,WM_CREATE消息,lParam来接受这个参数
        );
    
        if (hWnd == NULL)
        {
            MessageBox(NULL, TEXT("创建窗口失败"), TEXT("提示"), MB_OK);
            return 0;
        }
    View Code
    case WM_CREATE://窗口处理消息,发生在什么时候:窗口还没有显示的时候,通过调用CreateWindow函数或者CreateWindowEx函数,发出这个消息
        {
            MessageBox(NULL, L"这是WM_CREATE消息", L"提示", MB_OK);//阻塞函数,不点不往下走
            CREATESTRUCT* pcs = (CREATESTRUCT*)lParam;
            break;
        }
    View Code

    当执行完CreateWindow后才发出WM_CREATE消息,此时窗口还没显示出来。

     进队列消息:指Windows将消息放入到程序中的消息队列中取,并通过程序中的消息循环,循环把消息取出,经过一定处理(如例子中经过translate),然后由函数

    DispathMessage函数将消息分发给消息处理函数处理,这一类消息为进队列消息。常见的击键的消息(WM_KEYDOWN、WM_KEYUP)键盘输入产生字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)、
    鼠标键(WM_LBUTTONDOWN)、计时消息(WM_TIMER)、刷新消息(WM_PAINT)和退出消息(WM_QUIT),这类消息一般是由用户输入引发的。

    按照功能划分,消息分为两大类:

    系统定义消息

    (1)标准消息

    除WM_COMMAND之外,所有以WM_开头的消息都是标准消息,例如鼠标单击、移动,键盘左击、右击。

    (2)命令消息

    来自菜单,加速键或工具栏按钮的消息。这类消息都以WM——COMMAND形式呈现。WM_COMMAND, LOWORD(wParam)表示菜单项,工具栏按钮或一般控件的ID如编辑框,按钮等。如果是控件, HIWORD(wParam)表示控件消息类型

    (3)通告消息

    由复杂控件产生的消息。这类消息也是以WM——COMMAND形式呈现。 这是最灵活的消息格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHDR的指针。NMHDR包含控件通知的内容, 可以任意扩展。

    用户自定义消息

    WM_USER ,1024以下的定义的是系统消息,1024以上的是用户自定消息。

    消息发送

    提供了两种方式来发送消息:SendMessage和PostMessage。

    两者联系与区别:

    1.系统定义消息和用户自定义消息均可发送。

    2.SendMessage: 是一个阻塞函数,如果发送的消息没有没处理完,则不返回,处理完成,返回结果,并且结果就是SendMessage的返回值

      PostMessage:是一个非阻塞函数,只负责把消息发过去,不会等待消息的处理完成的结果。

    3.SendMessage返回值为LRESULT长整型(long),PostMessage为bool值。

    4.跨进程跨线程发送消息,推荐使用PostMessage。

     常用消息举例

    消息名称 消息参数 备注说明
    WM_CREATE消息

    WPARAM: 没有使用的

    LPARAM: CREATESTRUCT结构体指针

     
    WM_CLOSE消息

    WPARAM: 没有使用的

    LPARAM: 没有使用的

     窗口关闭消息 , 此时还能还原出来窗口,发生在:点击关闭按钮的时候
    WM_DESTROY消息  

    表示窗口销毁消息, 凡是执行到了WM_DESTROY消息了,那么此时此时已经没有回头路了,不能还原窗口了,因为界面已经被销毁了

    发生在什么时候:程序退出,进行清理工作了

    WM_LBUTTONDOWN   鼠标左键点击客户区消息
    WM_LBUTTONUP   鼠标左键抬起
    WM_RBUTTONDOWN   鼠标右键按下
    WM_RBUTTONUP   鼠标右键抬起
    WM_LBUTTONDBLCLK   鼠标左键双击消息。createwindows的时候style属性要加上CS_DBLCLKS,不然就只是单纯的 两次单击,不会发送此消息
    WM_MOUSEMOVE   鼠标移动消息
    WM_KEYDOWN   键盘按下消息
    WM_KEYUP   按键抬起消息
    WM_CHAR   字符消息

    Demo附录

    #include <Windows.h>
    #include "resource.h"
    #define UM_TEST                WM_USER+1                
    
    //窗口处理函数
    //第一个参数:当前窗口句柄
    //第二个参数:消息类型
    //第三个参数:附加信息/附加参数
    //第四个参数:附加信息/附加参数
    
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        //创建一个窗口
        //流程
        //1.设计窗口类
    
        wchar_t szAppClassName[] = TEXT("WINDOWS");
    
        WNDCLASS wc;
        wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;                    //窗口类的风格
        wc.lpfnWndProc = WindowProc;                                                //窗口回调函数/窗口处理函数 
        wc.cbClsExtra = 0;                                                        //窗口类的附加内存大小
        wc.cbWndExtra = 0;                                                        //窗口附加内存大小
        wc.hInstance = hInstance;                                                //当前应用程序实例句柄
        wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));        //图标句柄
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);    //光标句柄
        wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 0));                        //红,绿,蓝 0->255    0:最暗, 255:最亮, RGB(0,0,0):黑色, RGB(255,255,255):白色
        wc.lpszMenuName = NULL;                                                    //菜单名
        wc.lpszClassName = szAppClassName;                                            //窗口类型名 Spy++
    
        //2.注册窗口类
        //ATOM 
        //ATOM
        if (0 == RegisterClass(&wc))
        {
            MessageBox(NULL, TEXT("此程序不能运行在Windows NT平台."), TEXT("提示"), MB_OK);
            return 0;
        }
    
        //3.创建窗口
        //WS: Window Style
        HWND hWnd = CreateWindow(
            szAppClassName,                                                            //窗口类型名
            TEXT("这是我的第一个Windows窗口程序"),                                        //窗口左上角标题
            WS_BORDER | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU,    //窗口的风格
            200, 300,                                                                //窗口左上角坐标
            800, 600,                                                                //窗口的宽和高
            NULL,                                                                    //父窗口句柄
            NULL,                                                                    //菜单句柄
            hInstance,                                                                //应用程序实例句柄
            (void*)100                                                                //创建窗口的附加参数,WM_CREATE消息,lParam来接受这个参数
        );
    
        if (hWnd == NULL)
        {
            MessageBox(NULL, TEXT("创建窗口失败"), TEXT("提示"), MB_OK);
            return 0;
        }
    
        //4.显示窗口
        //SW_SHOW:原来在什么位置,就在什么位置显示
        //SW_SHOWMAXIMIZED:最大化显示
        //SW_SHOWMINIMIZED:最小化显示
        //SW_SHOWNORMAL:正常显示
        //SW_HIDE:隐藏运行
    
        ShowWindow(hWnd, SW_SHOW);
        //5.更新窗口 //窗口显示的时候,重新绘制一下
        UpdateWindow(hWnd);
        //6.消息循环
    
        //Windows程序都是通过消息机制驱动运行
    
        //GetMessage:什么时候返回FALSE 
        //当获取到WM_QUIT消息时,返回FALSE,退出循环,没有获取到这个消息,返回非0,不退出循环
    
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))  //0
        {
            //将虚拟键消息转化为字符消息 
            //一个按下消息+抬起消息=》字符消息,WM_KEYDOWN和WM_KEYUP=>WM_CHAR
            TranslateMessage(&msg);
            //将消息分发给窗口处理函数
            DispatchMessage(&msg);
        }
    
        return 0;
    }
    
    //窗口处理函数
    //Windows Message缩写
    //消息分为两类:
    //不进队列消息 WM_CREATE
    //进队列消息 :大部分消息时属于这一类
    
    //WM_CREATE消息
    //WPARAM: 没有使用的
    //LPARAM: CREATESTRUCT结构体指针
    
    //WM_CLOSE消息 窗口关闭消息 , 此时还能还原出来窗口
    //发生在:点击关闭按钮的时候
    //WPARAM: 没有使用的
    //LPARAM: 没有使用的
    
    //WM_DESTROY消息 表示窗口销毁消息, 凡是执行到了WM_DESTROY消息了,那么此时此时已经没有回头路了,不能还原窗口了,因为界面已经被销毁了
    //发生在什么时候:程序退出,进行清理工作了
    
    //WM_LBUTTONDOWN鼠标左键点击客户区消息
    //WPARAM:
    //LPARAM:
    
    //WM_LBUTTONUP:鼠标左键抬起
    
    //WM_RBUTTONDOWN:鼠标右键按下
    
    //WM_RBUTTONUP:鼠标右键抬起
    
    //WM_LBUTTONDBLCLK://鼠标左键双击消息
    
    //WM_MOUSEMOVE:鼠标移动消息
    
    //WM_KEYDOWN:键盘按下消息
    //WPARAM:
    //LPARAM:
    
    //WM_KEYUP:按键抬起消息
    
    
    //WM_CHAR:字符消息
    
    
    //后续讲解
    //WM_COMMAND消息
    //WM_SYSCOMMAND消息
    
    //消息的分类:0=>65535(消息范围)
    
    //1、系统消息    , 刚才介绍的这一些都是系统消息
    //WM_USER    1024以下的定义的是系统消息
    //1024以上的是用户自定消息
    
    //2、自定义消息
    //如果自定义消息
    //宏定义
    
    //3.发送消息
    //既可以发送系统消息,又可以发送用户自定义消息
    //SendMessage: 是一个阻塞函数,如果发送的消息没有没处理完,则不返回,处理完成,返回结果,并且结果就是SendMessage的返回值
    //PostMessage:是一个非阻塞函数,只负责把消息发过去,不会等待消息的处理完成的结果
    
    //SendMessage:用于自己进程发送消息
    //PostMessage:向进程外发送信息
    
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
        HDC hDC;
    
        //wchar_t szMsg[200];
        ////sprintf字符串格式化函数,窄字符
        //wsprintf(szMsg, L"窗口句柄:0X%x	消息:0X%x	wParam:%d	lParam:%d
    ", hWnd, uMsg, wParam,lParam);//字符串格式化函数,宽字符
        //OutputDebugString(szMsg);//仅限于调试
    
        switch (uMsg)
        {
    
        case WM_SIZE:
        {
            MessageBox(NULL, L"这是WM_SIZE消息,执行ShowWindow后创建该消息", L"提示", MB_OK);//阻塞函数,不点不往下走
            break;
        }
        case WM_CREATE://窗口处理消息,发生在什么时候:窗口还没有显示的时候,通过调用CreateWindow函数或者CreateWindowEx函数,发出这个消息
        {
            MessageBox(NULL, L"这是WM_CREATE消息", L"提示", MB_OK);//阻塞函数,不点不往下走
            CREATESTRUCT* pcs = (CREATESTRUCT*)lParam;
            break;
        }
        case WM_LBUTTONDOWN://鼠标左键点击客户区消息
        {
            //MessageBox(hWnd, L"WM_LBUTTONDOWN", L"提示", MB_OK);
            //int xPos = LOWORD(lParam); //WORD:字,unsigned short , 0-》65535
            //int yPos = HIWORD(lParam);
    
            //wchar_t szText[100];
            //wsprintf(szText, L"当前鼠标点击坐标(%d,%d)", xPos, yPos);
            //SetWindowText(hWnd, szText);
    
            //if (wParam & MK_CONTROL)
            //{
            //    wcscat(szText, L"按下了ctrl");
            //}
            //if (wParam & MK_MBUTTON)
            //{
            //    wcscat(szText, L"按下了鼠标中键");
            //}
            //if (wParam & MK_RBUTTON)
            //{
            //    wcscat(szText, L"按下了鼠标右键");
            //}
            //if (wParam & MK_SHIFT)
            //{
            //    wcscat(szText, L"按下了鼠标Shift键");
            //}
            //if (wParam & MK_LBUTTON)
            //{
            //    wcscat(szText, L"按下了鼠标左键;");
            //}
            //
            //////把坐标设置到窗口的标题
            //SetWindowText(hWnd, szText);
    
            //发送系统消息
            //SendMessage(hWnd, WM_CLOSE, 0, 0);
    
    
            //发送一个用户自定义消息
            int result = SendMessage(hWnd, UM_TEST, 45, 50);//阻塞
            BOOL b = PostMessage(hWnd, UM_TEST, 45, 50);//非阻塞
            int a = 20;
    
            /*HWND hNotepad = FindWindow(L"Notepad", L"无标题 - 记事本");
            if (hNotepad == NULL)
            {
                MessageBox(NULL, L"没有查找到窗口", L"提示", MB_OK);
                break;
            }*/
    
            //发送一个关闭消息
            //PostMessage(hNotepad, WM_CLOSE, 0, 0);
            //SendMessage(hNotepad, WM_CLOSE, 0, 0);
    
    
            break;
        }
        case WM_LBUTTONDBLCLK://createwindows的时候style属性要加上CS_DBLCLKS,不然就只是单纯的 两次单击,不会发送此消息)
        {
            SetWindowText(hWnd, L"双击");
            break;
        }
        case UM_TEST://用户自定义消息 
        {
            int a = (int)wParam;
            int b = (int)lParam;
    
            int result = a + b;
            return result;
        }
    
        case WM_MOUSEMOVE://鼠标移动消息
        {
            int xPos = LOWORD(lParam); //WORD:字,unsigned short , 0-》65535
            int yPos = HIWORD(lParam);
    
            wchar_t szText[100];
            wsprintf(szText, L"当前鼠标点击坐标(%d,%d)", xPos, yPos);
    
            if (wParam & MK_CONTROL) //按位&
            {
                wcscat(szText, L"按下了Ctrl;");
            }
    
    
            //把坐标设置到窗口的标题
            SetWindowText(hWnd, szText);
    
            break;
        }
        case WM_KEYDOWN://键盘按下消息
        {
            //MessageBox(hWnd, L"提示", L"OK", MB_OK);
            switch (wParam)
            {
            case VK_RETURN://回车键
                SetWindowText(hWnd, L"按下了回车键");
                break;
            }
            break;
        }
        case WM_CHAR://字符消息
        {
            char chCharCode = (TCHAR)wParam;
    
            wchar_t szText[100];
            wsprintf(szText, L"当前字符:%c", chCharCode);
            SetWindowText(hWnd, szText);
            break;
        }
        case WM_PAINT://客户区绘图消息, GDI绘图技术
        {
            //开始绘图
            HDC hDC = BeginPaint(hWnd, &ps);
            //Rectangle(hDC, 0, 0, 200, 200);矩形
            //绘制椭圆
            Ellipse(hDC, 0, 0, 300, 200);
            //结束绘图
            EndPaint(hWnd, &ps);
            break;
        }
        case WM_CLOSE://窗口关闭消息
        {
    
            //ShowWindow(hWnd, SW_HIDE);//隐藏
            //return 1;//表示我已经处理了
    
            if (IDYES == MessageBox(hWnd, L"您确定要关闭吗?", L"温馨提示", MB_YESNO))
            {
                DestroyWindow(hWnd);    //销毁窗口, 干掉界面,不会发出WM_QUIT,会发出一个WM_DESTROY消息
            }
            else
            {
                //break;//还是执行了DefWindowProc系统默认处理,界面销毁,不会退出进程
                //return 0;//没有处理,没有人去处理
                return 1;//我已经处理了,
            }
            break;
        }
        case WM_DESTROY://窗口销毁消息
            //ShowWindow(hWnd, SW_SHOW);        //无力回天了
            PostQuitMessage(0);        //发出WM_QUIT
            break;
    
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);//交给操作系统默认处理
    }
    View Code
     
  • 相关阅读:
    Smarty模板引擎技术(三)
    Smarty模板引擎技术(二)
    Smarty模板引擎技术(一)
    Ajax技术
    JavaScript--XML DOM
    JavaScript--HTML DOM
    [转]常用正则表达式
    JavaScript--事件
    CentOS 下开启PHP错误提示
    JavaScript实例
  • 原文地址:https://www.cnblogs.com/shuzhongke/p/15374661.html
Copyright © 2011-2022 走看看