在处理非WM_PAINT消息时,应用程序获取窗口用户区设备描述表句柄使用GetDC函数,它常常用来对用户的某些动作提供反馈。例如,当用户移动鼠标光标穿越窗口时,在屏幕上画一条线。GetDC函数返回一个显示缓冲区句柄,它可以用于任何GDI输出函数。
使用GetDC函数获得显示缓冲区句柄,在窗口函数中处理WM_PAINT消息。当窗口函数接收到影响用户区内容的WM_PAINT消息时,用户区中先前已画的内容可能被擦掉。这是因为在处理WM_PAINT消息的过程中,Windows发送WM_ERASEBKGND消息给窗口函数,如果把WM_ERASEBKGND消息交给DefWindowProc函数处理,DefWindowProc函数使用这种窗口类的背景色填满受影响的区域,并擦掉原先已经画的内容。
Windows发送WM_PAINT消息时,把它放到应用程序队列的最后,使得其它的输入能够先于WM_PAINT消息被处理。GetMessage函数也得到队列中WM_PAINT消息之后的其它消息,即只有有没有其它消息的情况下,才从队列中取出WM_PAINT消息进行处理。这样做是为了让应用程序首先完成影响窗口显示结果的其它操作,不致因为频繁地执行输出操作而引起显示器的闪烁。Windows把WM_PAINT消息放在队列最后就是这个原因。
(这里估计是使用了priority queue之类的队列来保证优先级)
如果不想等待应用程序队列中的WM_PAINT消息,使用UpdateWindow函数直接发送WM_PAINT消息给指定窗口的窗口函数。如果还存在无效的用户区,UpdateWindow函数从队列中取出WM_PAINT消息,并把它直接发送给指定窗口的窗口函数。UpdateWindow函数通常用在窗口需要立即更新它的用户区,如在窗口刚被创建时使用。
gdi和gdi++的区别到底是什么呢?难道仅仅是提供了对一些图形格式的支持?
对于windows来说,要创建一个窗口需要先用RegisterClass注册一个窗口类,windows已经预先创建了一些标准的,比如button,label之类的
然后就可以用CreateWindow来产生这个窗口了
windows的消息队列是以线程为单位的,每个界面线程都有一个,
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ; //翻译消息
DispatchMessage (&msg) ; //撤去消息
}
通过这个无限循环来接受分发消息,然后每个窗口通过registerclass注册过一个回调函数,在dispatchmessage里
就会根据msg的hwnd找到具体窗口的WndProc,然后去调用,调用完成后继续下一个getmessage
转:一旦上面的工作完成了我们把消息传给DispatchMessage().DispatchMessage()先看
看信号是给哪个窗口的,再找到那个窗口的窗口过程. 再调用那个过程,参数为窗口
的句柄,消息,wParam和lParam.
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
WNDPROC fWndProc = (WNDPROC)GetWindowLong(Msg.hwnd, GWL_WNDPROC);
fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam);
}
毕竟on_command的宏就是产生一个结构体
windows提供了一个DefWindowProc的默认窗口消息处理,wndproc所有不想关心的消息都可以调用它来完成
当用户对菜单如File单击鼠标时,就产生一条WM_INITMENUPOPUP消息,边框窗口在菜单下拉之前响应该消息,从而更新该菜单所有项的状态。
在应用程序开始运行时,边框也会收到WM_INITMENUPOPUP消息。
当应用程序进入空闲处理状态时,将发送WM_IDLEUPDATECMDUI消息,导致所有的工具条用户对象的状态处理函数被调用,从而改变其状态。WM_IDLEUPDATECMDUI是MFC自己定义和使用的消息。
也可主动发送消息更新界面状态 PostMessage(WM_IDLEUPDATECMDUI, TRUE, 0);
MFC提供的缺省空闲处理向顶层窗口(框架窗口)的所有子窗口发送消息WM_IDLEUPDATECMDUI;MFC的控制窗口(工具条、状态栏等)实现了对该消息的处理,导致用户对象状态处理函数的调用。
框架的消息处理,就是通过oncmdmsg来转发的,childframe里会调用view->oncmdmsg,view会调用document->oncmdmsg
在窗口初始化时,工具条也会收到WM_IDLEUPDATECMDUI消息。