2011-06-19
以前做一个项目,要求程序启动的时候主对话框是隐藏的。当时不知道怎么做,修改窗口风格、窗口类、OnInitDialog里ShowWindow、Create函数、WM_CREATE消息、PreCreateWindow等等都尝试了,没什么用,相当郁闷。后来有在网上找到一个解决方案,算是解决了当时的燃眉之急,但是我觉得这个方案并不令人满意,至少我觉得它太复杂了。
下面是网上搜索到的解决方案:(现在也不知道是出自哪里了)
//===========================================================
要想使 MFC对话框程序启动的时候直接隐藏(或者最小化到tray)有如下办法
1 在OnInitDialog ()中
SetTimer(1,100,null)
在OnTimer(UINT nIDEvent) 中
if( nIDEvent==1)
{
ShowWindow(sw_hide);
KillTimer(1);
}
///这种方法 会出现 程序在显示器上 闪一下的效果。。即使 timer 时间很短 ,也会有。
2 重载 WM_WINDOWPOSCHANGING
在重载函数内实现:
OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if( !m_bShowWindow)
lpwndpos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpwndpos);
// TODO: Add your message handler code here
}
m_bShowWindow 是我的一个变量,初始值为false
// 如果 m_bShowWindow 一直为false ,那么程序就见不到人了。。
所以应该给 True
在OnInitDialog ()中
SetTimer(1,1000,null)
在OnTimer(UINT nIDEvent) 中
if( nIDEvent==1)
{
m_bShowWindow =true;
KillTimer(1);
}
//使用这种方法 程序不会闪一下。。。
//===========================================================
一个偶然的机会,在研究用什么方法让任务栏不显示图标时终于发现了这个问题的最终应该也是最正确的解决方案。
原来MFC对话框主窗口是在WinApp的InitInstance里创建的。
新建一个名为OkCancel的MFC对话框程序,默认的theApp.InitInstance代码是:
COkCancelApp theApp;
BOOL COkCancelApp::InitInstance()
{
...
...
COkCancelDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal(); //使用的是DoModal方法,所以就是为什么对话框总是显示了
...
...
}
把以上代码修改成自建消息循环的代码:
BOOL COkCancelApp::InitInstance()
{
...
...
COkCancelDlg* pd=new COkCancelDlg;
m_pMainWnd=pd;
/*这行代码不知道有多少用处,不设置也没多少影响。如果设置了m_pMainWnd那么在程序退出之前会自动调用m_pMainWnd->DestroyWindow()函数,但是这种机制在这里可能会造成错误,所以在后面还要把m_pMainWnd设置为0
它是::AfxGetMainWnd()正确返回主窗口CWnd指针的前提。或许这个变量可以在别的方面大做文章*/
pd->Create(IDD_OKCANCEL_DIALOG); //编辑对话框时设置为首次不可见,或者调用ShowWindow(0),但是后者效果不好
MSG msg;
while(::GetMessage(&msg,pd->m_hWnd,0,0)) //GetMessage还有因为错误返回-1的情况,但是这里暂时不理会这种情况
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
pd->DestroyWindow();
delete pd;
m_pMainWnd=0;
...
...
}
以上的消息循环其实就是标准的Win32程序的消息循环。
但是以上代码会造成对话框在点关闭后只是隐藏而不是关闭,那么就要在对话框类里需要退出的位置向自己发送WM_QUIT消息,一般可以选择在OnCancel()函数里:
void COkCancelDlg::OnCancel()
{
CDialog::OnCancel();
this->PostMessage(WM_QUIT,0,0); //最好放在CDialog::OnCancel()的后面,但是这里不能由PostQuitMessage代替,不知道为什么。
}
----------------------------------------------------------------------------------------------------
另外隐藏任务栏图标,像QQ的做法就是创建一个隐藏的窗口,再以它为父窗口创建一个对话框窗口(虽然设置为工具栏风格也可以,但那样有猪多不爽)。我们的MFC对话框程序可以这么做:
BOOL COkCancelApp::InitInstance()
{
...
...
CDialog* pd=new CDialog;
pd->Create(IDD_DIALOG1); //IDD_DIALOG1是一个不显示的对话框资源ID
COkCancelDlg dlg(pd);
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
pd->DestroyWindow();
delete pd;
...
...
}
以上方法其实很简单的,不知道为什么在网上找不到资料。