windows的窗口消息机制(读windows核心编程笔记):基础篇

当线程调用函数来建立某个对象时,则该对象就归这个线程的进程所拥有。这样,当进程结束时,如果没有明确删除这个对象,则操作系统会自动删除这个对象。对窗口和挂钩( h o o k )这两种U s e r对象,它们分别由建立窗口和安装挂钩的线程所拥有。
如果一个线程建立一个窗口或安装一个挂钩,线程结束,操作系统会自动删除窗口或卸载挂钩。这意味:建立窗口的线程必须为窗口处理所有消息。这也意味着每个线程,如果至少建立了一个窗口,都由系统对它分配一个消息队列。这个队列用于窗口消息的派送( d i s p a t c h)。为了使窗口接收这些消息,线程必须有它自己的消息循环。


线程调用一个与图形用户界面有关的函数(例如检查它的消息队列或建立一个窗口),系统就会为该线程分配一些另外的资源,以便它能够执行与用户界面有关的任务。特别是,系统分配一个T H R E A D I N F O结构,并将这个数据结构与线程联系起来。这个T H R E A D I N F O结构包含一组成员变量,利用这组成员,线程可以认为它是在自己独享的环境中运行。T H R E A D I N F O是一个内部的、未公开的数据结构,用来指定线程的登记消息队列(posted-message queue)、发送消息队列( send-message queue)、应答消息队列( r e p l y -message queue)、虚拟输入队列(virtualized-input queue)、唤醒标志(wake flag)、以及用来描述线程局部输入状态的若干变量,离开代码(int nExitCode).这个T H R E A D I N F O结构是窗口消息系统的基础.

BOOL PostMessage(
  HWND
hWnd,      // handle of destination window-------Long,接收消息的那个窗口的句柄。
  UINT Msg,       // message to post----------------------------Long,消息标识符
  WPARAM wParam// first message parameter
  LPARAM lParam   // second message parameter
); 作用是消息被放置在线程的登记消息队列中。将一条消息投递到指定窗口的消息队列。投递的消息会在Windows事件处理过程中得到处理。特别适合那些不需要立即处理的窗口消息的发送
hWnd如设为HWND_BROADCAST,表示投递给系统中的所有顶级窗口。如设为零,表示投递一条线程消息。
当一个线程调用这个函数时,系统要确定是哪一个线程建立了用h w n d参数标识的窗口。然后系统分配一块内存,将这个消息参数存储在这块内存中,并将这块内存增加到相应线程的登记消息队列中。并且,这个函数还设置Q S _ P O S T M E S S A G E唤醒位。
函数在登记了消息之后立即返回,调用该函数的线程不知道登记的消息是否被指定窗口的窗口过程所处理。实际上,有可能这个指定的窗口永远不会收到登记的消息。如果建立这个特定窗口的线程在处理完它的消息队列中的所有消息之前就结束了,就会发生这种事。


DWORD GetWindowThreadProcessId(
  HWND
hWnd,             // handle to window
  LPDWORD lpdwProcessId // address of variable for process identifier
);函数返回线程的I D,这个线程建立了h w n d参数所标识的窗口。线程I D在全系统范围内是唯一的。可以通过对p d w P r o c e s s I d参数传递一个D W O R D地址来获取拥有该线程的进程I D,这个进程I D在全系统范围内也是唯一的。通常,不需要进程I D,只须对这个参数传递N U L L。

BOOL PostThreadMessage(
  DWORD
idThread, // thread identifier
  UINT Msg,       // message to post
  WPARAM wParam// first message parameter
  LPARAM lParam   // second message parameter
);也可以将消息放置在线程的登记消息队列中。PostThreadMessage是一个线程体发送一个消息到指定的线程ID
当消息被设置到队列中时,M S G结构的h w n d成员将设置成N U L L。当程序要在主消息循环中执行一些特殊处理时要调用这个函数。这个函数既可以发送消息给工作线程,也可以发送给UI线程。
接受PostThreadMessage的线程必须已经有了一个message queue,否则调用PostThreadMessage会失败。因为此原因使用GetLastError会得到错误码为1444,这种情况经常出现,解决方法有如下两种:调用PostThreadMessage,如果失败,就Sleep一段时间再次调PostThreadMessage直到调用成功;创建一个Event对象,让PostThreadMessage等待接受的线程创建一个message queue。可以通过调用PeekMessage强制系统创建一个message queue
PostThreadMessage传递的消息如果要包含信息,要注意在结束的时候释放消息中的信息。P o s t T h r e a d M e s s a g e在向线程的队列登记了消息之后就立即返回。调用该函数的线程不知道消息是否被处理。

VOID PostQuitMessage(
  int nExitCode   // exit code
);为了终止线程的消息循环,应该是由DestroyWindow()中发出的WM_QUIT消息来引起调用的。
PostQuitMessage()是posts一个WM_QUIT消息给消息队列并立即返回;进程收到WM_QUIT消息后退出
消息循环,程序结束。DestroyWindow()是发送一个WM_DESTROY消息,结束掉此窗口,但是程序并
没有结束。
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值