MFC窗口隱藏
因爲最近我的不良網頁過濾引擎--上帝之手的開發進入實際開發階段,因此開始了很多方面的系統編程比如說進程隱藏,窗口隱藏等等,因爲這是監控類的軟件,最好是運行在用戶不知情的情況下,所以最好是把窗口隱藏起來,然後通過hotkey來呼喚.在如何實現窗口隱藏的時候,我可以說是費盡周章.
一開始,我想到的是在CMainFrame裏的OnCreate寫上一句this->ShowWindow(SW_HIDE);,問題倒是得到了解決,但是卻出現一閃而過的現象,的確是很不完美.然後我開始在網上找資料,但都有這樣的問題,而且有關於窗口隱藏的很多都是基於Dialog的.我決定自己再研究研究.
於是我建立了一個新的空項目,仔細的看代碼,發現在CXXApp::InitInstance()裏有這麼一句:m_pMainWnd->ShowWindow(SW_SHOW);咦,這不是顯示主窗口的意思嗎?我把它註釋掉不就得了,說幹就幹,註釋,編譯,運行,我靠,窗口還是正常出現似乎跟這個語句無關啊.
這麼說來就是在執行這個語句之前窗口已經顯示出來了.因此我在這個語句前面的如下代碼段設了斷點:
if (!ProcessShellCommand(cmdInfo))
return FALSE;
跟蹤進去,發現:
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)
{
BOOL bResult = TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
///////////////////////////////////////////////.
............
break;
// If we've been asked to open a file, call OpenDocumentFile()
case CCommandLineInfo::FileOpen:
.......................
break;
// If the user wanted to print, hide our main window and
// fire a message to ourselves to start the printing
case CCommandLineInfo::FilePrintTo:
case CCommandLineInfo::FilePrint:
m_nCmdShow = SW_HIDE;
ASSERT(m_pCmdInfo == NULL);
OpenDocumentFile(rCmdInfo.m_strFileName);
m_pCmdInfo = &rCmdInfo;
m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);
m_pCmdInfo = NULL;
bResult = FALSE;
break;
// If we're doing DDE, hide ourselves
請注意紅色的那句,我發現 case CCommandLineInfo::FileNew:時是沒有這執行這一句的,因此我想能不能通過這一句實現窗口隱藏呢?
於是我在
if (!ProcessShellCommand(cmdInfo))
return FALSE;
的面面加上一句 m_nCmdShow = SW_HIDE;
然後編譯,運行,窗口不見了!!!也沒有出現一閃而過的情況,我成功了!
2------------
void CtDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
if (lpwndpos->flags & SWP_SHOWWINDOW)
{
lpwndpos->flags &= ~SWP_SHOWWINDOW;
PostMessage(WM_WINDOWPOSCHANGING, 0, (LPARAM)lpwndpos);
ShowWindow(SW_HIDE);
}
else
CDialog::OnWindowPosChanging(lpwndpos);
}
http://blog.csdn.net/lanphaday/archive/2008/12/15/3519303.aspx
3.
.隱藏基於對話框的MFC應用程序窗口的方法 (推薦這個方法,非常好用)
很多人可能會將窗口創建出來,然後用一個ShowWindow(SW_HIDE)的方法去隱藏窗口,當然這是可以做到隱藏的功能,但是有一點不足的地方就是窗口在隱藏之前會有一下短瞬的閃爍,而以下這種方法可以解決這種問題:
在C***App::InitInstance()的函數中將以下的這一段註釋掉:
C***Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
換成:
C***Dlg *dlg = new C***Dlg;
m_pMainWnd = dlg;
return dlg->Create(IDD_***_DIALOG);
同時將IDD_***_DIALOG的對話框資源的"More Stytles"屬性頁的Visible屬性的勾去掉即可.
這是我認爲最簡單的一種方法,還有另外一種方法,就是在工作區的資源菜單中插入一個新的對話框,然後用ClassWizard新建一個與之對應的類, 而下面
C***Dlg *dlg = new C***Dlg;
m_pMainWnd = dlg;
return dlg->Create(IDD_***_DIALOG);
這裏的C***Dlg和IDD_***_DIALOG改爲與你新建的對話框的對應即可,方法的原理與上面的一樣,只是麻煩了一點點而已.
2.隱藏基於單文檔的MFC應用程序窗口的方法
1) 最簡單的方法是從網上的找到的:
"CMainFrame::ActiveFrame()
{
nCmdShow= SW_HIDE;
CFrameWnd::ActivateFrame(nCmdShow);
}
C??App::Initstance()
{
m_pMainWnd->ShowWindow(SW_HIDE);
//UpdateWindow();
}
因爲 MFC
有兩個步驟來顯示 SDI 主窗口, 所有必須在這兩個地方都 SW_HIDE, 否則就會閃動.
即便 HWND 沒有 WS_VISIBLE 屬性, 用ShowWindow(SW_SHOW) 還是可以顯示該 HWND 的. 所以vcbear的方法有問題. "
這裏的ActiveFrame函數可以在ClassWizard中添加.
2)第二種方法則相對繁瑣得多
第一步,將CMainFrame的構造函數改爲public屬性(默認是protected的)
第二步,將C***App::InitInstance()裏面的下面代碼註釋掉:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestHideDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CTestHideView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
換成以下的代碼:
m_pMainWnd = new CMainFrame();
BOOL bRet = ((CMainFrame *)m_pMainWnd)->LoadFrame(IDR_MAINFRAME);
if (bRet)
{
m_pMainWnd->UpdateWindow();
}
else
{
if (m_pMainWnd)
{
delete m_pMainWnd;
m_pMainWnd = NULL;
}
}
這樣子編繹出來的程序運行時便不會有主窗口.
縱觀上面的隱藏窗口的方法,除了使用ShowWIndow(SW_HIDE)的方法之外,其實都是將程序中m_pMainWnd指針換一下面目,原來是正常顯示的,就改爲不顯示,或者用其它的對話框或者自身新建一個不同類別的框架指針.
我一開始的疑惑是既然C***App會有自已的線程和消息循環機制,那麼爲什麼還必要要這麼一個框架類CMainFrame作爲它的支撐呢?後來查了一下源碼發現在C***App類的Run()函數裏面有這麼一段(關於Run函數這裏不做詳細講解,有興趣可以去查看"深入淺出MFC"):
int CWinApp::Run()
{
if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
{
// Not launched /Embedding or /Automation, but has no main window!
TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
AfxPostQuitMessage(0);
}
return CWinThread::Run();
}
呵呵,原來只要m_pMainWnd不爲NULL, 則主線程就可以轉起來.至此,所有的問題就迎刃而解.
http://hi.baidu.com/diqiucun666/blog/item/bd044daf720b84fdfbed5075.html