您的位置 首页 > 实用软件

windows系统消息队列_microsoft消息队列

1.我的Windows 组件向导里没有消息队列的选项?

2.vc/mfc 进程消息队列,线程消息队列,和系统消息队列,该如何处理

3.如何清空Windows消息队列

4.Windows消息队列何时创以及它与线程的关系

5.怎么理解消息循环?

6.启用windows功能microsoft消息队列服务器显示错误

7.win7系统如何安装消息队列|win7加入消息队列的方法

windows系统消息队列_microsoft消息队列

可以使用Purge方法清除“消息队列”系统中您有权访问的任何队列的内容。例如,设在本地“消息队列”客户端上使用日记队列记录送出的所有消息的副本。当日记达到其大小上限时,可以使用Purge方法清除不再需要的项。

我的Windows 组件向导里没有消息队列的选项?

一、 引言

二、Windows消息机制的概念

1、DOS与Windows驱动机制的区别

2、消息

3、消息的来源

4、Windows的消息系统的组成

5、消息的响应

三、Windows消息机制要点

1. 窗口过程

2 消息类型

3消息队列(Message Queues)

4 队列消息和非队列消息

5 Windows消息函数

6消息死锁( Message Deadlocks

7 BroadcastSystemMessage

四、MFC消息机制

1.MFC框架下,接收处理来自Windows消息的过程

2.MFC内部消息处理方式

一、 引言

在 C++程序架构 一文中,我们看到,程序是由一些层次和模块组成的,那么,这些模块之间, 以及你的程序和windows 之间,是如何传递信息呢?在windows 的平台上,传递信息是由 windows message 消息机制来负责的,这是Windows 的核心部分。

消息包括数据和指令。

二、Windows消息机制的概念

1、DOS与Windows驱动机制的区别

1)DOS是过程驱动的。

传统的MS-DOS程序主要用顺序的。关联的、过程驱动的程序设计方法。一个过程是一系列预先定义好的操作序列的组合,它具有一定的开头、中间过程和结束。程序直接控制程序和过程的顺序。这样的程序设计方法是面向程序而不是面向用户的,交互性差,用户界面不够友好,因为它强迫用户按照某种不可更改的模式进行工作。它的基本模型如图1.1所示。

2)Windows是(消息)驱动

驱动程序设计是一种全新的程序设计方法,它不是由的顺序来控制,而是由的发生来控制,而这种的发生是随机的、不确定的,并没有预定的顺序,这样就允许程序的的用户用各种合理的顺序来安排程序的流程。对于需要用户交互的应用程序来说,驱动的程序设计有着过程驱动方法无法替代的优点。它是一种面向用户的程序设计方法,它在程序设计过程中除了完成所需功能之外,更多的考虑了用户可能的各种输入,并针对性的设计相应的处理程序。它是一种“被动”式程序设计方法,程序开始运行时,处于等待用户输入状态,然后取得并作出相应反应,处理完毕又返回并处于等待状态。它的框图如图1.2所示:

2、消息

Windows系统是一个驱动的OS,每一个的发生都会产生一个消息,我们通过消息来知道发生了什么,了解,进而解决。什么是消息呢?很难下一个定义,下面从不同的几个方面讲解一下:

1) 消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。

2)谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。

3)未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。

4)窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。

3、消息的来源

驱动围绕着消息的产生与处理展开,一条消息是关于发生的的消息。驱动是靠消息循环机制来实现的。也可以理解为消息是一种报告有关发生的通知。

Windows应用程序的消息来源有一下四种:

1)输入消息:包括键盘和鼠标的输入。这一类消息首先放在系统消息队列中,然后由Windows将它们送入应用程序消息队列中,由应用程序来处理消息。

2)控制消息:用来与Windows的控制对象,如列表框、按钮、检查框等进行双向通信。当用户在列表框中改动当前选择或改变了检查框的状态时发出此类消息。这类消息一般不经过应用程序消息队列,而是直接发送到控制对象上去。

3)系统消息:对程序化的或系统时钟中断作出反应。一些系统消息,象DDE消息(动态数据交换消息)要通过Windows的系统消息队列,而有的则不通过系统消息队列而直接送入应用程序的消息队列,如创建窗口消息。

