[c-host] added tray icon and context menu

This commit is contained in:
Geoffrey McRae 2019-05-21 17:52:58 +10:00
parent 67595d6deb
commit 3f404905d2
5 changed files with 66 additions and 7 deletions

View File

@ -1 +1 @@
a12-202-g77f942711a+1 a12-203-g67595d6deb+1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +1,4 @@
#include "winuser.h" #include "winuser.h"
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest" CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
IDI_APPLICATION ICON "icon.ico"

View File

@ -31,8 +31,13 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "windows/debug.h" #include "windows/debug.h"
#include "ivshmem/Public.h" #include "ivshmem/Public.h"
#define ID_MENU_OPEN_LOG 3000
#define ID_MENU_EXIT 3001
struct AppState struct AppState
{ {
HINSTANCE hInst;
int argc; int argc;
char ** argv; char ** argv;
@ -41,6 +46,7 @@ struct AppState
bool shmemOwned; bool shmemOwned;
IVSHMEM_MMAP shmemMap; IVSHMEM_MMAP shmemMap;
HWND messageWnd; HWND messageWnd;
HMENU trayMenu;
}; };
static struct AppState app = static struct AppState app =
@ -65,11 +71,6 @@ LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
switch(msg) switch(msg)
{ {
case WM_CLOSE:
mouseHook_remove();
DestroyWindow(hwnd);
break;
case WM_DESTROY: case WM_DESTROY:
PostQuitMessage(0); PostQuitMessage(0);
break; break;
@ -80,6 +81,36 @@ LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return cf->fn(cf->wParam, cf->lParam); return cf->fn(cf->wParam, cf->lParam);
} }
case WM_TRAYICON:
{
if (lParam == WM_RBUTTONDOWN)
{
POINT curPoint;
GetCursorPos(&curPoint);
SetForegroundWindow(hwnd);
UINT clicked = TrackPopupMenu(
app.trayMenu,
TPM_RETURNCMD | TPM_NONOTIFY,
curPoint.x,
curPoint.y,
0,
hwnd,
NULL
);
if (clicked == ID_MENU_EXIT ) app_quit();
else if (clicked == ID_MENU_OPEN_LOG)
{
const char * logFile = option_get_string("os", "logFile");
if (strcmp(logFile, "stderr") == 0)
DEBUG_INFO("Ignoring request to open the logFile, logging to stderr");
else
ShellExecute(NULL, NULL, logFile, NULL, NULL, SW_SHOWNORMAL);
}
}
break;
}
default: default:
return DefWindowProc(hwnd, msg, wParam, lParam); return DefWindowProc(hwnd, msg, wParam, lParam);
} }
@ -88,8 +119,23 @@ LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
static int appThread(void * opaque) static int appThread(void * opaque)
{ {
// register our TrayIcon
NOTIFYICONDATA iconData =
{
.cbSize = sizeof(NOTIFYICONDATA),
.hWnd = app.messageWnd,
.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP,
.uCallbackMessage = WM_TRAYICON,
.szTip = "Looking Glass (host)"
};
iconData.hIcon = LoadIcon(app.hInst, IDI_APPLICATION);
Shell_NotifyIcon(NIM_ADD, &iconData);
int result = app_main(app.argc, app.argv); int result = app_main(app.argc, app.argv);
SendMessage(app.messageWnd, WM_CLOSE, 0, 0);
Shell_NotifyIcon(NIM_DELETE, &iconData);
mouseHook_remove();
SendMessage(app.messageWnd, WM_DESTROY, 0, 0);
return result; return result;
} }
@ -112,6 +158,7 @@ static BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ {
int result = 0; int result = 0;
app.hInst = hInstance;
char tempPath[MAX_PATH+1]; char tempPath[MAX_PATH+1];
GetTempPathA(sizeof(tempPath), tempPath); GetTempPathA(sizeof(tempPath), tempPath);
@ -164,6 +211,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
wx.lpfnWndProc = DummyWndProc; wx.lpfnWndProc = DummyWndProc;
wx.hInstance = hInstance; wx.hInstance = hInstance;
wx.lpszClassName = "DUMMY_CLASS"; wx.lpszClassName = "DUMMY_CLASS";
wx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wx.hCursor = LoadCursor(NULL, IDC_ARROW);
wx.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
if (!RegisterClassEx(&wx)) if (!RegisterClassEx(&wx))
{ {
DEBUG_ERROR("Failed to register message window class"); DEBUG_ERROR("Failed to register message window class");
@ -172,6 +223,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
} }
app.messageWnd = CreateWindowEx(0, "DUMMY_CLASS", "DUMMY_NAME", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); app.messageWnd = CreateWindowEx(0, "DUMMY_CLASS", "DUMMY_NAME", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
app.trayMenu = CreatePopupMenu();
AppendMenu(app.trayMenu, MF_STRING , ID_MENU_OPEN_LOG, "Open Log File");
AppendMenu(app.trayMenu, MF_SEPARATOR, 0 , NULL );
AppendMenu(app.trayMenu, MF_STRING , ID_MENU_EXIT , "Exit" );
// create the application thread // create the application thread
osThreadHandle * thread; osThreadHandle * thread;
if (!os_createThread("appThread", appThread, NULL, &thread)) if (!os_createThread("appThread", appThread, NULL, &thread))
@ -202,6 +258,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
} }
shutdown: shutdown:
DestroyMenu(app.trayMenu);
app_quit(); app_quit();
if (!os_joinThread(thread, &result)) if (!os_joinThread(thread, &result))
{ {

View File

@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <windows.h> #include <windows.h>
#define WM_CALL_FUNCTION (WM_USER+1) #define WM_CALL_FUNCTION (WM_USER+1)
#define WM_TRAYICON (WM_USER+2)
typedef LRESULT (*CallFunction)(WPARAM wParam, LPARAM lParam); typedef LRESULT (*CallFunction)(WPARAM wParam, LPARAM lParam);
struct MSG_CALL_FUNCTION struct MSG_CALL_FUNCTION