关于win32编程中消息循环和WndProc()窗口过程函

在win32程序的消息循环函数中
  while (GetMessage (&msg, NULL, 0, 0))
  {   
  TranslateMessage (&msg) ;   
  DispatchMessage (&msg) ;   
  }

DispatchMessag()会调用WndProc()窗口过程函数,直到WndProc()处理完后DispatchMessag()才返回,继续消息循环检索下一条消息,在此之前while()消息循环会停顿掉

在WndProc()函数处理过程中如果又产生了另一个消息B,则必须等这个消息B处理完后wndProc()函数才会返回,而这个消息B也是要由WndProc()函数处理的,即在WndProc()调用的过程中系统接受到消息B后嵌套调用了WndProc(),但此时while消息循环已经停顿了


return msg.wParam;
根据试验,在WndProc()处理过程中发出消息B后,系统通过某种方式跳过while()消息循环获取了消息B,并且又调用了一个WndProc()来处理消息B,等消息B处理完后第二个WndProc()才返回,然后第一个WndProc()继续执行,等第一个WndProc()执行完毕后DispatchMessage()才会返回,然后继续下一轮while()循环


那么,系统是怎样接受到这个消息B的呢?系统是怎样绕过while消息循环获取消息B并且调用第二个WndProc()的,这中间具体发生了哪些事情?网上和书上都没找到详细的处理过程……


我想应该还是跟消息队列有关,不知道系统在这种情况下怎样处理消息队列中的消息的?


MSG_B Over
每个窗口、线程都有自己的消息队列,消息是投递到消息队列里的
while (GetMessage (&msg, NULL, 0, 0))
  TranslateMessage (&msg) ;   
  DispatchMessage (&msg) ;   
  }
GetMessage是从消息队列里获取消息,因此,消息传过来的时候,是不占用这个循环的


谢谢解答!

可是在DispatchMessage (&msg)函数中调用wndproc()窗口过程时,while ()消息循环是停顿掉的,发出消息B后,这时系统是跳过while()消息循环直接到消息队列里取的消息吗?是怎样调用第二个wndproc()窗口过程的?用到了哪些函数呢?

你用什么消息测试的。
有的消息是不放在消息队列里的。
ShowWindow(hwnd, nCmdShow);





不是所有消息都会进消息队列,系统会有额外处理,对于SendMessage,类似于直接调用WinProc来实现.

谢谢了,我是担心SendMssage()可能会影响测试结果,所以用PostMessage()发送的消息

PostMessage的话 消息进消息队列下次取消息的时候才会取到消息。





int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,  

不是,虽然PostMessage只是投递消息,但是在WndProc窗口过程函数中必须处理完这个新消息后才继续执行


WndProc()函数是可重入的,就是说:WndProc()函数虽然没结束,但一个API调用(SendMessage()、PostMessage等)会再次调用WndProc()


所以我想知道系统这时是怎样再次调用WndProc()窗口过程函数的


SendMessage给自己发才会先处理完这个新消息后才继续执行

SendMessageW->SendMessageWorker
SendMessageWorker判断目标窗口的线程是不是当前线程,如果不是就进入内核调用NtUserMessageCall
否则就在用户模式调用窗口过程

PostMessage的话只是把消息放到消息队列中,下次GetMessage的时候才取到。
SendMessage( hwnd , WM_MESS , w , l );内部调用WndProc( hwnd , WM_MESS , w , l );

你可以下个断点看看调用栈。




谢谢!

谢谢各位的解答,在此特别感谢 Lactoferrin qman007 等,感谢你们的解答


由于之前测试消息的选择和测试方式的错误,导致我测试的结果不可信,我重新进行了测试,根据测试结果,对于WinProc消息循环的机制我是这样理解的:

SendMessage 的话相当于直接调用 WndProc

1、在win32程序的while消息循环中,DispatchMessag()会调用WndProc()窗口过程函数,直到WndProc()处理完后DispatchMessag()才返回,继续消息循环检索下一条消息,在这之前while()消息循环会停顿掉

2、在WndProc()函数处理过程中又产生了另一个消息B,如果消息B是由PostMessage()发送的,则消息B会发送到消息队列中,然后WndProc()继续执行,执行完毕后返回到DispatchMessag()函数,继续消息循环检索下一条消息,检索到消息B后才开始执行消息B,

3、在WndProc()函数处理过程中又产生了另一个消息B,如果消息B是由SendMessage()发送的,则必须等这个消息B处理完后wndProc()函数才会返回,这时SendMessage()会调用 SendMessageWorker(),SendMessageWorker()判断目标窗口的线程是不是当前线程,如果不是就进入内核调用NtUserMessageCall(),否则就在用户模式调用窗口过程函数WndProc()
展开阅读全文

没有更多推荐了,返回首页