我想写一个程序具有任务栏图标的功能,并且在鼠标右键单击时能弹出菜单,但是不知为何菜单无法弹出,请大家帮忙看看。
我的具体操作如下: 1.我用VC建立了一个对话框程序命名为TEST
2.添加NOTIFYICONDATA类型的成员变量 tnd。
然后调用Shell_NotifyIcon创建了一个任务栏图标程序。将如下代码写在OnInitDialog()中 NOTIFYICONDATA tnd;
tnd.cbSize=sizeof(NOTIFYICONDATA);
tnd.hWnd=this->m_hWnd;
tnd.uID=IDI_TEST;
tnd.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage=WM_POPMENU;
tnd.hIcon=LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_TEST));
strcpy(tnd.szTip,"提示信息");
Shell_NotifyIcon(NIM_ADD,&tnd);
3.手动添加了WM_POPMENU消息,创建消息响应函数OnPopmenu,创建IDI_TEST菜单资源
4.在OnPopmenu函数中添加如下代码:
if(wParam!=tnd.uID || (lParam!=WM_RBUTTONUP && lParam!=WM_LBUTTONDBLCLK))
{
return 0;
}
CMenu menu;
if(!menu.LoadMenu(tnd.uID))
{
return 0;
} CMenu* pSubMenu=menu.GetSubMenu(0);
if(!pSubMenu)
{
return 0;
} if(lParam==WM_RBUTTONUP)
{
::SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE);
CPoint mouse;
GetCursorPos(&mouse);
::SetForegroundWindow(tnd.hWnd);
::TrackPopupMenu(pSubMenu->m_hMenu,0,mouse.x,mouse.y,0,tnd.hWnd,NULL);
}
我的具体操作如下: 1.我用VC建立了一个对话框程序命名为TEST
2.添加NOTIFYICONDATA类型的成员变量 tnd。
然后调用Shell_NotifyIcon创建了一个任务栏图标程序。将如下代码写在OnInitDialog()中 NOTIFYICONDATA tnd;
tnd.cbSize=sizeof(NOTIFYICONDATA);
tnd.hWnd=this->m_hWnd;
tnd.uID=IDI_TEST;
tnd.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage=WM_POPMENU;
tnd.hIcon=LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_TEST));
strcpy(tnd.szTip,"提示信息");
Shell_NotifyIcon(NIM_ADD,&tnd);
3.手动添加了WM_POPMENU消息,创建消息响应函数OnPopmenu,创建IDI_TEST菜单资源
4.在OnPopmenu函数中添加如下代码:
if(wParam!=tnd.uID || (lParam!=WM_RBUTTONUP && lParam!=WM_LBUTTONDBLCLK))
{
return 0;
}
CMenu menu;
if(!menu.LoadMenu(tnd.uID))
{
return 0;
} CMenu* pSubMenu=menu.GetSubMenu(0);
if(!pSubMenu)
{
return 0;
} if(lParam==WM_RBUTTONUP)
{
::SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE);
CPoint mouse;
GetCursorPos(&mouse);
::SetForegroundWindow(tnd.hWnd);
::TrackPopupMenu(pSubMenu->m_hMenu,0,mouse.x,mouse.y,0,tnd.hWnd,NULL);
}
解决方案 »
- 关于MFC的Dialog
- 下载图片,调用URLDownloadToFile几次后死机?
- 网页如何调用dll,大大给点思路
- sdk image控件刷新问题
- 关于操作ocx控件的一个问题,麻烦各位看看
- 读取Ftp服务器上的文件信息为何出错?
- xml 4.0sdk和3.0有何区别
- 请问怎么在启动时将listcontrol里的第一行数据加亮显示(即选中状态)!
- 简单问题请教: 一个ListCtrl控件放在一个Edit控件上面。为什么在Edit控件的位置处会显示一个编辑提示光标。
- 我原来一直用VB和ASP,形势所迫,现在不得不学VC了,不过听说VC很难学,各位高手有什么建议吗?
- 用 pCMainFrame->Create(NULL,_T("测试"),WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL);弹出子窗口后,怎样在子窗口中获取父窗口的句柄?
- 基于微软Speech SDK 5.1 语音识别配置文件的问题
#define WM_POPMENU WM_USER+1
利用向导加一个XXXX::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_POPMENU :
if(lParam==WM_LBUTTONDBLCLK){ ...}
else if(lParam==WM_RBUTTONDOWN){...}
else if(){}
...
break;}
return CDialog::WindowProc(message, wParam, lParam);
}
{
//在系统托盘上点击右键。
if (LOWORD(lParam) == WM_RBUTTONUP)
{
POINT pt;
GetCursorPos(&pt);
//在系统托盘中的弹出菜单。
GetMenu()->GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, this);
}
return 0;
}
{
switch(message)
{
case WM_POPMENU : //如果是用户定义的消息
if(lParam == WM_LBUTTONDOWN)
{
ShowWnd();//显示窗口
} else if(lParam == WM_RBUTTONDOWN) //鼠标右键单击弹出选单
{
CMenu menu;
menu.LoadMenu(IDR_TRAY_MENU); //载入事先定义的选单
CMenu *pMenu = menu.GetSubMenu(0);
if(pMenu != NULL)
{
CPoint pos;
GetCursorPos(&pos);
SetForegroundWindow();
pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, pos.x, pos.y, this);
} PostMessage(WM_NULL, 0, 0); //这样可能除去当失去焦点时,菜单不取消的问题
}
return 0;
break;
case WM_SYSCOMMAND: //如果是系统消息
if(wParam == SC_MINIMIZE) //接收到最小化消息时主窗口隐藏
{
ShowWnd(false);//隐藏窗口
return 0;
}
break; }
return CFrameWnd::WindowProc(message, wParam, lParam);
}
我这里有个疑问。就是NOTIFYICONDATA 这个结构体该定义在那个函数比较好?我发现放在OnInitDialog 和 OnPaint中都有效。
lParam判定改为WM_LBUTTONDBLCLK和WM_RBUTTONDOWN,双击左键或者单击右键,试试看。
CMainFrame哪里来?
你在自己的对话框下 重载虚函数 WindowProc
我复制我的给你看 我的就是对话框下做的
LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{ // TODO: Add your specialized code here and/or call the base class switch(message){
case MYWM_NOTIFYICON:
//如果是用户定义的消息
if(lParam==WM_LBUTTONDBLCLK)
{ //鼠标双击时主窗口出现
AfxGetApp()->m_pMainWnd->
ShowWindow(SW_SHOW);
}
else if(lParam==WM_RBUTTONDOWN)
{
//鼠标右键单击弹出菜单
CMenu menu;
menu.LoadMenu(IDM_RICHMENU);
//载入事先定义的菜单
CMenu* pMenu=menu.GetSubMenu(0);
CPoint pos;
GetCursorPos(&pos);
pMenu->TrackPopupMenu
(TPM_LEFTALIGN|TPM_RIGHTBUTTON,
pos.x,pos.y,AfxGetMainWnd());
}
break;
case WM_SYSCOMMAND:
//如果是系统消息
if(wParam==SC_CLOSE){ //接收到关闭消息时主窗口隐藏
AfxGetApp()->m_pMainWnd->
ShowWindow(SW_HIDE);
return 0;
}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
ON_MESSAGE(WM_TASKICON,OnTaskIcon)
其他的响应放到OnTaskIcon()里面。嘿嘿,偶素懒人哈。
大家注意看这个参数的解释
uCallbackMessage
Application-defined message identifier. The system uses this identifier to send notifications to the window identified in hWnd. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon, or when the icon is selected or activated with the keyboard. The wParam parameter of the message contains the identifier of the taskbar icon in which the event occurred. The lParam parameter holds the mouse or keyboard message associated with the event. For example, when the pointer moves over a taskbar icon, lParam is set to WM_MOUSEMOVE. See the Taskbar guide chapter for further discussion.MSDN的意思是lParam参数会捕获到关联的鼠标键盘消息wParam会获取到ICON的ID号。所以我我将自定义的消息WM_POPMENU付给uCallackMessage参数,并作了消息映射。响应函数是OnPopmenu(WPARAM wParam,LPARAM lParam)
将俩个参数传了进去。接下来的代码如帖子。可是不知哪里除了BUG,菜单就是无法显示~~~
上面说了,OnInitDialog()中设置NOTIFYICONDATA:
其中
TaskIcon.cbSize = sizeof(TaskIcon);
TaskIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
TaskIcon.hWnd = this->GetSafeHwnd();
TaskIcon.uFlags = 0x7; //NIF_MESSAGE|NIF_ICON|NIF_TIP;
lstrcpy(TaskIcon.szTip,_T("、、、、"));
TaskIcon.uCallbackMessage = WM_TASKICON;//设置出发图标响应消息
Shell_NotifyIcon(NIM_ADD,&TaskIcon);//这里设置图标咯2.
BEGIN_MESSAGE_MAP(CTest1Dlg, CDialog)
//{{AFX_MSG_MAP(CTest1Dlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_TASKICON,OnTaskIcon)//这里设置对图标响应消息的函数
END_MESSAGE_MAP()3.写响应函数吧
void CTest1Dlg::OnTaskIcon(WPARAM wParam,LPARAM lParam)
{
POINT point;
GetCursorPos(&point);
CMenu *pContextMenu ; if(lParam == WM_LBUTTONDBLCLK)
ShowWindow(SW_SHOWNORMAL);
else if(lParam == WM_RBUTTONDOWN)
{
CMenu menu;
menu.LoadMenu(IDR_QUIT);//这里放你自己希望弹出的菜单资源哈
pContextMenu = menu.GetSubMenu(0);
pContextMenu->TrackPopupMenu(TPM_LEFTBUTTON,point.x,point.y,this);
} return;
}
that's all.