4)用户消息:这是程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理。

4、Windows的消息系统的组成

Windows的消息系统由以下3部分组成:

消息队列:Windows能够为所有的应用程序维护一个消息队列,应用程序必须从消息队列中获去消息,然后分派给某个窗体。

消息循环:通过这个循环机制,应用程序从消息队列中检索消息,再把它分派给适当的窗口,然后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。

窗口过程:每个窗口都有一个窗口过程,以接收Windows 传递给窗口的消息,窗口过程的任务就是获取消息并且响应它。窗口过程是一个回调函数,处理完一个消息后,通常要给Windows 一个返回值。

5、消息的响应

消息的产生来源于系统事情(包括计时器)和用户事情,Windows用消息来调入和关闭(还有其它处理,如绘制一个窗口等)应用程序,一个典型表现是在关机操作中,Windows发一个关机的消息给所有正在运行的应用程序,告知它们退出内存,此时,应用程序用回应消息的方法来响应OS,因此,消息是应用程序与WinOS交互的手段..

消息产生到被窗口响应的步骤:(如下图)

1> 系统发生了或用户发出某个。

2> Windows把这个翻译为消息,然后把他放到消息队列中

3> 应用程序从消息队列中接受到这个消息,把他存放到TMsg记录中。

4> 应用程序把消息传递给一个适当的窗体过程。

窗体过程响应这个消息并进行处理。把消息传递给了这个窗体的窗体函数。

三、Windows消息机制要点

1. 窗口过程

每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam), 当窗口收到消息时系统就会调用此窗口过程来处理消息。(所以叫回调函数)

2 消息类型

1) 系统定义消息(System-Defined Messages)

在SDK中事先定义好的消息,非用户定义的,其范围在[0×0000, 0×03ff]之间, 可以分为以下三类:

窗口消息(Windows Message)

与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等。可以是一般的窗口,可以是 Dialog,控件等。

如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL..

命令消息(Command Message)

与处理用户请求有关, 如单击菜单项或工具栏或控件时, 就会产生命令消息。

WM_COMMAND, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件, HIWORD(wParam)表示控件消息类型

控件通知(Notify Message)

控件通知消息, 这是最灵活的消息格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHDR的指针。NMHDR包含控件通知的内容, 可以任意扩展。

2) 程序定义消息(Application-Defined Messages)

用户自定义的消息, 对于其范围有如下规定:

WM_USER: 0×0400-0×7FFF (ex. WM_USER+10)

WM_APP(winver>4.0): 0×8000-0xBFFF (ex.WM_APP+4)

RegisterWindowMessage: 0xC000-0xFFFF

3消息队列(Message Queues)

Windows中有两种类型的消息队列

1) 系统消息队列(System Message Queue)

这是一个系统唯一的Queue,设备驱动(mouse, keyboard)会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific message queue)中等待处理

2) 线程消息队列(Thread-specific Message Queue)

每一个GUI线程都会维护这样一个线程消息队列。(这个队列只有在线程调用GDI函数时才会创建,默认不创建)。然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理.

注意: 线程消息队列中WM_PAINT,WM_TIMER只有在Queue中没有其他消息的时候才会被处理,WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出(FIFO)的方式被处理。

4 队列消息(Queued Messages)和非队列消息(Non-Queued Messages)

1)队列消息(Queued Messages)

消息会先保存在消息队列中,消息循环会从此队列中取消息并分发到各窗口处理

如鼠标,键盘消息。

2) 非队列消息(NonQueued Messages)

消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理

如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED

注意: postMessage发送的消息是队列消息,它会把消息Post到消息队列中; SendMessage发送的消息是非队列消息, 被直接送到窗口过程处理

5 Windows消息函数

1)PostMessage(PostThreadMessage), SendMessage

PostMessage:把消息放到指定窗口所在的线程消息队列中后立即返回。 PostThreadMessage:把消息放到指定线程的消息队列中后立即返回。

SendMessage:直接把消息送到窗口过程处理, 处理完了才返回。

2)GetMessage, PeekMessage

PeekMessage会立即返回 可以保留消息

