RT
解决方案 »
- PICTURE CONTROL控件的问题
- 网络为什么还有名称呢?
- SelectClipRgn和IntersectClipRect的疑问。
- ComboBOX的问题
- COleDateTime在Unicode下,Format函数会有问题。
- 初学者,MessageBox显示问题
- 请问如何获得stl格式文件中部分三角片的轮廓?
- 请教Windows编程高手:如何编写一个应用程序,控制另外的应用程序?
- 在vc中如何实现命令行功能,比如;net send 192.168.0.1如何实现
- 如何能不用MFC创建ActiveX控件?
- 【原创&交流】二维图形旋转的实现
- 使用VS2008调试时 程序跳转出错 的原因 来着有分 等答复
消息循环也都存在
一. 非模态对话框的模板必须具有Visible风格(Visible=True),否则对话框将不可见,而模态对话框则无需设置该项风格。在实际编程中更加保险的办法是调用CWnd::ShowWindow(SW_SHOW)来显示对话框,而不管对话框是否具有Visible风格。
二. 非模态对话框对象是用new操作符来动态创建的,而不是以成员变量的形式嵌入到别的对象中或以局部变量的形式构建的。通常应在对话框的拥有者窗口类内声明一个指向对话框类的指针成员变量,通过该指针可访问对话框对象。
三. 通过调用CDialog::Create函数来启动对话框,而不是CDialog::DoModal,这是两者之间区别的关键所在。由于Create函数不会启动新的消息循环,对话框与应用程序共用同一个消息循环,这样对话框就不会垄断用户输入。Create在显示了对话框后就立即返回,而DoModal是在对话框被关闭后才返回的。由于在Create返回后,不能确定对话框是否已关闭,这样也就无法确定对话框对象的生存期,因此只好在堆栈中构建对话框对象,而不能以局部变量的形式来构建之。
四. 必须调用CWnd::DestroyWindow而不是CDialog::EndDialog来关闭非模态对话框。调用CWnd::DestroyWindow是直接删除窗口的一般方法。由于缺省的CDialog::OnOK和CDialog::OnCancel函数均调用EndDialog,故程序员必须编写自己的OnOK和OnCancel函数并且在函数中调用DestroyWindow来关闭对话框。
五. 因为是用new操作符构建非模态对话框对象,因此必须在对话框关闭后,用delete操作符删除对话框对象。在屏幕上一个窗口被删除后,框架会调用CWnd::PostNcDestroy,这是一个虚拟函数,程序可以在该函数中完成删除窗口对象的工作,具体代码如下
void CModelessDialog::PostNcDestroy
{delete this; //删除对象}
这样,在删除屏幕上的对话框后,对话框对象将被自动删除。拥有者就不必显式地调用delete来删除对话框对象了。
六. 必须有一个标志表明非模态对话框是否打开的。这样做的原因是用户有可能在打开一个模态对话框的情况下,又一次选择打开命令。程序根据标志来决定是打开一个新的对话框,还是仅仅把原来打开的对话框激活。通常可以用拥有者窗口中的指向对话框对象的指针作为这种标志,当对话框关闭时,给该指针赋NULL值,以表明对话框对象已不存在了。
例如:
创建模态对话框
CTestDlg dlg;
dlg.DoModal();
创建非模态对话框
CTestDlg * dlg = new CTestDlg;
dlg->Create(IDD_TEST_DLG);
dlg->ShowWindow(SW_SHOW);
(wincore.cpp)
MSG *pMsg = AfxGetCurrentMessage(); // acquire and dispatch messages until the modal state is done
for (;;)
{
ASSERT(ContinueModal()); // phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
{
ASSERT(ContinueModal()); // show the dialog when the message queue goes idle
if (bShowIdle)
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
} // call OnIdle while in bIdle state
if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
{
// send WM_ENTERIDLE to the parent
::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
}
if ((dwFlags & MLF_NOKICKIDLE) ||
!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
{
// stop idle processing next time
bIdle = FALSE;
}
} // phase2: pump messages while available
do
{
ASSERT(ContinueModal()); // pump message, but quit on WM_QUIT
if (!AfxPumpMessage())
{
AfxPostQuitMessage(0);
return -1;
} // show the window when certain special messages rec'd
if (bShowIdle &&
(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
} if (!ContinueModal())
goto ExitModal; // reset "no idle" state after pumping "normal" message
if (AfxIsIdleMessage(pMsg))
{
bIdle = TRUE;
lIdleCount = 0;
} } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}PeekMessage从线程消息队列里取消息pMsg,消息格式为:
(wpytes.h)
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
很清楚消息包含你做操作的窗口句柄,所以一个线程里的所有窗口是共享一个消息循环!