现在的位置: 首页 > 综合 > 正文

疯狂C++之路[MFC篇][程序系统托盘与运行实例唯一实现][基础]

2014年03月04日 ⁄ 综合 ⁄ 共 3245字 ⁄ 字号 评论关闭

程序都要实现系统托盘功能,最小化到托盘是不是很酷,像QQ等等软件

还有的程序只允许运行一个,再次运行时会提示已经运行,是不是很友好

下面就实现这两个功能:[思路来源与Visual C++实效编程280例]

一:实现实例唯一

托盘一般只用在类testApp中设置一个互斥对象就可以满足

首先在App类中添加一个成员变量HANDLE m_hMutex;并在构造中初始化m_hMutex = NULL;

在InitInstance()中把代码替换成如下代码就可达到目的

 AfxEnableControlContainer();

 // Standard initialization
 // If you are not using these features and wish to reduce the size
 //  of your final executable, you should remove from the following
 //  the specific initialization routines you do not need.
 m_hMutex = ::CreateMutex(NULL, FALSE, _T("abc"));//创建互斥对象
 //判断互斥量是否存在
 if (GetLastError() == ERROR_ALREADY_EXISTS) 
 {
  AfxMessageBox("应用程序已经运行。");
  return FALSE; 
 }

 AfxEnableControlContainer();
#ifdef _AFXDLL
 Enable3dControls();  // Call this when using MFC in a shared DLL
#else
 Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
 CTestTrayDlg dlg;
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal();
 if (nResponse == IDOK)
 {
  }
 else if (nResponse == IDCANCEL)
 {
 }
 return FALSE;

二:实现托盘功能

手盘功能比较麻烦,首先在Dlg中定义变量

NOTIFYICONDATA  m_Nid;也初化为NULL

//OnInitDlg中添加

m_Nid.cbSize = sizeof(NOTIFYICONDATA);

m_Nid.hWnd = m_hWnd;

m_Nid.uID = 100;

m_Nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;

m_Nid.uCallbackMessage = WM_NOTIFYICON;

m_Nid.hIcon = (HICON)LoadImage(AfxGetInstanceHandle(), 

MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, NULL);

StrCpy(m_Nid.szTip, _T("TrayName"));

对话框上添加按纽IDC_TEST,双击添加事件改名叫OnTest添加如下代码

ShowWindow(SW_HIDE);

//在任务栏中添加图标 

Shell_NotifyIcon(NIM_ADD, &m_Nid);

在头上定义

#define WM_NOTIFYICON WM_USER+1 定义一个常量,呆会映射到响应函数上

把下面代码与原消息映射比较添加

BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)

//{{AFX_MSG_MAP(CDemoDlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_TEST, OnTest)

ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)//响应托盘点击响应函数

ON_COMMAND(ID_SHOW, OnShow)//显示

ON_COMMAND(ID_EXIT, OnExit)//退出

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

//下面afx_msg知道添加在哪不,在.h的声明文件里,你会发现有类似这样的地方就添进去就行了(其实定义函数也一样,afx_msg只是让向导用的,对编译器来说没太大的意义,上下两步很重要,不然你会收到明明定义的却说没定义)

afx_msg void OnTest();

afx_msg void OnNotifyIcon(WPARAM wParam, LPARAM lParam);

afx_msg void OnShow();

afx_msg void OnExit();

三个小函数的实现

void CDemoDlg::OnTest() //点击界面按纽时触发

{ //隐藏窗口

ShowWindow(SW_HIDE);

//在任务栏中添加图标 

Shell_NotifyIcon(NIM_ADD, &m_Nid);

}

void CDemoDlg::OnShow()//点击显示后显示

{

//删除任务栏中的图标 

Shell_NotifyIcon(NIM_DELETE , &m_Nid);

//显示窗口

ShowWindow(SW_SHOWNORMAL);

UpdateWindow();

}

void CDemoDlg::OnExit()//点右下角退出后退出

{

//删除任务栏中的图标 

Shell_NotifyIcon(NIM_DELETE, &m_Nid);

//关闭窗口

SendMessage(WM_CLOSE);

}

最后添加一个托盘响应函数

 

void CtestDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)//CtestDlg改成你相同的名字

{

if (wParam == 100) //初始化时已经把ID设为100了

{

if (lParam == WM_LBUTTONDBLCLK)

{

//删除任务栏中的图标 

Shell_NotifyIcon(NIM_DELETE, &m_Nid);

//显示窗口

ShowWindow(SW_SHOWNORMAL);

UpdateWindow();

}

else if ((lParam == WM_LBUTTONDOWN) || (lParam == WM_RBUTTONDOWN))//左右键都能弹出菜单

{

//显示快捷子菜单

CMenu menu; 

if (!menu.LoadMenu(IDR_MENU))  //去资源里添加个IDR_MENU

{                              //添加两个项,显示,退出ID为ID_EXIT and ID_SHOW

return;         

}

CPoint point; 

GetCursorPos(&point); 

SetForegroundWindow();

CMenu* pSubMenu = menu.GetSubMenu(0);

if (pSubMenu == NULL)

{

return;

}

pSubMenu->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 

point.x, point.y, this, NULL); 

// PostMessage(WM_NULL, 0, 0);  //这句空消息可发可不发

}

}

}

还有一点,若说StrCpy未定义,添加#include "Shlwapi.h"

最后说一点:出错没事,你要跟着错误一点点改,这样你也能学到东西,多用脑子,你要能把这些都解决了,以后对你的成长有很大的作用,不会的也可以给我留言

也可以看看我做的,很粗糙但功能实现了

http://download.csdn.net/source/3190295

 

抱歉!评论已关闭.