时下流行的许多软件,如QQ,迅雷等,启动主程序以及主窗口最小化时,不在任务栏上显示按钮,这是怎么做到的呢?
首先说主窗口启动时不再任务栏上显示按钮的问题
方法1,将主窗口的属性设置为WS_EX_TOOLWINDOW,MSDN给的解释是创建一个工具窗口,用作浮动工具栏。工具窗口拥有比正常窗口短一些的标题栏,并且标题栏的字体也要小一些,工具栏窗口不会在任务栏中出现,也不会在用户按下Alt+Tab进行窗口切换时显示出来
通过这种方法可以比较简单的实现这个功能,但是这种方法存在一定的缺陷,具体后面分析。
方法2,创建一个隐形的窗口,然后将主窗口设置为隐形窗口的子窗口,注意:主窗口销毁后,将隐形窗口也销毁掉
方法1示例如下:
BOOL CXXXDlg::OnInitDialog()
{
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW); //这句话改变窗口的属性,也可以在窗口的创建int CXXXDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)或者预创建函数BOOL CXXXDlg::PreCreateWindow(CREATESTRUCT& cs) 中进行类似的处理
return TRUE;
}
这个方法,比较简单,快捷,但是有个缺点,如果你的窗口是有标题栏的,那么你的窗口的标题栏以及标题栏上的字体比正常的要小一些。
另外还有一个bug,这个bug在QQ2008中也存在(QQ2008主窗口就是这样的一个无标题的对话框,带有WS_EX_TOOLWINDOW属性),属于必现的bug(这个bug在QQ2009PreView版本中已经得到解决),重现方法如下:
1,将QQ2008系统设置中的“主窗口保持前端显示”选项前面的勾去掉
2.打开IE或者其他窗口,然后最大化该窗口,为方便叙述,将其称为窗口A
3.将QQ2008主界面(窗口B)显示在窗口A上
4.打开任意一个聊天窗口(窗口C),将其拉到屏幕中不与窗口B相交的地方
5.最小化窗口C
期望结果:
窗口B依然保持在屏幕上显示
实际结果:
窗口B不见了(实际上是跑到窗口A后面去了)
方法2示例如下:
首先,将对话框资源文件中的对话框属性中的"EXSTYLE WS_EX_APPWINDOW"这句话去掉,(和ModifyStyleEx(WS_EX_APPWINDOW,0)一样的效果)
然后,在你的CXXXApp类中定义一个CWnd类型的成员变量m_wndOwner
在你的主程序入口处,CXXXApp::InitInstance中加入如下代码
BOOL CXXXApp::InitInstance()//MFC应用程序框架的InitInstance函数,用于MFC程序启动执行必要的初始化
{
...
if ( m_wndOwner.m_hWnd == NULL )
{
LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
if ( !m_wndOwner.CreateEx(0, pstrOwnerClass, _T(""), //创建一个隐藏的弹出样式的窗口
WS_POPUP, CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, 0) )
return FALSE;
}
CXXXDlg dlg(&m_wndOwner);
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用“确定”来关闭
//对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用“取消”来关闭
//对话框的代码
}
if (m_wndOwner.m_hWnd != NULL)
m_wndOwner.DestroyWindow();
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}
接着你需要截获对话框的最小化事件和关闭事件,响应WM_SYSCOMMAND消息,在其中对SC_MINIMIZE以及SC_CLOSE事件进行处理,隐藏窗口,并在托盘区显示(托盘显示的例子很多,我就不加以说明了)
这样一切搞定了,你已经拥有了一个启动以及主窗口最小化时不在任务栏上显示的程序