您的位置:首页 > 其它

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

2013-01-18 21:40 731 查看
花了两三天在搞这些啊,顺便看了看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()中添加修改显示状态的代码并调用,此后窗口不再出现,故预计窗口难以恢复(未测试如何恢复窗口)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: