Windows消息

一.消息机制

windows操作系统最大的特色是良好的用户交互性,这种交互性是通过优秀的图形界面来是心啊的

Windows操作系统将用户对应用程序窗口的的所有操作(键盘按键,鼠标点击,窗口最大化最小化等等)转化为Windows雄安锡并分发给应用程序,应用程序对这些消息进行响应,从而实现用户对操作系统以及应用程序的控制。

这种产生消息,传递消息,处理消息的过程被称为Windows消息机制。

Windows操作系统位没一个正在运行的应用程序维护一个消息队列。应用程序的消息循环将接收和处理这些消息,从而对相关事件做出响应。

  1. 得到消息

  • GetMessage

从消息队列取消息,如果消息队列没有消息时,函数阻塞,等待消息,如果得到了消息,这个消息是

wm_quit消息,立马返回false,如果不是wm_quit消息,返回true


GetMessage(&msg, NULL, 0, 0);
  • PeekMessage

从消息队列取消息,如果消息队列有消息,且这个消息是任何消息,返回true,如果没有消息返回false


PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  1. 发送消息

  • SendMessage

可以理解为递归,直接把消息投递给该窗口对应的消息处理函数


SendMessage(hWnd,WM_KEYDOWN,0,0);
  • PostMessage


PostMessage(hWnd, WM_KEYDOWN, 0, 0);

可以理解为排队,把消息投递给这个窗口对应的消息队列,以供下一次去得到消息


二.基本消息

创建窗口消息

WM_CREATE

创建窗口时被发送给应用程序,该消息只被发送一次。理解为类的构造

GetMessage(&msg, NULL, 0, 0);

PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);

SendMessage(hWnd,WM_KEYDOWN,0,0);

PostMessage(hWnd, WM_KEYDOWN, 0, 0);

销毁窗口消息

WM_DESTROY

当关闭窗口时或者开发人员在程序中调用了DestroyWindow函数时,WM_DESTROY消息会被发送给应

用程序。理解为类的析构

激活消息

WM_ACTIVATE

该消息在以下3种情况时被发送:

1、鼠标单击激活。wParam参数被标记为WA_CLICKACTIVE

2、非鼠标激活。wParam参数被标记为WA_ACTIVE //比如同时启动了多个应用程序最上面的最小化了那么它下面的就被动激活了

  1. 非激活。wParam参数被标记为WA_INACTIVE

系统命令消息

WM_SYSCOMMAND

在关闭、最大化、最小化、还原窗口时被发送给应用程序。

1、当wParam参数为SC_CLOSE时表示窗口进行了关闭操作

2、当wParam参数为SC_MAXIMIZE时,表示窗口进行了最大化操作

3、当wParam参数为SC_MINIMIZE时,表示窗口进行了最小化操作

4、当wParam参数为SC_RESTORE时,表示窗口进行了最小化操作

命令消息

WM_COMMAND

当用户从菜单选中一个命令项目、当一个控件发送通知消息给去父窗口或者按下一个快捷键将发送

WM_COMMAND 消息

三.重要消息

按键消息----键盘是按下就发送了消息,但是鼠标要按下再松开的时候才发送消息

键盘是用户的标准输入设备,键盘的按键事件以消息的方式提供给应用程序

当按下一个键时Windows会产生WM_KEYDOWN或者WM_SYSKEYDOWN消息,当释放一个键时,

Windows会产生WM_KEYUP或者WM_SYSKEYUP消息

windows为按键的一个真实键值准备一个虚拟键值,对于ascii码中有的数据用ascii码来做为虚拟键值,

如果在ascii码中没有,vk_键名

WM_KEYDOWN

按键按下WM_KEYUP

按键抬起

WM_SYSKEYDOWN

系统按键按下。1、ALT或F10键;2、ALT+组合键

WM_SYSKEYUP

系统按键抬起

注意:按键消息响应VK_虚拟键名,如果是ASCII码则响应大写

WM_CHAR

TranslateMessage函数会对消息进行一部分预处理将键消息根据窗口当前状态翻译成对应的字符输入信

息,产生WM_CHAR消息

如果同时输入了多个字符,则WM_CHAR消息将被发送多次

字符消息可以响应大小写字符

鼠标消息

1、WM_LBUTTONDOWN

2、WM_LBUTTONUP

3、WM_LBUTTONDBLCLK

4、WM_MBUTTONDOWN

5、WM_MBUTTONUP

6、WM_MBUTTONDBLCLK

7、WM_RBUTTONDOWN

8、WM_RBUTTONUP

9、WM_RBUTTONDBLCLK

10、WM_MOUSEMOVE

11、WM_MOUSEWHEEL

得到鼠标当前坐标

GET_X_LPARAM(lParam)

GET_Y_LPARAM(lParam)

得到鼠标滚轮前后滚动

HIWORD(wParam)

朝前是120,朝后是-120

计时器消息设置计时器

响应计时器

1、如果设置计时器时,第4个参数为NULL,在WM_TIMER响应消息,通过wParam来匹配计时器id

2、如果设置计时器时,第4个参数有回调函数,则在回调函数中响应,也就是调用这个函数

销毁计时器

SetTimer(hWnd, //窗口句柄

1003, //计时器id

3000, //计时器间隔时间,单位:毫秒

(TIMERPROC)MyTimeFun);//计时器的回调函数

