MFC對話方塊程式啟動的時候直接隱藏、在工作列不顯示圖示
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;
...
...
}
以上方法其實很簡單的,不知道為什麼在網上找不到資料。