MFC程序员WTL指南(3)WTL界面基类
2008-01-19 20:26:39 来源:WEB开发网CMessageLoop为我们的应用程序提供一个消息泵,除了一个标准的DispatchMessage/TranslateMessage循环外,它还通过调用PreTranslateMessage()函数实现了消息过滤机制,通过调用OnIdle()实现了空闲处理功能。下面是Run()函数的伪代码:
int Run()
{
MSG msg;
for(;;)
{
while ( !PeekMessage(&msg) )
DoIdleProcessing();
if ( 0 == GetMessage(&msg) )
break; // WM_QUIT retrieved from the queue
if ( !PreTranslateMessage(&msg) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
那些需要过滤消息的类只需要象CMainFrame::OnCreate()函数那样调用CMessageLoop::AddMessageFilter()函数就行了,CMessageLoop就会知道该调用那个PreTranslateMessage()函数,同样,如果需要空闲处理就调用CMessageLoop::AddIdleHandler()函数。
需要注意得是在这个消息循环中没有调用TranslateAccelerator() 或 IsDialogMessage() 函数,因为CFrameWindowImpl在这之前已经做了处理,但是如果你在程序中使用了非模式对话框,那你就需要在CMainFrame::PreTranslateMessage()函数中添加对IsDialogMessage()函数的调用。
CFrameWindowImpl 的内部实现CFrameWindowImpl 和它的基类 CFrameWindowImplBase提供了对toolbars,rebars, status bars,工具条按钮的工具提示和菜单项的掠过式帮助,这些也是MFC的CFrameWnd类的基本特征。我会逐步介绍这些特征,完整的讨论CFrameWindowImpl类需要再写两篇文章,但是现在看看CFrameWindowImpl是如何处理WM_SIZE和它的客户区就足够了。需要记住一点前面提到的东西,m_hWndClient是CFrameWindowImplBase类的成员变量,它存储主窗口内的“视图”窗口的句柄。
CFrameWindowImpl类处理了WM_SIZE消息:
LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(wParam != SIZE_MINIMIZED)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
bHandled = FALSE;
return 1;
}
它首先检查窗口是否最小化,如果不是就调用UpdateLayout(),下面是UpdateLayout():
void UpdateLayout(BOOL bResizeBars = TRUE)
{
RECT rect;
GetClientRect(&rect);
// position bars and offset their dimensions
UpdateBarsPosition(rect, bResizeBars);
// resize client window
if(m_hWndClient != NULL)
::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
注意这些代码是如何使用m_hWndClient得,既然m_hWndClient是一般窗口的句柄,它就可能是任何窗口,对这个窗口的类型没有限制。这一点不像MFC,MFC在很多情况下需要CView的派生类(例如分隔窗口类)。如果你回过头看看CMainFrame::OnCreate()就会看到它创建了一个视图窗口并赋值给m_hWndClient,由m_hWndClient确保视图窗口被设置为正确的大小。
更多精彩
赞助商链接