您的位置:首页 > 其它

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

2009-12-24 15:16 585 查看
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,于是就有了文章开头我说的修改方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