|
|
最后是源代码:
- #define _CRT_SECURE_NO_WARNINGS // 禁用安全警告 (解决 C4996)
- #define _CRT_NON_CONFORMING_WCSTOK // 允许使用旧版双参数 wcstok
- #include <windows.h>
- #include <shellapi.h>
- #pragma comment(lib, "User32.lib")
- #pragma comment(lib, "Shell32.lib")
- #pragma comment(lib, "Gdi32.lib")
- #pragma comment(lib, "Kernel32.lib")
- // 纯手写结构体,不依赖 STL
- struct AppNode {
- wchar_t name[64];
- wchar_t path[MAX_PATH];
- int level;
- HICON hIcon;
- };
- // 全局静态数组(简单处理,假设最多 50 个条目)
- AppNode g_nodes[50];
- int g_nodeCount = 0;
- HFONT hFontMain = NULL;
- bool g_visible = false;
- int g_menuHeight = 600;
- int g_menuWidth = 450;
- // 1. 原生文件解析:手动处理换行和缩进
- void LoadConfig() {
- for (int i = 0; i < g_nodeCount; i++) if (g_nodes[i].hIcon) DestroyIcon(g_nodes[i].hIcon);
- g_nodeCount = 0;
- HANDLE hFile = CreateFile(L"config.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) return;
- DWORD fileSize = GetFileSize(hFile, NULL);
- char* buffer = (char*)HeapAlloc(GetProcessHeap(), 0, fileSize + 1);
- DWORD read;
- ReadFile(hFile, buffer, fileSize, &read, NULL);
- buffer[fileSize] = '\0';
- CloseHandle(hFile);
- // 简单的按行解析逻辑 (UTF-8 转 WideChar)
- int nLen = MultiByteToWideChar(CP_UTF8, 0, buffer, fileSize, NULL, 0);
- wchar_t* wBuf = (wchar_t*)HeapAlloc(GetProcessHeap(), 0, (nLen + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, buffer, fileSize, wBuf, nLen);
- wBuf[nLen] = L'\0';
- wchar_t* line = wcstok(wBuf, L"\r\n");
- while (line && g_nodeCount < 50) {
- int indent = 0;
- while (line[indent] == L'\t') indent++;
- g_nodes[g_nodeCount].level = indent;
- wchar_t* content = line + indent;
- wchar_t* split = wcschr(content, L'|');
- if (split) {
- *split = L'\0';
- lstrcpyn(g_nodes[g_nodeCount].name, content, 64);
- lstrcpyn(g_nodes[g_nodeCount].path, split + 1, MAX_PATH);
- SHFILEINFO sfi = { 0 };
- SHGetFileInfo(g_nodes[g_nodeCount].path, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SMALLICON);
- g_nodes[g_nodeCount].hIcon = sfi.hIcon;
- }
- else {
- lstrcpyn(g_nodes[g_nodeCount].name, content, 64);
- g_nodes[g_nodeCount].path[0] = L'\0';
- g_nodes[g_nodeCount].hIcon = NULL;
- }
- g_nodeCount++;
- line = wcstok(NULL, L"\r\n");
- }
- HeapFree(GetProcessHeap(), 0, buffer);
- HeapFree(GetProcessHeap(), 0, wBuf);
- }
- // 2. 动态热键与 INI (纯 API 版)
- void UpdateHotkeys(HWND hWnd) {
- for (int i = 1; i <= 4; i++) UnregisterHotKey(hWnd, i);
- wchar_t path[MAX_PATH];
- GetModuleFileName(NULL, path, MAX_PATH);
- wchar_t* lastSlash = wcsrchr(path, L'\\');
- if (lastSlash) lstrcpy(lastSlash + 1, L"settings.ini");
- UINT vk = GetPrivateProfileInt(L"Hotkey", L"WakeUpKey", 0x20, path);
- UINT mod = GetPrivateProfileInt(L"Hotkey", L"WakeUpMod", 1, path);
- g_menuWidth = GetPrivateProfileInt(L"Appearance", L"MenuWidth", 450, path);
- if (!g_visible) g_menuHeight = GetPrivateProfileInt(L"Appearance", L"MenuHeight", 600, path);
- RegisterHotKey(hWnd, 1, mod, vk);
- RegisterHotKey(hWnd, 2, MOD_ALT | MOD_CONTROL, 0x51);
- RegisterHotKey(hWnd, 3, mod | MOD_WIN | MOD_CONTROL, VK_UP);
- RegisterHotKey(hWnd, 4, mod | MOD_WIN | MOD_CONTROL, VK_DOWN);
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
- switch (msg) {
- case WM_CREATE:
- UpdateHotkeys(hWnd);
- hFontMain = CreateFont(24, 0, 0, 0, FW_BOLD, 0, 0, 0, 1, 0, 0, 2, 0, L"Microsoft YaHei");
- LoadConfig();
- break;
- case WM_HOTKEY:
- if (wp == 1) {
- if (!g_visible) {
- UpdateHotkeys(hWnd); LoadConfig();
- POINT pt; GetCursorPos(&pt);
- SetWindowPos(hWnd, HWND_TOPMOST, pt.x, pt.y, g_menuWidth, g_menuHeight, SWP_SHOWWINDOW);
- SetForegroundWindow(hWnd); g_visible = true;
- }
- else { ShowWindow(hWnd, SW_HIDE); g_visible = false; }
- }
- else if (wp == 2) DestroyWindow(hWnd);
- else if (wp == 3) { g_menuHeight += 40; SetWindowPos(hWnd, 0, 0, 0, g_menuWidth, g_menuHeight, SWP_NOMOVE); InvalidateRect(hWnd, 0, 1); }
- else if (wp == 4) { g_menuHeight -= 40; SetWindowPos(hWnd, 0, 0, 0, g_menuWidth, g_menuHeight, SWP_NOMOVE); InvalidateRect(hWnd, 0, 1); }
- break;
- case WM_PAINT: {
- PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);
- RECT rc; GetClientRect(hWnd, &rc);
- HBRUSH hBr = CreateSolidBrush(RGB(20, 20, 20)); FillRect(hdc, &rc, hBr); DeleteObject(hBr);
- SelectObject(hdc, hFontMain); SetBkMode(hdc, TRANSPARENT);
- int spacing = (g_nodeCount > 1) ? (g_menuHeight - 60) / (g_nodeCount - 1) : 55;
- if (spacing > 60) spacing = 60;
- for (int i = 0; i < g_nodeCount; i++) {
- int x = 30 + (g_nodes[i].level * 40);
- int y = 30 + i * spacing;
- if (g_nodes[i].hIcon) DrawIconEx(hdc, x, y + 4, g_nodes[i].hIcon, 18, 18, 0, 0, 3);
- SetTextColor(hdc, RGB(220, 220, 220));
- TextOut(hdc, x + 25, y, g_nodes[i].name, lstrlen(g_nodes[i].name));
- }
- EndPaint(hWnd, &ps);
- } break;
- case WM_LBUTTONDOWN: {
- int my = HIWORD(lp);
- int spacing = (g_nodeCount > 1) ? (g_menuHeight - 60) / (g_nodeCount - 1) : 55;
- if (spacing > 60) spacing = 60;
- int idx = (my - 20) / spacing;
- if (idx >= 0 && idx < g_nodeCount && g_nodes[idx].path[0]) {
- ShellExecute(NULL, L"open", g_nodes[idx].path, NULL, NULL, SW_SHOWNORMAL);
- ShowWindow(hWnd, SW_HIDE); g_visible = false;
- }
- } break;
- case WM_ACTIVATE: if (LOWORD(wp) == WA_INACTIVE) { ShowWindow(hWnd, SW_HIDE); g_visible = false; } break;
- case WM_DESTROY: PostQuitMessage(0); break;
- default: return DefWindowProc(hWnd, msg, wp, lp);
- }
- return 0;
- }
- #pragma comment(linker,""/manifestdependency:type='win32' \
- name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
- processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"")
- int APIENTRY wWinMain(HINSTANCE hi, HINSTANCE, LPWSTR, int) {
- WNDCLASS wc = { 0 }; wc.lpfnWndProc = WndProc; wc.hInstance = hi; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpszClassName = L"TinyML";
- RegisterClass(&wc);
- HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, L"TinyML", L"ML", WS_POPUP, 0, 0, 0, 0, 0, 0, hi, 0);
- MSG msg; while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
- return 0;
- }
复制代码
|
|