最近需要做一个主窗体常态隐藏的程序,类似360卫士那样,只有托盘图标常显示。本以为隐藏主窗体很简单,但遇到了意想不到的情况。

无效的做法

  最初的想法是设置主对话框资源的
Visiable 属性为 false, 并在OnInitDialog函数里调用ShowWindow(SW_HIDE) ,发现这些操作根本没有作用,对话框还是好好的显示在那里。开始还以为是改错了项目,或者当前启动项目设置错了,检查了一遍,确认没错,只好开始百度。

  最初发现的解决方法是在OnInitDialog函数中执行以下代码:

SetWindowPos(&wndNoTopMost,0,0,0,0,SWP_HIDEWINDOW);

ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);//移除任务栏图标显示

ShowWindow(SW_HIDE);

  结果是窗体的大部分隐藏了,还剩了点没隐藏,就是下图这个要死不活的样子

  

  既然还剩了一部分,那我就把对话框资源的
Caption 属性为空,SystemMenu属性设置为false,结果文字和关闭按钮确实都不见了,但还是剩下了一些东西,就是下图中的小长条

  只能继续研究。

有效的做法

  1 将界面像素置为0,移动界面至屏幕角落

int nFullWidth = GetSystemMetrics(SM_CXSCREEN);

int nFullHeight = GetSystemMetrics(SM_CYSCREEN);

SetWindowPos(NULL, nFullWidth, nFullHeight,
0, 0, SWP_NOZORDER); //设置0像素,移到最角落
或者:MoveWindow(0,0,0,0);

ShowWindow(SW_HIDE);

ModifyStyleEx(WS_EX_APPWINDOW,
WS_EX_TOOLWINDOW); //移除任务栏图标显示

  这种做法只是将上述的小长条移到了不易看到的地方,用户一旦操作界面的任一部位,窗口都会因为失活而不再显示,达到了隐藏界面的目的。但是这种做法明显属于凑合,而且一旦需要显示主界面,还需要将对话框的类型改回来,不能为工具窗口,否则任务栏不显示。

  2 采用定时器,在窗口初始化完成后马上隐藏

  在OnInitDialog中创建一个定时器SetTimer(1,1,NULL);

  然后在OnTimer函数中调用ShowWindow(SW_HIDE)

  这种做法的缺点就是窗口会闪烁一次,而且这种手法太野路子,不优雅。

  3 响应WM_NCPAINT消息

   在第一次处理WM_NCPAINT消息是,调用ShowWindow(SW_HIDE)方法,之所以只调用一次,是为了之后可以将主窗口再显示出来。

   这种方法比较优雅,推荐采用

void CMFCApplication1Dlg::OnNcPaint()

{

// TODO: 在此处添加消息处理程序代码

static bool bNotPaint = true;

if (bNotPaint)

{

ShowWindow(SW_HIDE);

bNotPaint = false;

}

else

{

CDialogEx::OnNcPaint();

}

}

  4改变主窗体的创建方式

    将C***App::InitInstance()
函数中的代码

CMFCApplication1Dlg
dlg;

m_pMainWnd =
&dlg;

INT_PTR nResponse
= dlg.DoModal();

  替换为

CMFCApplication1Dlg
dlg;

m_pMainWnd =
&dlg;

//INT_PTR
nResponse = dlg.DoModal();

INT_PTR nResponse
= dlg.Create(CMFCApplication1Dlg::IDD);

dlg.ShowWindow(SW_HIDE);

dlg.RunModalLoop();

  同样比较优雅,推荐使用

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。ks10086520@foxmail.com