(目前只能用在基于对话框的程序,SDI测试失败,待解决,在SDI中响应OnSize消息则可)
1、最小化的原理:首先要将窗口隐藏,然后 在右下角绘制图标。
2、恢复的原理:将窗口显示,再将托盘中的图片删除。
(二)程序实现1、自定义消息WM_SHOWTASK: #define WM_SHOWTASK (WM_USER +1)
2、在MFC的(的dlg类中)OnSysCommand(UINT nID, LPARAM lParam)函数体中增加一个命令响应
if(nID==SC_MINIMIZE)
ToTray(); //最小化到托盘的函数
3、在消息映射中添加 ON_MESSAGE(WM_SHOWTASK,OnShowTask),其中WM_SHOWTASK是消息名,OnShowTask是自己定义的消息响应函数,后面有说明。
(三)具体函数内容
1、最小化到托盘函数
void CMyDlg::ToTray(){
NOTIFYICONDATA nid;
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_SHOWTASK;//自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"程序名称"); //信息提示条
Shell_NotifyIcon(NIM_ADD,&nid); //在托盘区添加图标
ShowWindow(SW_HIDE); //隐藏主窗口
}
2、恢复界面函数
在头文件中定义消息响应函数afx_msg LRESULT OnShowTask(WPARAM wParam,LPARAM lParam) ;//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
view plaincopy to clipboardprint?
01.LRESULT CTimeDlg::OnShowTask(WPARAM wParam,LPARAM lParam)
02.{
03. if(wParam!=IDR_MAINFRAME)
04. return 1;
05. switch(lParam)
06. {
07. case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”
08. {
09. LPPOINT lpoint= new tagPOINT;
10. ::GetCursorPos(lpoint);//得到鼠标位置
11. CMenu menu;
12. menu.CreatePopupMenu();//声明一个弹出式菜单
13. //增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已
14. //隐藏),将程序结束。
15. menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");
16. menu.AppendMenu(MF_STRING,WM_DESTROY,"设置...");
17. //确定弹出式菜单的位置
18. menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
19. //资源回收
20. HMENU hmenu=menu.Detach();
21. menu.DestroyMenu();
22. delete lpoint;
23. }
24. break;
25. case WM_LBUTTONDBLCLK://双击左键的处理
26. {
27.
28. ShowWindow(SW_SHOWNORMAL);//简单的显示主窗口完事儿 SW_SHOW则错误
29.
30. // this->SetForegroundWindow(); // 置顶显示
31. DeleteTray();
32. }
33. break;
34. default:
35. break;
36. }
37. return 0;
38. }
LRESULT CTimeDlg::OnShowTask(WPARAM wParam,LPARAM lParam)
{
if(wParam!=IDR_MAINFRAME)
return 1;
switch(lParam)
{
case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”
{
LPPOINT lpoint= new tagPOINT;
::GetCursorPos(lpoint);//得到鼠标位置
CMenu menu;
menu.CreatePopupMenu();//声明一个弹出式菜单
//增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已
//隐藏),将程序结束。
menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");
menu.AppendMenu(MF_STRING,WM_DESTROY,"设置...");
//确定弹出式菜单的位置
menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
//资源回收
HMENU hmenu=menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK://双击左键的处理
{
ShowWindow(SW_SHOWNORMAL);//简单的显示主窗口完事儿 SW_SHOW则错误
// this->SetForegroundWindow(); // 置顶显示
DeleteTray();
}
break;
default:
break;
}
return 0;
}
3、删除托盘图标函数
view plaincopy to clipboardprint?
01.void CTimeDlg::DeleteTray()
02.{
03. NOTIFYICONDATA nid;
04. nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
05. nid.hWnd=this->m_hWnd;
06. nid.uID=IDR_MAINFRAME;
07. nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
08. nid.uCallbackMessage=WM_SHOWTASK;//自定义的消息名称
09. nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
10. strcpy(nid.szTip,"程序名称"); //信息提示条为“计划任务提醒”
11. Shell_NotifyIcon(NIM_DELETE,&nid); //在托盘区删除图标
12.}
void CTimeDlg::DeleteTray()
{
NOTIFYICONDATA nid;
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_SHOWTASK;//自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"程序名称"); //信息提示条为“计划任务提醒”
Shell_NotifyIcon(NIM_DELETE,&nid); //在托盘区删除图标
}
单文档程序中:
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)
{
ToTray();
}
//else
// {////
// Shell_NotifyIcon(NIM_DELETE,&nid);
//}
}
其他与上边类似
这是一个很经典的问题,因为可能许多时候你不想使用者老是面对一大堆的对话框或者缩小到工具栏占据一片界面的烦恼,我看过许多的类似问题的解决办法,但是他妈的让人反草的是都他妈的是对话框程序,在面对单文档程序时我曾经得到这么个似是而非的答案:应该和对话框差不多的吧!..........听到这句话我估计90%的兄弟们会很郁闷。差不多是差多少呢,十万八千里!!因为大多同志们不清楚VC消息处理的流程。一句话就是兄弟们都是新手。
废话少说这里我不想讲任何的道理直接把源代码考进来了,大伙看的懂看不懂直接塞进你的程序就能用了,注意:!!!!!!!!!!!必须留言,说句话再走
..
.
.
endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// Generated message map functions
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnOpenMainfrm();
//}}AFX_MSG
NOTIFYICONDATA m_tnid;
DECLARE_MESSAGE_MAP()
};
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_tnid.cbSize=sizeof(NOTIFYICONDATA);
m_tnid.hWnd=this->m_hWnd;
m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_tnid.uCallbackMessage=WM_USER_NOTIFYICON;
CString szToolTip;
szToolTip=_T("系统托盘");
_tcscpy(m_tnid.szTip, szToolTip);
m_tnid.uID=IDR_MAINFRAME;
m_tnid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
::Shell_NotifyIcon(NIM_ADD,&m_tnid);
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch(message) //判断消息类型
{
case WM_USER_NOTIFYICON:
//如果是用户定义的消息
if(lParam==WM_LBUTTONDBLCLK)
{
//鼠标双击时主窗口出现
if(AfxGetApp()->m_pMainWnd->IsWindowVisible()) //判断窗口当前状态
{
AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); //隐藏窗口
}
else
{
AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //显示窗口
}
}
else if(lParam==WM_RBUTTONDOWN)
{ //鼠标右键单击弹出选单
CMenu menu;
menu.LoadMenu(IDR_MENU); //载入事先定义的选单
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_MINIMIZE)
{
//接收到最小化消息时主窗口隐藏
AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE);
// ::Shell_NotifyIcon(NIM_ADD,&m_tnid);
return 0;
}
if(wParam==SC_CLOSE)
{
::Shell_NotifyIcon(NIM_DELETE,&m_tnid); //关闭时删除系统托盘图标
}
break;
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}
void CMainFrame::OnOpenMainfrm()
{
// TODO: Add your command handler code here
if(!AfxGetApp()->m_pMainWnd->IsWindowVisible()) //判断窗口当前状态
{
AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //显示窗口
}
}
注意:红色部分是必须添加的代码,有的同学可能会说我们在类视图中找不到LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 啊 ,没有这个函数啊,注意看看这个函数的原型以及参数你会发现这不是windows消息处理函数吗!!!自己去添加WINDows消息虚函数把,至于怎么添加我就不用说了相信大家都知道的
/////以下的未经验证,
单文档程序最小化到托盘+自定义消息
1.自定义消息的方法
#define WM_MYMESSAGE WM_USER+1
afx_msg LRESULT OnMyMessage ( WPARAM wParam, LPARAM lParam );
ON_MESSAGE ( WM_MYMESSAGE, OnMyMessage )//这句要在BEGIN MESSAGE MAP和end中间
LRESULT cxx::OnMyMessage ( WPARAM wParma, LPARAM lParam )
{
...
}
2.最小化到托盘函数
void CMainFrame::toTray(void)
{
NOTIFYICONDATA nid;
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_SHOWTASK;//自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
//CString str = L"计划任务提醒";
//nid.szTip = {L"计划任务提醒"}; //信息提示条为“计划任务提醒”
Shell_NotifyIcon(NIM_ADD,&nid);//在托盘区添加图标
ShowWindow(SW_HIDE);//隐藏主窗口
}
3、对托盘处理过程函数
LRESULT CMainFrame::OnShowTask(WPARAM wParam,LPARAM lParam)
{
// TODO: 在此处添加消息处理程序代码
if(wParam!=IDR_MAINFRAME)
return 1;
switch(lParam)
{
case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”
{
LPPOINT lpoint=new tagPOINT;
::GetCursorPos(lpoint);//得到鼠标位置
CMenu menu;
menu.CreatePopupMenu();//声明一个弹出式菜单
//增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已
//隐藏),将程序结束。
menu.AppendMenu(MF_STRING,WM_DESTROY,L"关闭");
//确定弹出式菜单的位置
menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
//资源回收
HMENU hmenu=menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK://双击左键的处理
{
this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿
}
break;
}
return 0;
}
4、上面是mfc下托盘的处理。下面是一个完整的纯SDK的托盘程序。
#include <windows.h>
#include <atlimage.h>
#include "resource.h"
//#include <afxwin.h>
#define WM_SHOWTASK WM_USER+10
//#define _AFXDLL;
HWND hWnd; //程序主窗口句柄
HINSTANCE mhInstance; //实例句柄
NOTIFYICONDATA nid; //托盘结构体
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void ToTray(void);
LRESULT OnShowTask(WPARAM wParam,LPARAM lParam);
CImage image;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground= (HBRUSH) GetStockObject (BLACK_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName= szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow( szAppName, // window class name
TEXT ("Full Screen Display"), // window caption
// WS_OVERLAPPEDWINDOW, // window style
WS_POPUP,
/* CW_USEDEFAULT,// initial x position
CW_USEDEFAULT,// initial y position
CW_USEDEFAULT,
CW_USEDEFAULT,// initial x size
*/ 100,100,100,100,
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
hWnd = hwnd;
mhInstance = hInstance;
ShowWindow (hwnd, SW_SHOW) ;
UpdateWindow (hwnd) ;
SetWindowPos(hwnd, HWND_TOPMOST,540,260,200,200,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE );
ToTray();
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return 0 ;
case WM_PAINT:
{
HDC hdc = GetDC(hwnd);
CImage image;
image.Load(L"C:\\bitmap\\002.bmp");
int x = GetSystemMetrics(SM_CXSCREEN),y = GetSystemMetrics(SM_CYSCREEN);
// image.BitBlt(hdc,x-100,y-100,x,y,0,0);
SetStretchBltMode(hdc,COLORONCOLOR);
RECT rect;
GetClientRect(hwnd,&rect);
// image.StretchBlt(hdc,x-500,y-500,x,y);
image.StretchBlt(hdc,rect);
image.Destroy();
ReleaseDC(hwnd,hdc);
// delete rect;
return 0 ;
}
case WM_DESTROY:
Shell_NotifyIcon(NIM_DELETE,&nid);
PostQuitMessage (0) ;
return 0;
case WM_SHOWTASK:
OnShowTask(wParam,lParam);
return 0;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDR_MENU1:
Shell_NotifyIcon(NIM_DELETE,&nid);
PostQuitMessage (0) ;
return 0;
case IDR_MENU2:
SetWindowPos(hwnd, HWND_TOPMOST,540,260,200,200,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOMOVE |SWP_NOSIZE );
return 0;
case IDR_MENU3:
SetWindowPos(hwnd, HWND_TOPMOST,540,260,200,200,SWP_HIDEWINDOW);
return 0;
}
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
void ToTray(void)
{
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd=hWnd;
nid.uID=IDI_ICON1;
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage=WM_SHOWTASK;//自定义的消息名称
nid.hIcon=LoadIcon(mhInstance,MAKEINTRESOURCE(IDI_ICON1));
//信息提示条为“计划任务提醒”
WCHAR sz[] = L"计划任务提醒";
memcpy(nid.szTip,sz,sizeof(sz));
Shell_NotifyIcon(NIM_ADD,&nid);//在托盘区添加图标
// ShowWindow(hWnd,SW_HIDE);//隐藏主窗口
}
LRESULT OnShowTask(WPARAM wParam,LPARAM lParam)
{
if(wParam!=IDI_ICON1)
return 1;
switch(lParam)
{
case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”
{
LPPOINT lpoint=new tagPOINT;
::GetCursorPos(lpoint);//得到鼠标位置
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu,MF_STRING,IDR_MENU1,L"关闭");
AppendMenu(hMenu,MF_STRING,IDR_MENU2,L"显示");
AppendMenu(hMenu,MF_STRING,IDR_MENU3,L"隐藏");
TrackPopupMenu(hMenu, TPM_LEFTALIGN,lpoint->x,lpoint->y, 0,hWnd, NULL);
DestroyMenu(hMenu);
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK://双击左键的处理
{
ShowWindow(hWnd,SW_SHOW);//简单的显示主窗口完事儿
}
break;
}
return 0;
}