Add DeskTools source (main, header, DeskIcons, SeeThru, QuickNote)
This commit is contained in:
+261
@@ -0,0 +1,261 @@
|
||||
// DeskTools: DeskIcons, SeeThru, QuickNote and Pin a Window in one small tray program.
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT 0x0A00
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <objbase.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include "desktools.h"
|
||||
|
||||
#define APP_NAME L"DeskTools"
|
||||
#define WM_TRAY (WM_APP + 50)
|
||||
|
||||
#define BASE_DI 10000
|
||||
#define BASE_ST 20000
|
||||
#define BASE_QN 30000
|
||||
#define BASE_PW 40000
|
||||
#define IDM_STARTUP 1
|
||||
#define IDM_HELP 2
|
||||
#define IDM_EXIT 3
|
||||
|
||||
static HINSTANCE g_inst;
|
||||
static HWND g_main;
|
||||
static HHOOK g_hook;
|
||||
static NOTIFYICONDATAW g_nid;
|
||||
static UINT g_taskbarCreated;
|
||||
|
||||
/* ---------------- settings ---------------- */
|
||||
|
||||
static const WCHAR *RUN_KEY = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
||||
|
||||
static BOOL RunEntryExists(const WCHAR *name) {
|
||||
WCHAR buf[MAX_PATH * 2]; DWORD sz = sizeof(buf);
|
||||
return RegGetValueW(HKEY_CURRENT_USER, RUN_KEY, name, RRF_RT_REG_SZ, NULL, buf, &sz) == ERROR_SUCCESS;
|
||||
}
|
||||
static void DeleteRunEntry(const WCHAR *name) {
|
||||
HKEY k;
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, RUN_KEY, 0, KEY_WRITE, &k) == ERROR_SUCCESS) {
|
||||
RegDeleteValueW(k, name);
|
||||
RegCloseKey(k);
|
||||
}
|
||||
}
|
||||
static void SetStartup(BOOL on) {
|
||||
if (!on) { DeleteRunEntry(APP_NAME); return; }
|
||||
HKEY k;
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, RUN_KEY, 0, KEY_WRITE, &k) != ERROR_SUCCESS) return;
|
||||
WCHAR exe[MAX_PATH], val[MAX_PATH + 4];
|
||||
GetModuleFileNameW(NULL, exe, MAX_PATH);
|
||||
swprintf(val, MAX_PATH + 4, L"\"%ls\"", exe);
|
||||
RegSetValueExW(k, APP_NAME, 0, REG_SZ, (BYTE *)val, (DWORD)((wcslen(val) + 1) * sizeof(WCHAR)));
|
||||
RegCloseKey(k);
|
||||
}
|
||||
static DWORD GetSetting(const WCHAR *name, DWORD def) {
|
||||
DWORD v = def, sz = sizeof(v);
|
||||
if (RegGetValueW(HKEY_CURRENT_USER, L"Software\\DeskTools", name, RRF_RT_REG_DWORD, NULL, &v, &sz) != ERROR_SUCCESS)
|
||||
return def;
|
||||
return v;
|
||||
}
|
||||
static void PutSetting(const WCHAR *name, DWORD v) {
|
||||
HKEY k;
|
||||
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\DeskTools", 0, NULL, 0, KEY_WRITE, NULL, &k, NULL) == ERROR_SUCCESS) {
|
||||
RegSetValueExW(k, name, 0, REG_DWORD, (BYTE *)&v, sizeof(v));
|
||||
RegCloseKey(k);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- tray ---------------- */
|
||||
|
||||
void DT_Balloon(const WCHAR *title, const WCHAR *text) {
|
||||
if (!g_nid.hWnd) return;
|
||||
g_nid.uFlags = NIF_INFO;
|
||||
wcsncpy(g_nid.szInfoTitle, title, 63); g_nid.szInfoTitle[63] = 0;
|
||||
wcsncpy(g_nid.szInfo, text, 255); g_nid.szInfo[255] = 0;
|
||||
g_nid.dwInfoFlags = NIIF_INFO;
|
||||
Shell_NotifyIconW(NIM_MODIFY, &g_nid);
|
||||
}
|
||||
|
||||
static void AddTrayIcon(void) {
|
||||
ZeroMemory(&g_nid, sizeof(g_nid));
|
||||
g_nid.cbSize = sizeof(g_nid);
|
||||
g_nid.hWnd = g_main;
|
||||
g_nid.uID = 1;
|
||||
g_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
||||
g_nid.uCallbackMessage = WM_TRAY;
|
||||
g_nid.hIcon = (HICON)LoadImageW(g_inst, MAKEINTRESOURCEW(1), IMAGE_ICON,
|
||||
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
|
||||
wcscpy(g_nid.szTip, L"DeskTools");
|
||||
Shell_NotifyIconW(NIM_ADD, &g_nid);
|
||||
}
|
||||
|
||||
static void ShowHelp(void) {
|
||||
MessageBoxW(NULL,
|
||||
L"DESKICONS (send a window to the desktop)\n"
|
||||
L" Shift+click a window's minimize button, or press Ctrl+Alt+I.\n"
|
||||
L" Drag the label anywhere. Double-click it to bring the window back.\n\n"
|
||||
L"SEETHRU (make a window see-through)\n"
|
||||
L" Hold Ctrl+Shift and scroll over a window, down 5% at a time.\n"
|
||||
L" Ctrl+Alt+Page Down / Page Up on the active window.\n"
|
||||
L" Ctrl+Alt+Home: fully solid again. Ctrl+Alt+End: ghost mode\n"
|
||||
L" (stays on top, clicks pass through it).\n\n"
|
||||
L"QUICKNOTE (type on the desktop)\n"
|
||||
L" Double-click empty wallpaper and start typing.\n"
|
||||
L" Drag across text to select it, Ctrl+C to copy.\n"
|
||||
L" Drag the small gray square to move a note. Right-click for color or delete.\n\n"
|
||||
L"PIN A WINDOW (keep a window on top)\n"
|
||||
L" Press Ctrl+Alt+P to pin or unpin the active window,\n"
|
||||
L" or choose Pin a window... from the tray menu and click a window.\n"
|
||||
L" A blue box with a plus sign appears on its title bar.\n"
|
||||
L" Click that box to unpin it.\n\n"
|
||||
L"Each tool can be turned off from its submenu in the tray menu.\n"
|
||||
L"Exiting DeskTools brings every window back to normal.",
|
||||
L"How to use DeskTools", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
static void ShowTrayMenu(void) {
|
||||
HMENU m = CreatePopupMenu();
|
||||
AppendMenuW(m, MF_STRING | MF_GRAYED, 0, L"DeskTools");
|
||||
AppendMenuW(m, MF_SEPARATOR, 0, NULL);
|
||||
DI_AppendMenu(m, BASE_DI);
|
||||
ST_AppendMenu(m, BASE_ST);
|
||||
QN_AppendMenu(m, BASE_QN);
|
||||
PW_AppendMenu(m, BASE_PW);
|
||||
AppendMenuW(m, MF_SEPARATOR, 0, NULL);
|
||||
AppendMenuW(m, MF_STRING | (RunEntryExists(APP_NAME) ? MF_CHECKED : 0), IDM_STARTUP, L"Start with Windows");
|
||||
AppendMenuW(m, MF_STRING, IDM_HELP, L"How to use");
|
||||
AppendMenuW(m, MF_SEPARATOR, 0, NULL);
|
||||
AppendMenuW(m, MF_STRING, IDM_EXIT, L"Exit (puts every window back to normal)");
|
||||
POINT p; GetCursorPos(&p);
|
||||
SetForegroundWindow(g_main);
|
||||
UINT cmd = (UINT)TrackPopupMenu(m, TPM_RIGHTBUTTON | TPM_BOTTOMALIGN | TPM_RETURNCMD, p.x, p.y, 0, g_main, NULL);
|
||||
PostMessageW(g_main, WM_NULL, 0, 0);
|
||||
DestroyMenu(m); // also frees the submenus
|
||||
|
||||
if (!cmd) return;
|
||||
if (cmd >= BASE_DI && cmd < BASE_ST) { DI_Command(cmd - BASE_DI); PutSetting(L"DeskIcons", DI_IsEnabled()); }
|
||||
else if (cmd >= BASE_ST && cmd < BASE_QN) { ST_Command(cmd - BASE_ST); PutSetting(L"SeeThru", ST_IsEnabled()); }
|
||||
else if (cmd >= BASE_QN && cmd < BASE_PW) { QN_Command(cmd - BASE_QN); PutSetting(L"QuickNote", QN_IsEnabled()); }
|
||||
else if (cmd >= BASE_PW) { PW_Command(cmd - BASE_PW); PutSetting(L"PinWindow", PW_IsEnabled()); }
|
||||
else if (cmd == IDM_STARTUP) SetStartup(!RunEntryExists(APP_NAME));
|
||||
else if (cmd == IDM_HELP) ShowHelp();
|
||||
else if (cmd == IDM_EXIT) DestroyWindow(g_main);
|
||||
}
|
||||
|
||||
/* ---------------- one mouse hook for every tool ---------------- */
|
||||
|
||||
static LRESULT CALLBACK MouseLL(int code, WPARAM wp, LPARAM lp) {
|
||||
if (code == HC_ACTION) {
|
||||
MSLLHOOKSTRUCT *m = (MSLLHOOKSTRUCT *)lp;
|
||||
if (PW_Mouse(wp, m)) return 1; // picking a window to pin takes priority
|
||||
if (DI_Mouse(wp, m)) return 1;
|
||||
if (ST_Mouse(wp, m)) return 1;
|
||||
if (QN_Mouse(wp, m)) return 1;
|
||||
}
|
||||
return CallNextHookEx(g_hook, code, wp, lp);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK MainProc(HWND h, UINT msg, WPARAM wp, LPARAM lp) {
|
||||
if (msg == g_taskbarCreated && g_taskbarCreated) { AddTrayIcon(); return 0; }
|
||||
switch (msg) {
|
||||
case WM_TRAY:
|
||||
if (LOWORD(lp) == WM_RBUTTONUP || LOWORD(lp) == WM_LBUTTONUP) ShowTrayMenu();
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
if (g_hook) { UnhookWindowsHookEx(g_hook); g_hook = NULL; }
|
||||
PW_Shutdown();
|
||||
DI_Shutdown();
|
||||
ST_Shutdown();
|
||||
QN_Shutdown();
|
||||
Shell_NotifyIconW(NIM_DELETE, &g_nid);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProcW(h, msg, wp, lp);
|
||||
}
|
||||
|
||||
/* ---------------- start up ---------------- */
|
||||
|
||||
static BOOL OldAppRunning(const WCHAR *mutexName) {
|
||||
HANDLE m = OpenMutexW(SYNCHRONIZE, FALSE, mutexName);
|
||||
if (m) { CloseHandle(m); return TRUE; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef BOOL (WINAPI *SetDpiCtxFn)(HANDLE);
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, PWSTR cmd, int show) {
|
||||
(void)prev; (void)cmd; (void)show;
|
||||
g_inst = inst;
|
||||
|
||||
HANDLE mutex = CreateMutexW(NULL, TRUE, L"DeskTools_SingleInstance_Mutex");
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||
MessageBoxW(NULL, L"DeskTools is already running. Look for its icon in the system tray.", APP_NAME, MB_OK | MB_ICONINFORMATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The separate apps would fight DeskTools over the same shortcuts, so they need to be closed first.
|
||||
WCHAR running[160] = L"";
|
||||
if (OldAppRunning(L"DeskIcons_SingleInstance_Mutex")) wcscat(running, L" DeskIcons\n");
|
||||
if (OldAppRunning(L"SeeThru_SingleInstance_Mutex")) wcscat(running, L" SeeThru\n");
|
||||
if (OldAppRunning(L"QuickNote_SingleInstance_Mutex")) wcscat(running, L" QuickNote\n");
|
||||
if (running[0]) {
|
||||
WCHAR msg[512];
|
||||
swprintf(msg, 512, L"DeskTools already includes these, and they are still running on their own:\n\n%ls\n"
|
||||
L"Right-click each one's icon in the system tray and choose Exit, then start DeskTools again.", running);
|
||||
MessageBoxW(NULL, msg, APP_NAME, MB_OK | MB_ICONINFORMATION);
|
||||
ReleaseMutex(mutex); CloseHandle(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the separate apps were set to start with Windows, offer to switch that over to DeskTools.
|
||||
BOOL oldRun = RunEntryExists(L"DeskIcons") || RunEntryExists(L"SeeThru") || RunEntryExists(L"QuickNote");
|
||||
if (oldRun && !GetSetting(L"AskedAboutOldStartup", 0)) {
|
||||
PutSetting(L"AskedAboutOldStartup", 1);
|
||||
if (MessageBoxW(NULL, L"Some of the separate apps (DeskIcons, SeeThru, QuickNote) are set to start with Windows.\n\n"
|
||||
L"Turn those off and have DeskTools start with Windows instead?",
|
||||
APP_NAME, MB_YESNO | MB_ICONQUESTION) == IDYES) {
|
||||
DeleteRunEntry(L"DeskIcons"); DeleteRunEntry(L"SeeThru"); DeleteRunEntry(L"QuickNote");
|
||||
SetStartup(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
CoInitialize(NULL);
|
||||
SetDpiCtxFn setCtx = (SetDpiCtxFn)(void *)GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetProcessDpiAwarenessContext");
|
||||
if (!setCtx || !setCtx((HANDLE)-4)) SetProcessDPIAware();
|
||||
|
||||
WNDCLASSEXW wc; ZeroMemory(&wc, sizeof(wc));
|
||||
wc.cbSize = sizeof(wc); wc.lpfnWndProc = MainProc; wc.hInstance = inst; wc.lpszClassName = L"DeskToolsMain";
|
||||
wc.hIcon = LoadIconW(inst, MAKEINTRESOURCEW(1));
|
||||
RegisterClassExW(&wc);
|
||||
g_main = CreateWindowExW(0, L"DeskToolsMain", APP_NAME, 0, 0, 0, 0, 0, NULL, NULL, inst, NULL);
|
||||
g_taskbarCreated = RegisterWindowMessageW(L"TaskbarCreated");
|
||||
AddTrayIcon();
|
||||
|
||||
DI_Init(inst, GetSetting(L"DeskIcons", 1) != 0);
|
||||
ST_Init(inst, GetSetting(L"SeeThru", 1) != 0);
|
||||
QN_Init(inst, GetSetting(L"QuickNote", 1) != 0);
|
||||
PW_Init(inst, GetSetting(L"PinWindow", 1) != 0);
|
||||
g_hook = SetWindowsHookExW(WH_MOUSE_LL, MouseLL, inst, 0);
|
||||
|
||||
if (!GetSetting(L"Welcomed", 0)) {
|
||||
PutSetting(L"Welcomed", 1);
|
||||
DT_Balloon(L"DeskTools is running",
|
||||
L"DeskIcons, SeeThru, QuickNote and Pin a Window are all in this one icon. Right-click it for the menu and help.");
|
||||
}
|
||||
|
||||
MSG m;
|
||||
while (GetMessageW(&m, NULL, 0, 0) > 0) {
|
||||
TranslateMessage(&m);
|
||||
DispatchMessageW(&m);
|
||||
}
|
||||
CoUninitialize();
|
||||
ReleaseMutex(mutex); CloseHandle(mutex);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user