您的位置:首页 > 其它

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

2016-09-30 10:20 453 查看
 最近由于项目需要,做了一个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,于是就有了文章开头我说的修改方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