您的位置:首页 > 其它

MFC窗口隐藏 --对话框--单文档

2012-09-07 16:33 357 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: