VC窗口启动隐藏时闪烁问题解决方法

来源:互联网 发布:金融投资网站源码 编辑:程序博客网 时间:2024/05/29 19:47
 最近由于项目需要,做了一个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,于是就有了文章开头我说的修改方法。

0 0
原创粉丝点击