MFC窗口隱藏 --對話框--單文檔

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章