托盘图标添加通用解决方案
#define WM_SYSTEMTRAY (WM_USER + WM_COMMAND + 1)
const UINT WMEX_TASKBARCREATED = ::RegisterWindowMessage(TEXT("TaskbarCreated"));
afx_msg LRESULT OnSystemtray(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnRestartExplorer(WPARAM wParam, LPARAM lParam);
ON_MESSAGE(WM_SYSTEMTRAY, &CMySqlMgrDlg::OnSystemtray)
ON_REGISTERED_MESSAGE(WMEX_TASKBARCREATED, &CMySqlMgrDlg::OnRestartExplorer)
BOOL CMySqlMgrDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
{
m_nidNotifyIcon.cbSize = sizeof(NOTIFYICONDATA);
m_nidNotifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_nidNotifyIcon.hIcon = m_hIcon;
m_nidNotifyIcon.hWnd = m_hWnd;
wcscpy(m_nidNotifyIcon.szTip, L"托盘显示");
m_nidNotifyIcon.uCallbackMessage = WM_SYSTEMTRAY;
m_nidNotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
Shell_NotifyIcon(NIM_ADD, &m_nidNotifyIcon);
}
return TRUE; // return TRUE unless you set the focus to a control
}
afx_msg LRESULT CMySqlMgrDlg::OnSystemtray(WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_RBUTTONDOWN:
{
enum MenuEnumType {
METYPE_SHOWHIDE = 10001,
METYPE_EXIT,
};
CMenu menu = {};
CPoint pt = { 0 };
GetCursorPos(&pt);
SetForegroundWindow();
if (menu.CreatePopupMenu() == TRUE)
{
menu.AppendMenu(MF_STRING, METYPE_SHOWHIDE, (IsWindowVisible() == TRUE) ? TEXT("后台运行") : TEXT("前台运行"));
menu.AppendMenu(MF_STRING, METYPE_EXIT, TEXT("退出软件"));
switch ((enum MenuEnumType)menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, this))
{
case METYPE_SHOWHIDE:
{
if (((::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) & (WS_EX_TOOLWINDOW)) == WS_EX_TOOLWINDOW) == TRUE)
{
::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, (::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | (WS_EX_APPWINDOW)) & (~WS_EX_TOOLWINDOW));
::ShowWindow(m_hWnd, SW_SHOWNORMAL);
::SetForegroundWindow(m_hWnd);
}
else
{
::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, (::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | (WS_EX_TOOLWINDOW)) & (~WS_EX_APPWINDOW));
::ShowWindow(m_hWnd, SW_HIDE);
}
}
break;
case METYPE_EXIT:
{
PostQuitMessage(IDCLOSE);
}
break;
default:
break;
};
menu.DestroyMenu();
}
}
break;
case WM_LBUTTONDBLCLK:
{
if (((::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) & (WS_EX_TOOLWINDOW)) == WS_EX_TOOLWINDOW) == TRUE)
{
::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, (::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | (WS_EX_APPWINDOW)) & (~WS_EX_TOOLWINDOW));
::ShowWindow(m_hWnd, SW_SHOWNORMAL);
::SetForegroundWindow(m_hWnd);
}
else
{
::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, (::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | (WS_EX_TOOLWINDOW)) & (~WS_EX_APPWINDOW));
::ShowWindow(m_hWnd, SW_HIDE);
}
}
break;
case WM_LBUTTONDOWN:
{
}
break;
}
return 0;
}
LRESULT CMySqlMgrDlg::OnRestartExplorer(WPARAM wParam, LPARAM lParam)
{
Shell_NotifyIcon(NIM_ADD, &m_nidNotifyIcon);
return TRUE;
}
void CMySqlMgrDlg::OnCancel()
{
// TODO: Add your specialized code here and/or call the base class
Shell_NotifyIcon(NIM_DELETE, &m_nidNotifyIcon)
CDialogEx::OnCancel();
}
关闭进程
__inline static
HANDLE GetCurrentProcessReal()
{
HANDLE RealProcessHandle = NULL;
HANDLE PseudoProcessHandle = ::GetCurrentProcess(); //获得一个伪句柄
::DuplicateHandle(
::GetCurrentProcess(), //源进程内核句柄(即负责传递内核对象句柄的进程句柄)
PseudoProcessHandle, //进程伪句柄 GetCurrentProcess()
::GetCurrentProcess(), //目标进程内核句柄
&RealProcessHandle, //接受新的,真实句柄!
0, //TargetHandle句柄使用何种访问掩码,这个参数将被忽略,因为DUPLICATE_SAME_ACCESS
FALSE, //新的句柄不可继承
DUPLICATE_SAME_ACCESS);
return(RealProcessHandle);
}
__inline static
DWORD GetCurrentProcessIdReal()
{
return ::GetProcessId(GetCurrentProcessReal());
}
__inline static
void TerminateProcesses(LPCWSTR lpcwProcessName)
{
BOOL bResult = FALSE;
HANDLE hSnapShot = NULL;
PROCESSENTRY32W PE32W = { 0 };
hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapShot != NULL)
{
for (BOOL bOk = (PE32W.dwSize = sizeof(PE32W), ::Process32FirstW(hSnapShot, &PE32W)); bOk == TRUE; PE32W.dwSize = sizeof(PE32W), bOk = ::Process32NextW(hSnapShot, &PE32W))
{
if (PE32W.th32ProcessID != GetCurrentProcessIdReal()
&& ::_wcsicmp(PE32W.szExeFile, lpcwProcessName) == 0)
{
HANDLE hP = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, PE32W.th32ProcessID);
if (hP != NULL)
{
::TerminateProcess(hP, (0));
::CloseHandle(hP);
}
}
}
::CloseHandle(hSnapShot);
}
}
class IniMgr
{
std::wstring m_wIniFilePath = std::wstring();
public:
std::wstring ReadPass(const std::wstring& wAppName)
{
{WCHAR wPass[4096] = { 0 }; return(GetPrivateProfileStringW(wAppName.c_str(), L"PASS", L"", wPass, 4096, m_wIniFilePath.c_str()) > 0) ? wPass : L""; }
}
std::wstring ReadPort(const std::wstring& wAppName)
{
{WCHAR wPort[4096] = { 0 }; return(GetPrivateProfileStringW(wAppName.c_str(), L"PORT", L"", wPort, 4096, m_wIniFilePath.c_str()) > 0) ? wPort : L""; }
}
BOOL WritePass(const std::wstring& wAppName, const std::wstring& wPass)
{
return WritePrivateProfileStringW(wAppName.c_str(), L"PASS", wPass.c_str(), m_wIniFilePath.c_str());
}
BOOL WritePort(const std::wstring& wAppName, const std::wstring& wPort)
{
return WritePrivateProfileStringW(wAppName.c_str(), L"PORT", wPort.c_str(), m_wIniFilePath.c_str());
}
public:
static IniMgr& Inst()
{
static IniMgr IniMgrInstance = {};
if (IniMgrInstance.m_wIniFilePath.empty() == true)
{
IniMgrInstance.m_wIniFilePath = (std::wstring(*__wargv).substr(0, std::wstring(*__wargv).rfind(L'.')).append(L".conf"));
}
return(IniMgrInstance);
}
};