mfc 控制只运行一个实例,并在托盘显示图标

(方式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,共享数据段等

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值