MFC对话框初始化运行时如何隐藏,托盘图标,任务栏图标的相关问题

花了两三天在搞这些啊,顺便看了看MFC对话框的机制。


一、托盘图标

参见http://www.vckbase.com/index.php/wv/1167,《给托盘添加右击菜单……》

1. 添加托盘消息定义;在dlg类中添加变量,托盘消息响应函数的声明;在dlg类的cpp中手动添加托盘消息映射

	#define WM_NOTIFYICON WM_USER+5
	NOTIFYICONDATA nd;
	LONG CxxDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam);
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
END_MESSAGE_MAP()

2. 在dlg类的初始化函数BOOL CxxDlg::OnInitDialog()中,设计NotifyIcon结构并向系统shell添加托盘图标

	nd.cbSize= sizeof (NOTIFYICONDATA);
	nd.hWnd= m_hWnd;
	nd.uID= IDR_MAINFRAME;
	nd.uFlags= NIF_ICON|NIF_MESSAGE|NIF_TIP;
	nd.uCallbackMessage= WM_NOTIFYICON;
	nd.hIcon= m_hIcon;
	strcpy(nd.szTip, "Init Agent");

	Shell_NotifyIcon(NIM_ADD, &nd);

3. 在ClassWizard中重写dlg类的OnClose函数,并加入删除托盘图标语句

void CxxDlg::OnClose()
{
	Shell_NotifyIcon(NIM_DELETE, &nd); 
	
	CDialog::OnClose();
	DestroyWindow();	//一般要手动调用该函数才会使退出生效
}
4. 建立菜单及菜单响应函数
void CxxDlg::OnTrayShow() 
{
	ShowWindow( SW_SHOWNORMAL);
}
void CxxDlg::OnTrayHide() 
{
	ShowWindow( SW_HIDE);
}
void CxxDlg::OnTrayExit() 
{
	this->OnClose();
}
5.设计托盘消息响应函数,即消息响应与popup菜单编程

LONG CxxDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
	// 响应在托盘图标上的单击
	//wParam中是响应消息的图标ID,lParam中则是Windows的消息
    switch ( lParam )
    {
	case WM_RBUTTONDOWN:
		{
			// 用户在托盘图标上单击鼠标右键,弹出菜单	
			CMenu pMenu;
			if (pMenu.LoadMenu(IDR_TRAY))
			{
				CMenu* pPopup = pMenu.GetSubMenu(0);
				ASSERT(pPopup != NULL);
				CPoint Point;
				if (IsWindowVisible())// 根据对话框窗口的状态对相关菜单项使能
				{
					pPopup->EnableMenuItem(ID_TRAY_SHOW,MF_BYCOMMAND | \
					MF_DISABLED | MF_GRAYED);
				}
				else
					pPopup->EnableMenuItem(ID_TRAY_HIDE,MF_BYCOMMAND | 
					MF_DISABLED | MF_GRAYED);
				// 确定鼠标位置以便在该位置附近显示菜单
				GetCursorPos( &Point );
				SetForegroundWindow();
				pPopup->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON, Point.x, Point.y, this);
			}
		}
		break;
	case WM_LBUTTONDBLCLK:
	case WM_LBUTTONDOWN:
		if (IsWindowVisible())	ShowWindow( SW_HIDE);
		else	ShowWindow( SW_SHOWNORMAL);
		break;
    }
    return 0;
}      
微笑此节完成。


二、任务栏按钮

参见http://blog.sina.com.cn/s/blog_55f9aac5010096dv.html

1.在dlg类的初始化函数OnInitDialog()函数中添加下面这句,使对话框不在系统任务栏中显示。

ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);//改变样式为从app窗口到工具窗,从而不会在任务栏中显示。
2.在需要 显示 对话框的函数中添加下句,使对话框显示在系统任务栏中。

ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);


三、初始化运行时即隐藏

参见上篇及http://bbs.csdn.net/topics/350105993#post-352053344,6楼

假如永远都不需要显示,解决方案不少。比较经济的是直接在dlg类现有的OnPaint()函数中添加ShowWindow(SW_HIDE);。

下文讨论前提:窗口完好的存在,只是初始化运行之后不显示出来,但后来仍可以调动出来。最优的解决方案就是在窗口响应函数中重写WM_NCPAINT消息的处理过程,见后文。

如果不严格要求,即允许初始化运行时一闪而过的现象,那么解决方案如下:

0. 改用非模态对话框。在app类的InitInstance里面Create非模态dlg,再ShowWindow(SW_HIDE); 并调用消息循环函数

	CxxDlg dlg;
	m_pMainWnd = &dlg;
	dlg.Create( IDD_INITAGENT_DIALOG );
	dlg.ShowWindow(SW_HIDE);
	INT_PTR nResponse = dlg.RunModalLoop();


如果要求最开始根本不出现窗口,有以下几种处理:

1. 见上帖6#。重写dlg类的DefWindowProc()函数,对WM_NCPAINT消息进行改变。

LRESULT CxxDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	static int i=3;		//此处因为多一次恢复任务栏按钮的操作,故2+1->3;如果使用非模态对话框,则少一次ShowWindow,即i<- 2
	// TODO: Add your specialized code here and/or call the base class
	if(message==WM_NCPAINT && i)
	{
		if(i==1)	//这一次需要是用户调用的,用来先恢复窗口在系统任务栏的显示。
			ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);
		else	//最开始的一或两次WM_NCPAINT是由系统调用的,在此加以阻止。
			ShowWindow(SW_HIDE);
		i--;
		return 0;
	}
	return CDialog::DefWindowProc(message, wParam, lParam);	//无视其作用
}
2.见上帖11#。重写WM_WINDOWPOSCHANGING消息,改变某些指示标志。(未测试。貌似需手工添加消息映射)
3. 见 http://bbs.csdn.net/topics/360201943#post-371035442,13#。在dlg类的OnInitDialog()中添加修改显示状态的代码并调用,此后窗口不再出现,故预计窗口难以恢复(未测试如何恢复窗口)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值