GetMessage在有消息时返回 会删除消息

3) TranslateMessage, TranslateAccelerator

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

TranslateAccelerator: 将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN 或 WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND 或WM_SYSCOMMAND消息, 然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口过程处理, 处理完后才会返回。

6消息死锁( Message Deadlocks

设有线程A和B, 现在有以下下步骤

1) 线程A SendMessage给线程B, A等待消息在线程B中处理后返回

2)线程B收到了线程A发来的消息,并进行处理, 在处理过程中,B也向线程A SendMessgae,然后等待从A返回。

因为此时, 线程A正等待从线程B返回, 无法处理B发来的消息, 从而导致了\线程A,B相互等待, 形成死锁。多个线程也可以形成环形死锁。

可以使用 SendNotifyMessage或SendMessageTimeout来避免出现死锁。

7 BroadcastSystemMessage

我们一般所接触到的消息都是发送给窗口的, 其实, 消息的接收者可以是多种多样的,它可以是应用程序(lications), 可安装驱动(installable drivers), 网络设备(network drivers), 系统级设备驱动(system-level device drivers)等,

BroadcastSystemMessage这个API可以对以上系统组件发送消息。

那么这些消息是怎样传送的呢。我们以MFC为例来看一下消息传送过程。

四、MFC消息机制

在Windows应用程序的主函数中,首先要注册窗口类,然后创建并显示窗口。创建窗口后程序就进入消息循环,在消息循环中,程序不断地获得消息并将消息派送给对应的窗口函数进行处理。

我们可以看到,在MFC的框架结构下,可以进行消息处理的类的头文件里面

都会含有DECLARE_MESSE_MAP()宏,这里主要进行消息映射和消息处理函数的声

明。可以进行消息处理的类的实现文件里一般都含有如下的结构。

BEGIN_MESSE_MAP(CInheritClass, CBaseClass) //{{AFX_MSG_MAP(CInheritClass)

//}}AFX_MSG_MAP

END_MESSE_MAP()

这里主要进行消息映射的实现和消息处理函数的实现。

所有能够进行消息处理的类都是基于CCmdTarget类的,也就是说CCmdTarget

类是所有可以进行消息处理类的父类。CCmdTarget类是MFC处理命令消息的基础和核心。

同时MFC定义了下面的两个主要结构:

AFX_MSGMAP_ENTRY

struct AFX_MSGMAP_ENTRY

{//“““//

};

和AFX_MSGMAP

struct AFX_MSGMAP

{//“““`//

};

其中AFX_MSGMAP_ENTRY结构包含了一个消息的所有相关信息, 而AFX_MSGMAP主要作用是两个,一:用来得到基类的消息映射入口地址。二:得到本身的消息映射入口地址。

实际上,MFC把所有的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了所有的消息和与它们相关的消息的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时也得到基类的消息映射入口地址,这是为例当本身对该消息不响应的时候,就调用其基类的消息响应。

现在我们来分析MFC是如何让窗口过程来处理消息的,实际上所有MFC的窗口类都通过钩子函数_AfxCFilterHook截获消息,并且在钩子函数_AfxCFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中

1.MFC框架下,接收处理来自Windows消息的过程:

2.MFC内部消息处理方式

MFC接收一个寄送的消息:

MFC处理一个寄送和发送消息的惟一明显不同是寄送的消息要做应用程序的消息队列中花费一些时间。在消息泵(message pump)弹出它之前,它要一直在队列中。下面是怎样接受寄送消息的过程。MFC应用程序中的消息泵在CWinApp的成员函数Run()中。应用程序开始运行时,Run()就被调用,Run()把时间分割成两部分。一部分用来执行后台处理,如取消临时CWnd对象;另一部分用来检查消息队列。当一个新的消息进来时,Run()抽取它—即用GetMessage( )从队列中取出该消息,运行PreTranslateMessage( )和::TranslateMessage( )两个消息翻译函数,然后用DispatchMessage( )函数调用该消息预期的目标窗口进程。如下图。

我们用一个实例函数A发送消息到函数B的过程来看一下MFC内部消息处理过程。

