(方式1)创建进程互斥体Sample07
HANDLE m_hMutex = CreateMutex(NULL, TRUE, _T("xxxx"));
//在app文件下InitInstance()中加入
BOOL xxxApp::InitInstance()
{
//创建进程互斥体Sample07
HANDLE m_hMutex = CreateMutex(NULL, TRUE, _T("xxx"));
if (m_hMutex == NULL)
{
return FALSE;
}
//AfxMessageBox(_T("01"));
//如果程序已经存在并且正在运行
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
HWND hProgramWnd = ::FindWindow(NULL, L"xxx");
if (hProgramWnd)
{
WINDOWPLACEMENT* pWndpl = NULL;
WINDOWPLACEMENT wpm;
pWndpl = &wpm;
GetWindowPlacement(hProgramWnd, &wpm);
if (pWndpl)
{
COPYDATASTRUCT cpd;
// //主窗口已最小化,则恢复其大小
//if (::IsIconic(hProgramWnd))
// ::ShowWindow(hProgramWnd, SW_RESTORE);
将主窗激活
//::SetForegroundWindow(hProgramWnd);
将主窗的对话框激活
//::SetForegroundWindow(::GetLastActivePopup(hProgramWnd));
//将运行的程序窗口还原成正常状态
pWndpl->showCmd = SW_SHOWNORMAL;
::SetWindowPlacement(hProgramWnd, pWndpl);
SetWindowPos(hProgramWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
FlashWindow(hProgramWnd, TRUE);//任务栏图标闪烁
//发送字符串到窗口中
CString str1 = _T("qqqw");
cpd.dwData = 1;
cpd.cbData = str1.GetLength() + 1;
cpd.lpData = (void*)str1.GetBuffer(cpd.cbData);
::SendMessage(hProgramWnd, WM_COPYDATA, NULL, (LPARAM)&cpd);//发送!
//::SendMessage(hProgramWnd, WM_MYMESSAGE, 0, (LPARAM)(LPCTSTR)str1);
}
}
//关闭进程互斥体
CloseHandle(m_hMutex);
m_hMutex = NULL;
return FALSE;
}
}
//方式2
BOOL XXXApp::InitInstance()
{
// 用应用程序名创建信号量
HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszExeName);
// 信号量已存在?
// 信号量存在,则程序已有一个实例运行
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// 关闭信号量句柄
CloseHandle(hSem);
// 寻找先前实例的主窗口
HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (::IsWindow(hWndPrevious))
{
// 检查窗口是否有预设的标记?
// 有,则是我们寻找的主窗
if (::GetProp(hWndPrevious, m_pszExeName))
{
// 主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_RESTORE);
// 将主窗激活
::SetForegroundWindow(hWndPrevious);
// 将主窗的对话框激活
::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
// 退出本实例
COPYDATASTRUCT cpd;
CString strCmd(m_lpCmdLine);
cpd.dwData = 1;
//发送copydata消息时的长度请注意时2倍+1
cpd.cbData = 2* strCmd.GetLength() + 1;
cpd.lpData = (void*)strCmd.GetBuffer(cpd.cbData);
::SendMessage(hWndPrevious, WM_COPYDATA, NULL, (LPARAM)&cpd);//发送!
return false;
break;
}
// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
}
/* 前一实例已存在,但找不到其主窗
可能出错了
退出本实例*/
return FALSE;
}
}
//在下面函数加入
BOOL XXXDlg::OnInitDialog()
{
// 设置寻找标记
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
}
void XXXDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
// 删除寻找标记
::RemoveProp(this->m_hWnd, AfxGetApp()->m_pszExeName);
CDialogEx::OnClose();
}
//增加托盘图标函数
NOTIFYICONDATA m_nid;
//---------------------------托盘显示---------------------------------//
m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
m_nid.hWnd = this->m_hWnd;
m_nid.uID = IDI_NOTIFYICON;
m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
m_nid.uCallbackMessage = WM_SHOWTASK; // 自定义的消息名称
m_nid.hIcon = m_hIcon;
wcscpy(m_nid.szTip, _T("NN上号器"));
Shell_NotifyIcon(NIM_ADD, &m_nid); // 在托盘区添加图标
//增加托盘菜单操作响应函数
#define WM_SHOWTASK WM_USER+101
afx_msg LRESULT OnAddTrayIcon(WPARAM wParam, LPARAM lParam);
ON_MESSAGE(WM_SHOWTASK, OnAddTrayIcon)
//菜单可在资源文件中增加
LRESULT xxxDlg::OnAddTrayIcon(WPARAM wParam, LPARAM lParam)
{
UINT uMsg = (UINT)lParam;
switch (uMsg)
{
case WM_RBUTTONUP:
{
//让托盘菜单消失
SetForegroundWindow();
//右键处理
CMenu menuTray;
CPoint point;
int id;
GetCursorPos(&point);
BOOL bResulet = menuTray.LoadMenu(IDR_MENU1);
HMENU handle;
CMenu *p = menuTray.GetSubMenu(0);
id = menuTray.GetSubMenu(0)->TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
switch (id)
{
case ID_32772:
//关闭窗口
Shell_NotifyIcon(NIM_DELETE, &m_nid);
OnOK();
break;
case ID_32771:
//窗口前端显示
SetForegroundWindow();
ShowWindow(SW_SHOWNORMAL);
break;
default:
break;
}
break;
}
case WM_LBUTTONDBLCLK:
SetForegroundWindow();
ShowWindow(SW_SHOWNORMAL);
break;
default:
break;
}
return 0;
}
//最小化隐藏窗口
void xxxDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
if (nType == SIZE_MINIMIZED)
{
ShowWindow(SW_HIDE); // 当最小化市,隐藏主窗口
}
// TODO: 在此处添加消息处理程序代码
}
void xxxDlg::OnDestroy()
{
//Shell_NotifyIcon(NIM_DELETE, &m_nid);
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
}
//关闭按钮隐藏窗口
void xxxDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CloseWindow();
ShowWindow(SW_HIDE);
CDialogEx::OnClose();
}
注意只运行一个实例,需要采用进程通信方式,COPYDATA,共享数据段等