|
现在很多程序都有托盘功能,下面介绍一下如何在VC下实现托盘程序的功能:
1.准备一个菜单
菜单有两上项“显示”和“退出”。
菜单的名为“托盘菜单”ID为:IDR_MENU_TRAY,两个项分别为:IDR_MENU_SHOW,IDR_MENU_EXIT。
2.初始化托盘
(1)源代码
void CSmsDlg::InitTray()
{
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd=this->m_hWnd;
nid.uID=IDR_MAINFRAME;
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage=WM_NOTIFYICON;//自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"东讯短信平台");//信息提示
Shell_NotifyIcon(NIM_ADD,&nid);//在托盘区添加图标
}
(2)消息的定义#define WM_NOTIFYICON WM_USER+5,一般放在头文件的开始。
(3)所有到的变量 NOTIFYICONDATA nid; 一般在头文件中定义。
(4)初始化托盘函数一般在初始化对话框函数中引用或在单文档中int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)引用。
3.响应托盘消息函数
(1)源代码
LONG CSmsDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
//wParam中是响应消息的图标ID,lParam中则是Windows的消息
CMenu pMenu;
switch ( lParam )
{
case WM_RBUTTONDOWN:// 用户在托盘图标上单击鼠标左、右键,弹出菜单
case WM_LBUTTONDOWN:
if (pMenu.LoadMenu(IDR_MENU_TRAY))
{
CMenu* pPopup = pMenu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CPoint Point;
//if(IsIconic()) pPopup->EnableMenuItem(IDC_MIN,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
if (IsWindowVisible())
{// 根据对话框窗口的显示/隐藏状态修改菜单名称
if(!IsIconic())
pPopup->EnableMenuItem(IDR_MENU_SHOW,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
//else
// pPopup->EnableMenuItem(ID_MENUITEM_HIDE,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
// 确定鼠标位置以便在该位置附近显示菜单
GetCursorPos( &Point );
SetForegroundWindow();
pPopup->TrackPopupMenu(
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
Point.x, Point.y, this);
}
break;
case WM_LBUTTONDBLCLK:
OnMenuShow();
break;
default:
break;
}
return 0;
}
(2)在头文件中定义函数
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CSmsDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
virtual void OnOK();
afx_msg void OnMenuShow();
afx_msg void OnMenuExit();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg LONG OnNotifyIcon(WPARAM wParam, LPARAM lParam);//定义的一个
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
(3)在源文件中响应消息
BEGIN_MESSAGE_MAP(CSmsDlg, CDialog)
//{{AFX_MSG_MAP(CSmsDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(IDR_MENU_SHOW, OnMenuShow)
ON_COMMAND(IDR_MENU_EXIT, OnMenuExit)
ON_WM_SIZE()
ON_WM_CANCELMODE()
ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)//手工添加托盘消息映射
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
4.菜单函数的添加
(1)托盘显示菜单
void CSmsDlg::OnMenuShow()
{
// TODO: Add your command handler code here
ShowWindow(SW_SHOWNORMAL);
}
(2)托盘退出菜单
void CSmsDlg::OnMenuExit()
{
// TODO: Add your command handler code here
Shell_NotifyIcon(NIM_DELETE, &nid);
CDialog::OnCancel();
}
2007.9.5添加
1.不在下边的状态栏显示
在OnSize中添加下列代码
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (nType == SIZE_MINIMIZED)
ShowWindow(SW_HIDE);
}
2.关闭时不关闭,显示托盘
(1)基于对话框的将OnSysCommand的代码改为下边的代码
void CSmsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else if ((nID & 0xFFF0)==SC_CLOSE)
{
ShowWindow(SW_HIDE);//系统菜单的关闭也改为隐藏。
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
(2)基于单文档将OnClose的代码改为下边的代码
//关闭对话框 2007.09.10
void CMainFrame::OnClose()
{
// TODO: Add your message handler code here and/or call default
//InitTray();
ShowWindow(SW_HIDE);//系统菜单的关闭也改为隐藏。
//CFrameWnd::OnClose();
}
|
|