1. 首先函数A应获取消息的CWnd类对象的指针,然后,调用CWnd的成员函数SendMessage()。

LRESULT Res=pWnd->SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam);

pWnd指针指向目标CWnd类对象。变量Msg是消息,wParam和lParam变量包含消息的参数,如鼠标单单击哪里或选择了什么菜单项。目标窗口返回的消息结果放在变量Res中。

发送消息到一个没有CWnd的函数对象的窗口,可以用下列目标窗口的句柄直接调用Windows API:

LRESULT Res=::SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

这里的hWnd是目标窗口的句柄。

如果是异步传输也可使用PostMessage(),消息同上相同,但返回值Res不一样,Res不是一个由目标窗体返回的值,而是一个布尔值,用来表示消息是否成功的放到消息队列中。

2. 正常情况下,一旦消息被发送后,应用程序后台会自动的将它发送,但是在特殊情况下,需要你自己去删除一个消息,例如想在应用程序接收到某种消息之前停止应用程序。有两种方法可以从应用程序消息队列中删除一个消息,但这两种方法都没有涉及MFC。

第一种方法:在不干扰任何事情之下窥视消息队列,看看一个消息是否在那里。

BOOL res=::PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ) ;

第二种方法:实际上是等待,一直等到一个新的消息到达队列为止,然后删除并返回该消息。

BOOL res=::GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);

在这两种方法中,变量hWnd指定要截获消息的窗口,如果该变量设为NULL,所有窗口消息将被截获。wMsgFilterMin和wMsgFilterMax变量与SendMessage( )中的变量Msg相对应,指定查看消息的范围。如果用“0,0〃,则所有的消息都将被截获。如果用WM_KEYFIRST,WM_KEYLAST或WM_MOUSEFIRST,WM_MOUSELAST,则所有键盘或鼠标的消息将被截获。wRemoveMsg变量指定PeekMessage( )是否应该真正地从队列中删除该消息。(GetMessage( )总是删除消息)。该变量可以取两个值:

PM_REMOVE,PeekMessage( )将删除消息。

PM_NOREMOVE,PeekMessage( )将把消息留在队列里,并返回它的一个拷贝。

当然,如果把消息留在消息队列中,然后再次调用PeekMessage( )查看相同类型的消息,则将返回完全相同的消息。

lpMsg变量是一个指向MSG结构的指针,MSG包含检索到的消息。

typedef struct tagMSG {

HWND hwnd; // window handle message is intended for

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time; // the time the message was put in the queue

POINT pt; // the location of the mouse cursor when the

// message was put in the queue

} MSG;

3. 消息会到消息队列中。CwinApp的成员函数Run,在应用程序运行时,Run就把时间分割成两部分,一部分执行后台的处理,另一部分来检查消息的队列,当发现新消息时,Run就调用GetMessage()从队列消息中取出该消息。

3.运行两个消息翻译函数PreTranslateMessage()和::TranslateMessage(),进行翻译。主要找到函数对象的位置、消息的动作标识和跟消息相关的执行操作。

4.用DispatchMessage()函数调用该消息预期的函数B进程,进行执行。

vc/mfc 进程消息队列,线程消息队列,和系统消息队列,该如何处理

home版是不可以的,必须是专业版的,我笔记本也是正版的HOME版,网上搜了一些办法但都行不通,你还是换盗版的专业版吧,安装的时候还要注意下面的问题:

简化版的好像不行,用番茄花园修改过的系统肯定不行这个我实际试过的,

在安装Wincc的时候它会自动检测系统还需要安装的组件。

第一个:SQL Server 2000 SP3 For Wincc,需要注意的是系统如果不是原版wincc的这个SQL可能安装不上,你安装的时候会出现“Setup finished with err”。

第二个:信息服务(IIs)和Message Queue(消息队列),安装方法为在“控制面板”-“添加Windows组件”中选择“Internet信息服务(IIS)”与“消息队列”,这里要注意,选中消息队列后,点出详细信息后把“触发器”前面的勾要去掉,安装需要操作系统的安装光盘。

第三个:安装两个XP 新补丁KB3140 KB889673 解决办法:重新安装msdtc服务

开始--运行--cmd

net stop msdtc

msdtc -uninstall

msdtc - install

net start msdtc

参考资料:

.jiaoyichong.cn

如何清空Windows消息队列

队列消息和非队列消息

从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息。消息队列由可以分成系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数数系统给线程创建一个消息队列。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。

对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,还有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。当鼠标、键盘被触发后,相应的鼠标或键盘驱动程序就会把这些转换成相应的消息,然后输送到系统消息队列,由Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。

一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。

非队列消息将会绕过系统队列和消息队列,直接将消息发送到窗口过程,。系统发送非队列消息通知窗口,系统发送消息通知窗口。 例如,当用户激活一个窗口系统发送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。这些消息通知窗口它被激活了。非队列消息也可以由当应用程序调用系统函数产生。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息。一些函数也发送非队列消息,例如下面我们要谈到的函数。

消息的发送

了解了上面的这些基础理论之后,我们就可以进行一下简单的消息发送与接收。

把一个消息发送到窗口有3种方式:发送、寄送和广播。

发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函数主要有PostMessage、PostThreadMessage、PostQuitMessage;广播消息的函数我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。

SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),这个函数主要是向一个或多个窗口发送一条消息,一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。函数的返回值是由接收消息的窗口的窗口函数返回,返回的值取决于被发送的消息。

PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),该函数把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。需要注意的是,如果hWnd参数为HWND_BROADCAST,那么,消息将被寄送给系统中的所有的重叠窗口和弹出窗口,但是子窗口不会收到该消息;如果hWnd参数为NULL,则该函数类似于将dwThreadID参数设置成当前线程的标志来调用PostThreadMEssage函数。

从上面的这2个具有代表性的函数,我们可以看出消息的发送方式和寄送方式的区别所在:被发送的消息是否会被立即处理,函数是否立即返回。被发送的消息会被立即处理,处理完毕后函数才会返回;被寄送的消息不会被立即处理,他被放到一个先进先出的队列中,一直等到应用程序空线的时候才会被处理,不过函数放置消息后立即返回。

实际上,发送消息到一个窗口处理过程和直接调用窗口处理过程之间并没有太大的区别,他们直接的唯一区别就在于你可以要作系统截获所有被发送的消息,但是不能够截获对窗口处理过程的直接调用。

以寄送方式发送的消息通常是与用户输入相对应的,因为这些不是十分紧迫,可以进行缓慢的缓冲处理,例如鼠标、键盘消息会被寄送,而按钮等消息则会被发送。

广播消息用得比较少,BroadcastSystemMessage函数原型如下:

long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);

该函数可以向指定的接收者发送一条消息,这些接收者可以是应用程序、可安装的驱动程序、网络驱动程序、系统级别的设备驱动消息和他们的任意组合。需要注意的是,如果dwFlags参数是B_QUERY并且至少一个接收者返回了BROADCAST_QUERY_DENY,则返回值为0,如果没有指定B_QUERY,则函数将消息发送给所有接收者,并且忽略其返回值。

窗口过程

窗口过程是一个用于处理所有发送到这个窗口的消息的函数。任何一个窗口类都有一个窗口过程。同一个类的窗口使用同样的窗口过程来响应消息。 系统发送消息给窗口过程将消息数据作为参数传递给他,消息到来之后,按照消息类型排序进行处理,其中的参数则用来区分不同的消息,窗口过程使用参数产生合适行为。

一个窗口过程不经常忽略消息,如果他不处理,它会将消息传回到执行默认的处理。窗口过程通过调用DefWindowProc来做这个处理。窗口过程必须return一个值作为它的消息处理结果。大多数窗口只处理小部分消息和将其他的通过DefWindowProc传递给系统做默认的处理。窗口过程被所有属于同一个类的窗口共享,能为不同的窗口处理消息。下面我们来看一下具体的实例:

 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

 {

int wmId, wmEvent;

PAINTSTRUCT ps;

HDC hdc;

TCHAR szHello[MAX_LOADSTRING];

LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

switch (message)

{

case WM_COMMAND:

wmId = LOWORD(wParam);

wmEvent = HIWORD(wParam);

// Parse the menu selections:

switch (wmId)

{

case IDM_ABOUT:

DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);

break;

case IDM_EXIT:

DestroyWindow(hWnd);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

RECT rt;

GetClientRect(hWnd, &rt);

DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

  }

return 0;

 }

消息分流器

通常的窗口过程是通过一个switch语句来实现的,这个事情很烦,有没有更简便的方法呢?有,那就是消息分流器,利用消息分流器,我们可以把switch语句分成更小的函数,每一个消息都对应一个小函数,这样做的好处就是对消息更容易管理。

之所以被称为消息分流器,就是因为它可以对任何消息进行分流。下面我们做一个函数就很清楚了:

void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)

{

switch(id)

{

case ID_A:

if(codeNotify==EN_CHANGE)...

break;

case ID_B:

if(codeNotify==BN_CLICKED)...

break;

....

}

}

然后我们修改一下窗口过程:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

switch(message)

{

HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);

HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);

default:

return DefWindowProc(hWnd, message, wParam, lParam);

  }

return 0;

 }

在WindowsX.h中定义了如下的HANDLE_MSG宏:

 #define HANDLE_MSG(hwnd,msg,fn) \

switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));

实际上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);将被转换成如下定义:

 #define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn)\

((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);

好了,事情到了这一步,应该一切都明朗了。

不过,我们发现在windowsx.h里面还有一个宏:FORWARD_WM_XXXX,我们还是那WM_COMMAND为例,进行分析:

 #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \

(void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))

所以实际上,FORWARD_WM_XXXX将消息参数进行了重新构造,生成了wParam && lParam,然后调用了我们定义的函数。

MFC消息的处理实现方式

初看MFC中的各种消息,以及在头脑中根深蒂固的C++的影响,我们可能很自然的就会想到利用C++的三大特性之一:虚拟机制来实现消息的传递,但是经过分析,我们看到事情并不是想我们想象的那样,在MFC中消息是通过一种所谓的消息映射机制来处理的。

为什么呢?在潘爱民老师翻译的《Visual C++技术内幕》(第4版)中给出了详细的原因说明,我再简要的说一遍。在CWnd类中大约有110个消息,还有其它的MFC的类呢,算起来消息太多了,在C++中对程序中用到的每一个派生类都要有一个vtable,每一个虚函数在vtable中都要占用一个4字节大小的入口地址,这样一来,对于每个特定类型的窗口或控件,应用程序都需要一个440KB大小的表来支持虚拟消息控件函数。

如果说上面的窗口或控件可以勉强实现的话,那么对于菜单命令消息及按钮命令消息呢?因为不同的应用程序有不同的菜单和按钮,我们怎么处理呢?在MFC库的这种消息映射系统就避免了使用大的vtable,并且能够在处理常规Windows消息的同时处理各种各样的应用程序的命令消息。

说白了,MFC中的消息机制其实质是一张巨大的消息及其处理函数的一一对应表,然后加上分析处理这张表的应用框架内部的一些程序代码.这样就可以避免在SDK编程中用到的繁琐的CASE语句。

MFC的消息映射的基类CCmdTarget

如果你想让你的控件能够进行消息映射,就必须从CCmdTarget类中派生。CCmdTarget类是MFC处理命令消息的基础、核心。MFC为该类设计了许多成员函数和一些成员数据,基本上是为了解决消息映射问题的,所有响应消息或的类都从它派生,例如:应用程序类、框架类、文档类、视图类和各种各样的控件类等等,还有很多。

不过这个类里面有2个函数对消息映射非常重要,一个是静态成员函数DispatchCmdMsg,另一个是虚函数OnCmdMsg。

DispatchCmdMsg专门供MFC内部使用,用来分发Windows消息。OnCmdMsg用来传递和发送消息、更新用户界面对象的状态。

CCmdTarget对OnCmdMsg的默认实现:在当前命令目标(this所指)的类和基类的消息映射数组里搜索指定命令消息的消息处理函数。

这里使用虚拟函数GetMessageMap得到命令目标类的消息映射入口数组_messageEntries,然后在数组里匹配命令消息ID相同、控制通知代码也相同的消息映射条目。其中GetMessageMap是虚拟函数,所以可以确认当前命令目标的确切类。

