子窗口与父窗口的消息传递

今天看到一篇不错的有关子窗口和父窗口消息传递的文章,转来学习学习

链接如下:

http://hi.baidu.com/drunkdream/item/a8b11230d6a779159dc65eca


子窗口和父窗口的消息传递

      

      
1. 什么是窗口      
2. 什么是消息      
3. 什么是窗口过程函数      
4. 怎么创建窗口      
5. 消息是怎么传递并处理的      
      
用调用windows API的方法创建了两个窗口,父窗口和子窗口。父窗口处理了鼠标左键按下和鼠标右键按下的消息,子窗口只处理了左键按下的消息。   
验证用的源码: 

/*

//自己的理解:

结合下图父窗口与子窗口属于同一线程

都用WinMain函数中 GetMessage(&msg, NULL, 0, 0) 接收消息

分发消息时,会根据消息所属的窗口句柄(MSG结构体中包含HWND结构)发送给不同的窗口函数进行处理

*/  

1. 在子窗口单击左键,弹出“子窗口左键按下”提示,之后父窗口未出现“父窗口左键按下”的提示。      
2. 在父窗口单击右键,弹出“父窗口右键按下”的提示。      
3. 在子窗口单击右键,没有任何提示,父窗口也没有任何提示。      
      
消息是根据窗口进行分发的,而不考虑该窗口的从属关系。也就是说在子窗口中产生的消息只在子窗口函数中处理,处理完后不会再把消息传递给父窗口(除非你自己做反射)。      
对窗口、线程、消息的关系总结:      
1.每一个窗口都是属于某一个线程的      
注意是线程      
2.每一个窗口都“绑定”了一个“窗口函数”!~      
也就是在每个窗口上产生的消息,会发往对应的函数来处理!~      
3.每一个线程都有一个属于自己的“消息队列”   
图示:   


      
1. 什么是窗口      
MSDN: In a graphical Win32-based application, a window is a rectangular area of the screen where the application displays output and receives input from the user. Therefore, one of the first tasks of a graphical Win32-based application is to create a window.      
大意:窗口就是一个矩形区域,应用程序可以用它来显示输出,或者从user来获得输入(键盘鼠标)。      
在windows中,“一切皆为窗口”。虽然不是很贴切,但是说明了窗口的普遍性和其重要性。      
比如,你现在看到的QQ聊天窗口,就是由多个窗口组成的!~      
2. 什么是消息      
MSDN: A data packet used for communicating information or a request. Messages can be passed between the operating system and an application, different applications, threads within an application, and windows within an application.      
大意:消息就是一组数据包(结构体),用于传递信息。消息可以在操作系统和一个进程之间传递,也可以在两个不同的进程间传递,也可以在同一个进程的不同线程间传递或同一个进程的不同窗口间传递。      
比如,你在QQ聊天窗口中点一下鼠标,打字等,都会产生消息。      
在代码中消息是以消息结构体MSG来保存的,里面的成员包括处理该消息的窗口句柄,消息代码,消息产生的时间和光标的位置等。      
3. 什么是窗口过程函数      
我们鼠标、键盘消息是在窗口上产生的,windows会把消息传给该窗口所属线程的消息队列中。然后这个消息在某个时间被这个窗口对应的处理函数来“搞定”。      
这个和窗口绑定的“处理消息的函数”就是“窗口过程函数”。      
一般的,一个窗口类绑定一个窗口过程函数。      
4. 怎么创建窗口      
首先,对于windows系统来讲,不管你是C#还是C++还是JAVA,要创建一个标准的窗口,都是调用相同的API的~      
只是在VC、C# .NET或用JAVA开发windows时,开发工具都帮你把创建窗口“通用的部分”封装了起来,你是看不到的。      
在我们C#的代码中,在Main函数里已经给我们创建好了第一个窗口Fomr1。为我们免去了N多初始化的麻烦,但是我们也就不知道窗口是怎么被创造出来的了。      
因此,这里的示例代码使用的是最原始,最明显的方法来创建一个窗口,显示出来并处理你发出的消息。我们用C语言来调用API创建窗口。      
创建窗口的4个步骤:      
1) 初始化窗口类(实际上是一个结构体)      
WNDCLASS wndclass;      
2) 注册这个类      
RegisterClass(……);      
3) 创建窗口      
hwnd = CreateWindow(……);      
4) 显示      
ShowWindow(hwnd, iCmdShow);      
精简后的创建窗口程序主干:      
WinMain(……)      
{      
……      
HWND hwnd;//用来存放窗口句柄      
MSG msg;//用来存放消息的结构体      
WNDCLASS wndclass;// 1)窗口结构体   
RegisterClass(……);// 2)注册窗口类    
hwnd = CreateWindow(……);// 3)创建窗口   
ShowWindow(hwnd, iCmdShow);// 4)显示      
UpdateWindow(hwnd);    
//下面是消息循环      
while(GetMessage(&msg, NULL, 0, 0))      
{      
TranslateMessage(&msg);      
DispatchMessage(&msg);      
}      
return msg.wParam;      
}      

说明:      
1) WNDCLASS wndclass;      
这个结构体里存放了窗口的各种初始数据。如窗体类的风格,窗体上显示的图标,鼠标的图标等。      
2) RegisterClass(……);      
调用该函数通知系统被注册类的窗口的消息,windows为后面创建窗口准备一系列资源。      
3) hwnd = CreateWindow(……);      
调用该函数创建较迭的、弹出的或子窗口。它指定窗口类、窗口标题、窗口风格和窗口的初始大小与位置等。      
创建出来的窗口以属于“活动”状态,已经开始进行消息处理。只是没有被“显示”出来。      
4) ShowWindow(hwnd, iCmdShow);      
该函数用来设置指定窗口的“显示状态”,如大小、位置、是否隐藏等。      
5. 消息是怎么传递并处理的      
消息(Message)在窗口中产生后,系统把它放入到该窗口所属线程的消息队列中,等待处理。      
线程将队列中的消息取得后,在翻译后,将它“投放”到相应的窗口过程函数中进行处理。      

消息处理机制的核心代码:      
while(GetMessage(&msg, NULL, 0, 0))      
{      
TranslateMessage(&msg);      
DispatchMessage(&msg);      
}      
根据MSDN,上面几个函数的作用:      
     1.GetMessage只获取自己所属线程的消息队列中的消息,包括windows消息和      
通过PostThreadMessage发送的线程消息。      
2.TranslateMessage是为了将虚拟键消息“翻译”成字符消息,然后把字符消息放回到线程的消息队列中,在下一次被GetMessage取得。(具体内容见MSDN)       
3.DispatchMessage的作用是将从GetMessage获得的消息分发给相应的窗口处理函数(WndProc),然后窗口过程函数对消息进行处理。      

上面代码中使用while循环的意义是:循环是应用程序能够持续存在的根本原因。如果循环退出,则应用程序就结束了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Qt中,窗口窗口传递参数可以通过信号和槽机制来实现。首先,我们需要在窗口中定义一个信号,以便在某个特定条件下向窗口发送参数。可以使用`signals`关键字定义信号,例如在窗口的头文件中添加以下代码: ``` signals: void sendData(QString data); ``` 在窗口中的某个操作触发时,可以通过`emit`关键字发送信号,并将参数传递给窗口。例如,在窗口的槽函数中添加以下代码: ``` void ChildWindow::onButtonClicked() { QString data = "Hello World"; emit sendData(data); } ``` 接下来,在窗口中连接窗口发送的信号和一个窗口的槽函数,以便接收参数。在窗口的代码中添加以下代码: ``` void MainWindow::onChildDataReceived(QString data) { qDebug() << "Received data from child window: " << data; } ``` 在窗口的构造函数或初始化函数中,可以使用以下代码来连接窗口的信号和窗口的槽函数: ``` ChildWindow *childWindow = new ChildWindow(); connect(childWindow, SIGNAL(sendData(QString)), this, SLOT(onChildDataReceived(QString))); ``` 这样,当窗口中的`onButtonClicked`函数被调用时,它将发送一个带有参数的信号,并且窗口的`onChildDataReceived`槽函数将接收到这个参数。在槽函数中,你可以使用这个参数进行相应的处理。 通过以上的方法,窗口就可以向窗口传递参数了。在实际的应用中,你可以根据具体的需求和场景进行适配和修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值