KillTimer(hWnd, 1003);//销毁哪个窗口的哪个计时器

下面是一些简单的操作,大家可以试着实现一下


// win32基本框架.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "win32基本框架.h"

#define MAX_LOADSTRING 100

// 全局变量: 
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名

// 此代码模块中包含的函数的前向声明: 
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,//应用程序实例句柄  句柄类似于身份证具有唯一性 
                     _In_opt_ HINSTANCE hPrevInstance,//父应用程序实例句柄  比如画图  我打开了一个画图之后又打开了一个画图  先打开的就是父应用程序 后打开的是子应用程序
                     _In_ LPTSTR    lpCmdLine,//命令行参数   在启动这个应用程序后可以给这个程序从命令行传递一些参数
                     _In_ int       nCmdShow)//窗口的显示风格   打开的时候窗口的显示风格 最大化 最小化 ...........
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO:  在此放置代码。
    MSG msg;
    HACCEL hAccelTable;

    // 初始化全局字符串
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_WIN32, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化: 
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
    //加载快捷键资源  暂时用不上
    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32));

    // 主消息循环: 
    while (GetMessage(&msg, NULL, 0, 0))//阻塞函数
    {
        /*这里有两种得到消息的函数 1是Getmessage (&mag,NULL.0,0)*/
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函数:  MyRegisterClass()
//
//  目的:  注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_WIN32);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   函数:  InitInstance(HINSTANCE, int)
//
//   目的:  保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中

   hWnd = CreateWindow(szWindowClass, _T("pp的第一窗口"),WS_OVERLAPPEDWINDOW/*窗口样式*/,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,/*窗口坐标 左上角 右下角*/
       NULL,//父窗口句柄
       NULL, //菜单
       hInstance,
       NULL);//窗口的辅助信息  

   if (!hWnd)//判断窗口是否创建成功
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);//绘制窗口
   UpdateWindow(hWnd);//更新窗口

   return TRUE;
}

//
//  函数:  WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    处理主窗口的消息。
//
//  WM_COMMAND    - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY    - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent, nVirtKey = (int)wParam,wPa/*虚拟键代码*/; 
    PAINTSTRUCT ps;
    HDC hdc;
    static int j = 0;
    switch (message)
    {
    case WM_CREATE:
        //创建计时器
        SetTimer(hWnd, 10010, 2000, NULL);//两个数字分别是id 和时间间隔(单位:毫秒)
        break;
    case WM_TIMER:
        wPa = wParam;
        switch (wPa)
        {
        case 10010:
            j++;
            if (j == 3)
                KillTimer(hWnd, 10010);
            MessageBox(hWnd,_T("10010"), _T("提示"), MB_OK);
            break;
        }
    case WM_SYSKEYDOWN://按键消息
        switch (nVirtKey)
        {
        case VK_MENU:
            MessageBox(hWnd, _T("ALT"),_T("提示"),MB_OK);
        default:
            break;
        }
    case WM_CHAR://字符消息
        wmId = wParam;
        switch (wmId)
        {
        case 'a':
        case 'A':
            MessageBox(hWnd, _T("a or A"), _T("提示"), 0);
            break;
        default:
            break;
        }
    case WM_SYSCOMMAND://系统命令
        wmId = wParam;
        switch (wmId)
        {
        case SC_CLOSE:
    if (IDOK==MessageBox(hWnd, _T("确定要退出吗?"), 0, 0))
        {
            //PostMessage(hWnd, WM_DESTROY, 0, 0);
            PostQuitMessage(0);//两种退出的方式都可以
        }
    break;
        default:    
            return DefWindowProc(hWnd, message, wParam, lParam);

        }
    
        break;
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // 分析菜单选择: 
        switch (wmId)
        {
        case IDM_ABOUT:
            //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, //About);
            MessageBox(hWnd, _T("第一个窗口:2023/01/17"), _T("关于窗口"), MB_OK);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO:  在此添加任意绘图代码...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Windows消息机制是指在Windows操作系统中,用于实现应用程序之间的通信和事件处理的机制。每个消息都由一个消息标识符和一些相关的参数组成。当系统中发生某个事件时,Windows会将这个事件转化为一个消息,并将其放入消息队列中。应用程序通过接收消息并将其传递给适当的窗口过程来处理这些消息。 在Windows消息机制中,每个线程都有自己的消息队列。GUI线程通常拥有一个消息循环,负责接收和处理消息消息循环会不断从消息队列中获取消息,并将其翻译和分发给对应的窗口过程进行处理。 除了通过消息队列派发消息窗口过程外,有些消息也可以直接发送到窗口过程进行处理,绕过消息队列和线程消息队列。例如,当用户激活一个新的应用程序窗口时,系统会直接发送一系列消息窗口,包括WM_ACTIVATE、WM_SETFOCUS和WM_SETCURSOR等消息,用于通知窗口被激活、键盘输入被定向到窗口以及鼠标光标移到窗口的边界内。 因此,Windows消息机制是通过将事件转化为消息并通过消息队列进行传递,以实现应用程序之间的通信和事件处理的机制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Windows消息机制](https://blog.csdn.net/King_weng/article/details/100072633)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pp不会算法^v^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值