如果找到了一个匹配的消息映射条目,则使用DispachCmdMsg调用这个处理函数;

如果没有找到,则使用_GetBaseMessageMap得到基类的消息映射数组,查找,直到找到或搜寻了所有的基类(到CCmdTarget)为止;

如果最后没有找到,则返回FASLE。

每个从CCmdTarget派生的命令目标类都可以覆盖OnCmdMsg,利用它来确定是否可以处理某条命令,如果不能,就通过调用下一命令目标的OnCmdMsg,把该命令送给下一个命令目标处理。通常,派生类覆盖OnCmdMsg时 ,要调用基类的被覆盖的OnCmdMsg。

在MFC框架中,一些MFC命令目标类覆盖了OnCmdMsg,如框架窗口类覆盖了该函数,实现了MFC的标准命令消息发送路径。必要的话,应用程序也可以覆盖OnCmdMsg,改变一个或多个类中的发送规定,实现与标准框架发送规定不同的发送路径。例如,在以下情况可以作这样的处理:在要打断发送顺序的类中把命令传给一个非MFC默认对象;在新的非默认对象中或在可能要传出命令的命令目标中。

消息映射的内容

通过ClassWizard为我们生成的代码,我们可以看到,消息映射基本上分为2大部分:

在头文件(.h)中有一个宏DECLARE_MESSE_MAP(),他被放在了类的末尾,是一个public属性的;与之对应的是在实现部分(.cpp)增加了一章消息映射表,内容如下:

BEGIN_MESSE_MAP(当前类, 当前类的基类)

file://{{AFX_MSG_MAP(CMainFrame)

 消息的入口项

file://}}AFX_MSG_MAP

END_MESSE_MAP()

但是仅是这两项还远不足以完成一条消息,要是一个消息工作,必须有以下3个部分去协作:

1.在类的定义中加入相应的函数声明;

  2.在类的消息映射表中加入相应的消息映射入口项;

  3.在类的实现中加入相应的函数体;

消息的添加

有了上面的这些只是作为基础,我们接下来就做我们最熟悉、最常用的工作:添加消息。MFC消息的添加主要有2种方法:自动/手动,我们就以这2种方法为例,说一下如何添加消息。

1、利用Class Wizard实现自动添加

在菜单中选择View-->Class Wizard,也可以用单击鼠标右键,选择Class Wizard,同样可以激活Class Wizard。选择Message Map标签,从Class name组合框中选取我们想要添加消息的类。在Object IDs列表框中,选取类的名称。此时, Messages列表框显示该类的大多数(若不是全部的话)可重载成员函数和窗口消息。类重载显示在列表的上部,以实际虚构成员函数的大小写字母来表示。其他为窗口消息,以大写字母出现,描述了实际窗口所能响应的消息ID。选中我们向添加的消息,单击Add Function按钮,Class Wizard自动将该消息添加进来。

有时候,我们想要添加的消息本应该出现在Message列表中,可是就是找不到,怎么办?不要着急,我们可以利用Class Wizard上Class Info标签以扩展消息列表。在该页中,找到Message Filter组合框,通过它可以改变首页中Messages列表框中的选项。这里,我们选择Window,从而显示所有的窗口消息,一把情况下,你想要添加的消息就可以在Message列表框中出现了,如果还没有,那就接着往下看:)

2、手动地添加消息处理函数

如果在Messages列表框中仍然看不到我们想要的消息,那么该消息可能是被系统忽略掉或者是你自己创建的,在这种情况下,就必须自己手工添加。根据我们前面所说的消息工作的3个部件,我们一一进行处理:

1) 在类的. 件中添加处理函数的声明,紧接在//}}AFX_MSG行之后加入声明,注意:一定要以afx_msg开头。

通常,添加处理函数声明的最好的地方是源代码中Class Wizard维护的表下面,但是在它标记其领域的{{}}括弧外面。这些括弧中的任何东西都将会被Class Wizard销毁。

2) 接着,在用户类的.cpp文件中找到//}}AFX_MSG_MAP行,紧接在它之后加入消息入口项。同样,也是放在{ {} }的外面

