Windows的消息机制

Windows消息机制

Windows是一个消息驱动的操作系统。

什么是消息

消息是一种手段,可以帮助应用程序和操作系统应用程序之间 进行通信。

操作系统可以发给应用程序一个消息,告诉应用程序某个特定的事件发生了。比如:当用户点击鼠标或键盘都会引发Windows发送相应的消息。应用程序也可以产生一个消息,使窗口执行特定的任务,或与其它应用程序通信。

从数据结构的角度来看,消息是一个结构体,包含了消息的类型标识符和其他附加信息。

typedef struct tagMSG {
	HWND hwnd;		// 消息所属的窗口,一个消息一般都是与某个窗口相关联的
	UINT message;	// 消息的标识符,Windows中消息是由一个数值来表示的,为了方便记忆,又将对应的数值定义为WM_XXX宏
	WPARAM wParam;	// 消息的附加信息,随消息的不同而不同
	LPARAM lParam;	// 消息的附加信息
	DWORD time;		// 消息投递到消息队列中的时间
	POINT pt;		// 消息投递到消息队列中鼠标的当前位置
} MSG, *LPMSG, *PMSG;

消息的种类

根据定义者来分类:

  • 系统定义的消息0x0-0x3ff之间,又可细分为三种

    • 窗口消息:与窗口的内部运作有关,如窗口的创建、绘制、销毁;
    • 命令消息:一般特指WM_COMMAND,与处理用户请求有关,通常由控件或菜单产生;
    • 通知消息:特指WM_NOTIFY消息,通常指一个窗口内的子控件发生了一些事情,需要通知父窗口,只适用于标准的窗口控件(按钮、列表框、编辑框,以及化公共控件树状视图、列表视图)。
  • 应用程序定义的消息0x400-0xffff之间。

    • WM_USER:0x400-0x7fff之间,用户自定义的消息范围;
    • WM_APP:0x8000-0xbfff,用于应用程序之间进行通信时;
    • RegisterWindoMessage:0xc000-0xffff

根据发送途径分类:

  • 队列消息:消息先保存在消息队列中,之后再被分发到对应的窗口处理函数。如鼠标、键盘消息。
  • 非队列消息:消息会绕过消息队列,直接被发送到对应的窗口处理函数。如WM_ACTIVATE、WM_SETFOCUS、WM_SETCURSOR、WM_WINDOWPOSCHANGED,应用程序调用SetWindowPos时会产生这些消息。

消息队列

Windows系统中有两种消息队列:

  • 系统消息队列:由系统维护,唯一的消息队列。计算机的所有输入设备都由系统监控,设备驱动会把输入操作转化成消息,放在系统消息队列中,系统再将其复制到相应的应用程序消息队列中。
  • 应用程序消息队列:每个GUI线程都会维护一个消息队列(当该线程第一次调用GDI函数时,系统才会为它创建消息队列),应用程序中的消息循环会在它的消息队列中检索每个消息并发送给相应的窗口处理函数。
小结:当一个事件发生时,Windows会先将输入的消息放入系统消息队列,再将其复制到相应的应用程序队列中,应用程序中的消息循环
会在它的消息队列中检索每个消息并发送给相应的窗口函数。一个事件从发生到到达处理它的窗口函数必须经历上述过程。

注意:事件有非抢先性,即不论事件的急与缓,总是按到达的先后排队(一些系统消息除外),这可能导致一些外部实时事件得不到及时的处理。

常用的消息函数

  • 发送消息

SendMessage:将消息发给目标窗口。等消息处理完毕后,函数才会返回;否则一直阻塞。

PostMessage:将消息发给目标窗口所在的消息队列中,然后立即返回。

PostThreadMessage:将消息发给指定线程的消息队列中,然后立即返回。

注意:SendMessage发送的是非队列消息,PostMessage发送的是队列消息。

LRESULT
SendMessageW(
    HWND Wnd,
	UINT Msg,
	WPARAM wParam,
	LPARAM lParam);
BOOL
PostMessageW(
    HWND hWnd,
    UINT Msg,
    WPARAM wParam,
    LPARAM lParam);
BOOL
WINAPI
PostThreadMessageW(
    DWORD idThread,
    UINT Msg,
    WPARAM wParam,
    LPARAM lParam);
  • 接收消息

GetMessage:从指定的窗口中取出消息(消息范围在wMsgFilterMin~wMsgFilterMax之间),消息取出后就从消息队列中删除该消息。取不到消息线程会挂起,直到取出。

PeekMessage:从消息队列中查询消息,如果有消息则返回TRUE,没有则返回FALSE。

WaitMessage:当一个线程的消息队列中没有消息时,WaitMessage会使该线程中断并处于等待状态,把控制权交给其他线程,直到被中断线程的消息队列中有新消息。

BOOL
GetMessageW(
    LPMSG lpMsg,
    HWND hWnd,
    UINT wMsgFilterMin,	
    UINT wMsgFilterMax);
BOOL
PeekMessageW(
  	LPMSG lpMsg,
  	HWND hWnd,
  	UINT wMsgFilterMin,
  	UINT wMsgFilterMax,
  	UINT wRemoveMsg);	// 为PM_REMOVE时,若消息队列中有消息,则取出并从队列中删除;为PM_NOREMOVE时,不取出消息
BOOL WaitMessage(VOID);
  • 转换消息

TranslateMessage:把一个virtual-key消息转化成字符消息,并放到当前线程的消息队列中,消息循环下一次取出处理。

BOOL
TranslateMessage(CONST MSG *lpMsg);
  • 分发消息

DispatchMessage:应用程序通过消息循环将消息派发到目标窗口。

LRESULT
DispatchMessageW(CONST MSG *lpmsg);

常用的消息

  • WM_COMMAND:当用户从菜单或按钮中选择一条命令或一个控件时,该消息被发送给它的父窗口,或者当一个快捷键被释放时发送。对应0111h。

  • WM_DESTROY:当一个窗口被销毁时发送该消息。对应02h。

  • WM_GETTEXT:用户程序发送一条WM_GETTEXT消息,会将对应窗口的文本复制到一个由应用程序提供的缓冲区中。对应0Dh。

  • WM_QUIT:当应用程序调用PostQuitMessage时,生成WM_QUIT消息。对应012h。

  • WM_LBUTTONDOWN:当光标停在一个窗口的客户区且用户按下鼠标左键时,WM_LBUTTONDOWN消息将被发送。如果鼠标动作未被捕获,这条消息将被发送给光标下的窗口;否则将被发送给已经捕获鼠标动作的窗口。对应0201h。

模拟点击按钮

两种方式:一种是通过父窗口,一种是直接通过WM_LBUTTONDOWN+WM_LBUTTONUP消息

BOOL
SendMouseLeft(HWND hWnd)
{
    BOOL   bReturn = FALSE;
    WPARAM wParam  = 0;

    if (hWnd == NULL)
    {
        return FALSE;
    }
    wParam = MAKEWPARAM(GetDlgCtrlID(hWnd), BM_CLICK);
    bReturn = PostMessageW(GetParent(hWnd), WM_COMMAND, wParam, (LPARAM)hWnd);
    if (!bReturn)
    {
        SendMessageW(GetParent(hWnd), WM_COMMAND, wParam, (LPARAM)hWnd);
    }
    
    // PostMessageW(hWnd, WM_LBUTTONDOWN, 0, 0);
    // PostMessageW(hWnd, WM_LBUTTONUP, 0, 0);
    return TRUE;
}
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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值