VC窗口啓動隱藏時閃爍問題解決方法(原創)

VC窗口啓動隱藏時閃爍問題解決方法(原創)

       最近由於項目需要,做了一個VC托盤程序,讓該程序在後臺執行,當程序啓動時我需要將窗口隱藏,但總是在隱藏前會閃爍一下再隱藏,於是我跟蹤代碼到MFC類庫裏終於發現問題給解決了。

       下面都是針對創建的單文檔程序而講的,因爲我創建的是單文檔工程,其它的類型工程我沒試過,多文檔工程應該也可以用下面的方法,好了,開始講解了。

 

       如果你使用VC6做的單文檔程序,那麼只需在BOOL CXXXXApp::InitInstance()方法中添加如下代碼:

                    m_nCmdShow = SW_HIDE;
                    if (!ProcessShellCommand(cmdInfo))
                            return FALSE;

           即在"if (!ProcessShellCommand(cmdInfo))”在這一句的上方加一句代碼"m_nCmdShow = SW_HIDE;"即可

 

      如果使用VC2008建立的單文檔程序,那麼需要在BOOL CXXXXApp::InitInstance()方法中添加如下代碼:

                    m_nCmdShow = SW_HIDE;
                    m_bLoadWindowPlacement=FALSE;
                    if (!ProcessShellCommand(cmdInfo))
                               return FALSE;

            即在"if (!ProcessShellCommand(cmdInfo))”在這一句的上方加兩行代碼"m_nCmdShow = SW_HIDE;"和"m_bLoadWindowPlacement=FALSE;"

 

        大家可能覺得奇怪,爲什麼不一樣呢?

        原因是在VC2008建立的單文檔程序中,CXXXXApp默認繼承的CWinAppEx類,該類中新添加了一些處理。如果你在"if (!ProcessShellCommand(cmdInfo))”處打上斷點按F11,走到一個方法後繼續按F11跟蹤進去直到代碼走到下面這個方法:

       BOOL CWinAppEx::LoadState(LPCTSTR lpszSectionName /*=NULL*/, CFrameImpl* pFrameImpl /*= NULL*/)

       而在該方法中有下面一段代碼,問題就出在這裏:

       if (m_bLoadWindowPlacement)
      {
               //--------------------------------------------------------
               // Set frame default(restored) size:
               //--------------------------------------------------------
               ReloadWindowPlacement(pFrameImpl->m_pFrame);
      }

我們再繼續跟進BOOL CWinAppEx::ReloadWindowPlacement(CFrameWnd* pFrameWnd),其實現代碼如下:

BOOL CWinAppEx::ReloadWindowPlacement(CFrameWnd* pFrameWnd)
{
     ASSERT_VALID(pFrameWnd);

     CCommandLineInfo cmdInfo;
    AfxGetApp()->ParseCommandLine(cmdInfo);
    if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
    {
       //Don't show the main window if Application
       //was run with /Embedding or /Automation.
       return FALSE;
    }

    CRect rectNormal;
    int nFlags = 0;
    int nShowCmd = SW_SHOWNORMAL;
    BOOL bRet = FALSE;

    if (LoadWindowPlacement(rectNormal, nFlags, nShowCmd))
 {
  WINDOWPLACEMENT wp;
  wp.length = sizeof(WINDOWPLACEMENT);

  if (pFrameWnd->GetWindowPlacement(&wp))
  {
   wp.rcNormalPosition = rectNormal;
   wp.showCmd = nShowCmd;

   RECT rectDesktop;
   SystemParametersInfo(SPI_GETWORKAREA,0, (PVOID)&rectDesktop,0);
   OffsetRect(&wp.rcNormalPosition, -rectDesktop.left, -rectDesktop.top);

   pFrameWnd->SetWindowPlacement(&wp);

   bRet = TRUE;
  }
 }

 if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameWndEx)))
 {
  CDockingManager *pDockingManager = ((CMDIFrameWndEx *)pFrameWnd)->GetDockingManager();
  pDockingManager->ShowDelayShowMiniFrames(TRUE);
 }
 else if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CFrameWndEx)))
 {
  CDockingManager *pDockingManager = ((CFrameWndEx *)pFrameWnd)->GetDockingManager();
  pDockingManager->ShowDelayShowMiniFrames(TRUE);
 }

 return bRet;
}

       看我加了下劃線加粗的代碼行,發現我之前設置的"m_nCmdShow = SW_HIDE;"在這裏被更改,所以會閃爍,那麼看到這裏問題就可以解決了。

      我們發現之所以會進ReloadWindowPlacement方法,是因爲m_bLoadWindowPlacement=TRUE的原因,這個值在CWinAppEx的構造函數中初始化爲TRUE了,那麼我們就應該想辦法將m_bLoadWindowPlacement置爲FALSE,所以我們使用VC2008開發時就應該在調用ReloadWindowPlacement方法前把m_bLoadWindowPlacement置爲FALSE,於是就有了文章開頭我說的修改方法。

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