|
#include <windows.h> |
|
#include <winuser.h> |
|
#include <iostream> |
|
#include "menu.h" |
|
|
|
#if defined(__MINGW32__) |
|
# undef MAKEINTRESOURCE |
|
# define MAKEINTRESOURCE(i) ((LPCWSTR)((ULONG_PTR)(i))) |
|
#endif /* defined(__MINGW32__) */ |
|
|
|
#define WM_NOTIFYICON (WM_USER + 100) |
|
|
|
|
|
class TrayIcon { |
|
private: |
|
HICON iconHandle; |
|
public: |
|
TrayIcon(HINSTANCE inst, LPCWSTR iconName); |
|
~TrayIcon(); |
|
HICON handle(); |
|
}; |
|
TrayIcon::TrayIcon(HINSTANCE inst, LPCWSTR iconName) { |
|
this->iconHandle = (HICON)LoadImage( |
|
inst, |
|
iconName, |
|
IMAGE_ICON, |
|
0, |
|
0, |
|
LR_DEFAULTSIZE |
|
); |
|
} |
|
|
|
TrayIcon::~TrayIcon() { |
|
DestroyIcon(this->iconHandle); |
|
} |
|
|
|
HICON TrayIcon::handle() { return this->iconHandle; } |
|
|
|
|
|
|
|
class ContextMenu { |
|
private: |
|
HMENU parentMenu; |
|
HMENU rootPopup; |
|
public: |
|
ContextMenu(); |
|
~ContextMenu(); |
|
void Show(HWND hWnd); |
|
void OnMenuClicked(WORD itemID); |
|
}; |
|
ContextMenu::ContextMenu() { |
|
this->parentMenu = LoadMenu(NULL, TEXT("CTX_MENU")); |
|
this->rootPopup = GetSubMenu(this->parentMenu, 0); |
|
} |
|
|
|
ContextMenu::~ContextMenu() { |
|
DestroyMenu(this->parentMenu); |
|
} |
|
|
|
void ContextMenu::Show(HWND hWnd) { |
|
POINT currentCursorPoint; |
|
GetCursorPos(¤tCursorPoint); |
|
TrackPopupMenu( |
|
this->rootPopup, |
|
0, |
|
currentCursorPoint.x, |
|
currentCursorPoint.y, |
|
0, |
|
hWnd, |
|
NULL |
|
); |
|
} |
|
|
|
void ContextMenu::OnMenuClicked(WORD itemID) { |
|
switch (itemID) { |
|
case IDM_QUIT: |
|
PostQuitMessage(0); |
|
} |
|
} |
|
|
|
|
|
class Tray { |
|
private: |
|
HWND windowHandler; |
|
TrayIcon *currentIcon = NULL; |
|
ContextMenu *currentMenu = NULL; |
|
public: |
|
Tray(HINSTANCE inst, int nCmdShow); |
|
int AddIcon(TrayIcon *icon, ContextMenu *menu, LPCWSTR tipMessage); |
|
void ClearIcon(); |
|
LRESULT CALLBACK WndProcDelegate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); |
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); |
|
~Tray(); |
|
}; |
|
Tray::Tray(HINSTANCE inst, int nCmdShow) { |
|
WNDCLASS wclass; |
|
wclass.style = CS_HREDRAW | CS_VREDRAW; |
|
wclass.lpfnWndProc = Tray::WndProc; |
|
//wclass.lpfnWndProc = WndProc; |
|
wclass.cbClsExtra = 0; |
|
wclass.cbWndExtra = 0; |
|
wclass.hIcon = LoadIcon(NULL , IDI_APPLICATION); |
|
wclass.hInstance = inst; |
|
wclass.lpszClassName = TEXT("TRAY"); |
|
|
|
if(!RegisterClass(&wclass)) throw std::runtime_error("Tray class must be registered."); |
|
|
|
this->windowHandler = CreateWindowEx( |
|
WS_EX_TOOLWINDOW, |
|
TEXT("TRAY"), |
|
TEXT("tray"), |
|
WS_OVERLAPPEDWINDOW, |
|
0, |
|
0, |
|
0, |
|
0, |
|
NULL, |
|
NULL, |
|
inst, |
|
this |
|
); |
|
} |
|
|
|
Tray::~Tray() { |
|
|
|
} |
|
|
|
int Tray::AddIcon(TrayIcon *icon, ContextMenu *menu, LPCWSTR tipMessage) { |
|
this->currentIcon = icon; |
|
this->currentMenu = menu; |
|
|
|
NOTIFYICONDATA nid; |
|
nid.cbSize = sizeof(nid); |
|
nid.hWnd = this->windowHandler; |
|
nid.uID = 0; |
|
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; |
|
nid.uCallbackMessage = WM_NOTIFYICON; |
|
nid.hIcon = icon->handle(); |
|
lstrcpy(nid.szTip, tipMessage); |
|
return (int)Shell_NotifyIcon(NIM_ADD, &nid); |
|
} |
|
|
|
void Tray::ClearIcon() { |
|
NOTIFYICONDATA nid; |
|
nid.cbSize = sizeof(nid); |
|
nid.hWnd = this->windowHandler; |
|
nid.uID = 0; |
|
nid.uFlags = 0; |
|
Shell_NotifyIcon(NIM_DELETE, &nid); |
|
|
|
this->currentMenu = NULL; |
|
this->currentIcon = NULL; |
|
} |
|
|
|
LRESULT Tray::WndProcDelegate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
|
switch (lParam) { |
|
case WM_LBUTTONDOWN: |
|
if (MessageBox(NULL, TEXT("Quit?"), TEXT("Quit?"), MB_YESNO) == IDYES) { |
|
PostQuitMessage(0); |
|
return 0; |
|
} |
|
break; |
|
case WM_RBUTTONDOWN: |
|
this->currentMenu->Show(hWnd); |
|
break; |
|
} |
|
return DefWindowProc(hWnd, msg, wParam, lParam); |
|
} |
|
|
|
LRESULT Tray::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
|
Tray *tray = (Tray *)GetWindowLong(hWnd, GWL_USERDATA); |
|
if (!tray) { |
|
tray = (Tray *)(((LPCREATESTRUCT)lParam)->lpCreateParams); |
|
if (tray) { |
|
SetWindowLong(hWnd, GWL_USERDATA, (LONG)tray); |
|
} |
|
} |
|
|
|
switch (msg) { |
|
case WM_NOTIFYICON: |
|
if (wParam == 0) { |
|
return tray->WndProcDelegate(hWnd, msg, wParam, lParam); |
|
} |
|
break; |
|
case WM_COMMAND: |
|
tray->currentMenu->OnMenuClicked(LOWORD(wParam)); |
|
return 0; |
|
case WM_DESTROY: |
|
PostQuitMessage(0); |
|
return 0; |
|
} |
|
return DefWindowProc(hWnd, msg, wParam, lParam); |
|
} |
|
|
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { |
|
Tray tray(hInstance, nCmdShow); |
|
TrayIcon *ti = new TrayIcon(NULL, MAKEINTRESOURCE(IDI_WINLOGO)); |
|
ContextMenu *ctxMenu = new ContextMenu(); |
|
LPCWSTR tip = TEXT("ほげほげ"); |
|
tray.AddIcon(ti, ctxMenu, tip); |
|
|
|
MSG msg; |
|
while (GetMessage(&msg, NULL, 0, 0)) { |
|
TranslateMessage(&msg); |
|
DispatchMessage(&msg); |
|
} |
|
|
|
tray.ClearIcon(); |
|
delete ti; |
|
delete ctxMenu; |
|
return msg.wParam; |
|
} |