3) 最后,在该文件中添加消息处理函数的实体。

Windows消息队列何时创以及它与线程的关系

一.准备工具:

PC

Windows7(以WIN7为例)

二.步骤如下:

打开开始菜单—控制面板。

点击程序和功能。

点击打开或关闭windows功能。

将其中的Microsoft Message Queue (MSMQ)取消对勾确定即可,便执行取消WIN7消息队列。

怎么理解消息循环?

消息线程与线程?Windows编程里并没有这种划分。

线程有两种,分别叫用户界面线程和工作者线程,很多人误以为这两个种类是在线程最初建立时为其赋予的天生的属性,实际上它们的区别不在于建立时,而在于运行时是否创建了消息队列,任何线程在最初建立时是一样的。

无论是系统在启动窗口程序时为其建立一个主线程,还是程序员在主线程运行时调用CreateThread建立一个新线程,内部过程以及为线程建立的内部数据结构是一样的,都是调用Ntdll.dll的RtlUserThreadStart函数并传入线程入口指令地址和一个线程参数(系统启动主线程时传入的线程参数为0)。这时它们都没有自己的线程消息队列,都是工作者线程。但是窗口程序的主线程往往在启动后很快建立一个窗口并循环调用GetMessage抓取消息,而一旦线程调用一个与图形用户界面有关的函数,如GetMessage/PeekMessage检查消息队列或建立一个窗口,系统就会为该线程分配一些与用户界面相关的,尤其是分配一个用于管理消息队列的THREADINFO结构,这时线程的消息队列就建立起来,主线程也就转变为用户界面线程。

启用windows功能microsoft消息队列服务器显示错误

Windows是以消息驱动的操作系统,Windows 消息提供了应用程序与应用程序以及应用程序与Windows系统之间进行通讯的手段。

Windows 中有一个系统消息队列,对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。

消息循环代码是应用程序中主函数winmain ( )中类似如下的程序段:

while(GetMessage(&&msg,NULL,NULL,NULL))

{ //从消息队列中取得消息

TranslateMessage(&&msg);

//检索并生成字符消息WM_CHAR

DispatchMessage(&&msg);

//将消息发送给相应的窗口函数

}

由此可见,所谓“消息循环”,实际是程序循环。

Windows 应用程序创建的每个窗口都在系统核心注册一个相应的窗口函数,窗口函数程序代码形式上是一个巨大的switch 语句,用以处理由消息循环发送到该窗口的消息,窗口函数由Windows 用消息驱动的形式直接调用,而不是由应用程序显示调用的,窗口函数处理完消息后又将控制权返回给Windows。

win7系统如何安装消息队列|win7加入消息队列的方法

具体如下:

更改:1、首先要进入UAC设置,点击“开始”按钮打开“开始”菜单,在下方的搜索框内输入“UAC”,接着上面会显示搜索结果,点击进入“更改用户账户控制设置”。2、打开“用户账户控制设置”窗口后,将滑块拖动至最底端,设置为“从不通知”,然后点击“确定”;3、然后再从“开始”菜单进入“控制面板--程序--程序和功能”,然后点击左侧的“打开或关闭Windows功能”;取消后重启计算机就可以。

很多软件在使用的时候都会要求安装消息队列,比如WinCC、数据库等,很多深度win7用户都不知道win7系统如何安装消息队列,那么怎么安装消息队列呢?其实消息队列在windows功能里面可以添加,接下来请大家好、跟小编一起学习一下win7加入消息队列的方法。

添加消息队列方法:

1、首先点击“开始”按钮打开“开始”菜单,从中打开控制面板;

2、打开控制面板后,在“查看方式”为大图标或者小图标的情况下,点击“程序和功能”;

3、进入“程序和功能”窗口后,点击左侧的“打开或关闭Windows功能”;

4、来到“Windows功能”窗口后,找到“MicrosoftMessageQueue(MSMQ)服务器”,将其勾选,点击确定即可安装消息队列。

以上就是win7加入消息队列的方法的所有内容了,想要在win7安装消息队列只要按照上述方法在windows功能开启“MicrosoftMessageQueue(MSMQ)服务器”即可。

热门文章