diff --git a/wCenterWindow/Resource.h b/wCenterWindow/Resource.h index e334def..e56104a 100644 --- a/wCenterWindow/Resource.h +++ b/wCenterWindow/Resource.h @@ -1,27 +1,24 @@ -//{{NO_DEPENDENCIES}} -// Включаемый файл, созданный в Microsoft Visual C++. -// Используется wCenterWindow.rc +// resource.h +#define IDS_APP_TITLE 100 +#define IDS_CLASSNAME 101 +#define IDS_HELPTEXT 102 +#define IDI_TRAYICON 103 +#define IDR_MENU 104 +#define ID_POPUPMENU_HELP 105 +#define ID_POPUPMENU_EXIT 106 +#define IDS_ERR_MAIN 107 +#define IDS_ERR_WND 108 +#define IDS_ERR_ICON 109 +#define IDS_ERR_MENU 110 +#define IDS_ERR_POPUP 111 +#define IDS_ERR_HOOK 112 +#define IDS_RUNNING 113 +#define IDC_STATIC -1 -#define IDS_APP_TITLE 103 - -#define IDR_MAINFRAME 128 -#define IDD_WCENTERWINDOW_DIALOG 102 -#define IDD_ABOUTBOX 103 -#define IDM_ABOUT 104 -#define IDM_EXIT 105 -#define IDI_WCENTERWINDOW 107 -#define IDI_SMALL 108 -#define IDC_WCENTERWINDOW 109 -#define IDC_MYICON 2 -#ifndef IDC_STATIC -#define IDC_STATIC -1 -#endif -// Следующие стандартные значения для новых объектов -// +// Next default values for new objects #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS - -#define _APS_NO_MFC 130 +#define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 129 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 1000 diff --git a/wCenterWindow/framework.h b/wCenterWindow/framework.h index a8f6dc8..4a9e0e6 100644 --- a/wCenterWindow/framework.h +++ b/wCenterWindow/framework.h @@ -8,6 +8,8 @@ #define WIN32_LEAN_AND_MEAN // Исключите редко используемые компоненты из заголовков Windows // Файлы заголовков Windows #include +#include +#include // Файлы заголовков среды выполнения C #include #include diff --git a/wCenterWindow/small.ico b/wCenterWindow/small.ico deleted file mode 100644 index b3ec03b..0000000 Binary files a/wCenterWindow/small.ico and /dev/null differ diff --git a/wCenterWindow/wCenterWindow.cpp b/wCenterWindow/wCenterWindow.cpp index cd0329b..aafc94d 100644 --- a/wCenterWindow/wCenterWindow.cpp +++ b/wCenterWindow/wCenterWindow.cpp @@ -4,177 +4,207 @@ #include "framework.h" #include "wCenterWindow.h" -#define MAX_LOADSTRING 100 +#define MAX_LOADSTRING 80 +#define WM_WCW WM_USER + 0x7F00 // Глобальные переменные: -HINSTANCE hInst; // текущий экземпляр -WCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка -WCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна +HINSTANCE hInst; // Текущий экземпляр +WCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка +WCHAR szClass[MAX_LOADSTRING]; // Имя класса главного окна +WCHAR szHelp[MAX_LOADSTRING]; // Текст описания +HHOOK KeyboardHook; +HICON hIcon; +HMENU hMenu, hPopup; +HWND hWnd; +NOTIFYICONDATA nid = { 0 }; +KBDLLHOOKSTRUCT *pkhs; +int dtCenterX, dtCenterY; +bool pressed = FALSE; -// Отправить объявления функций, включенных в этот модуль кода: -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +// Прототипы функций +ATOM MyRegisterClass(HINSTANCE); +VOID ShowError(HINSTANCE, UINT); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK KeyboardHookProc(int, WPARAM, LPARAM); -int APIENTRY wWinMain(_In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPWSTR lpCmdLine, - _In_ int nCmdShow) +// Точка входа +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) { - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); - // TODO: Разместите код здесь. + LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadStringW(hInstance, IDS_CLASSNAME, szClass, MAX_LOADSTRING); + if (FindWindow(szClass, NULL)) + { + ShowError(hInstance, IDS_RUNNING); + return FALSE; + } + MyRegisterClass(hInstance); + hWnd = CreateWindowExW(0, szClass, szTitle, 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); + if (!hWnd) + { + ShowError(hInstance, IDS_ERR_WND); + return FALSE; + } - // Инициализация глобальных строк - LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); - LoadStringW(hInstance, IDC_WCENTERWINDOW, szWindowClass, MAX_LOADSTRING); - MyRegisterClass(hInstance); + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = hWnd; + nid.uVersion = NOTIFYICON_VERSION; + nid.uCallbackMessage = WM_WCW; + nid.hIcon = hIcon; + nid.uID = IDI_TRAYICON; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + nid.dwInfoFlags = NIIF_INFO; + StringCchCopy(nid.szTip, sizeof(nid.szTip), szTitle); + if (!Shell_NotifyIcon(NIM_ADD, &nid)) + { + ShowError(hInstance, IDS_ERR_ICON); + SendMessage(hWnd, WM_CLOSE, NULL, NULL); + } - // Выполнить инициализацию приложения: - if (!InitInstance (hInstance, nCmdShow)) - { - return FALSE; - } + hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU)); + if (!hMenu) + { + ShowError(hInstance, IDS_ERR_MENU); + SendMessage(hWnd, WM_CLOSE, NULL, NULL); + } - HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WCENTERWINDOW)); + hPopup = GetSubMenu(hMenu, 0); + if (!hPopup) + { + ShowError(hInstance, IDS_ERR_POPUP); + SendMessage(hWnd, WM_CLOSE, NULL, NULL); + } - MSG msg; + KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, hInstance, NULL); + if (!KeyboardHook) + { + ShowError(hInstance, IDS_ERR_HOOK); + SendMessage(hWnd, WM_CLOSE, NULL, NULL); + } - // Цикл основного сообщения: - while (GetMessage(&msg, nullptr, 0, 0)) - { - if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } + LoadStringW(hInstance, IDS_HELPTEXT, szHelp, MAX_LOADSTRING); + RECT dtrc = { 0 }; + SystemParametersInfo(SPI_GETWORKAREA, NULL, &dtrc, FALSE); + dtCenterX = dtrc.right / 2, dtCenterY = dtrc.bottom / 2; - return (int) msg.wParam; + MSG msg; + BOOL bRet; + + while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) + { + if (bRet == -1) + { + ShowError(hInstance, IDS_ERR_MAIN); + return -1; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return (int)msg.wParam; } - - -// -// ФУНКЦИЯ: MyRegisterClass() -// -// ЦЕЛЬ: Регистрирует класс окна. -// ATOM MyRegisterClass(HINSTANCE hInstance) { - WNDCLASSEXW wcex; - - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WCENTERWINDOW)); - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WCENTERWINDOW); - wcex.lpszClassName = szWindowClass; - wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); - - return RegisterClassExW(&wcex); + WNDCLASSEX wcex = { 0 }; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = WndProc; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRAYICON)); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.lpszClassName = szClass; + wcex.hIconSm = wcex.hIcon; + hIcon = wcex.hIcon; + return RegisterClassEx(&wcex); } -// -// ФУНКЦИЯ: InitInstance(HINSTANCE, int) -// -// ЦЕЛЬ: Сохраняет маркер экземпляра и создает главное окно -// -// КОММЕНТАРИИ: -// -// В этой функции маркер экземпляра сохраняется в глобальной переменной, а также -// создается и выводится главное окно программы. -// -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) -{ - hInst = hInstance; // Сохранить маркер экземпляра в глобальной переменной - - HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); - - if (!hWnd) - { - return FALSE; - } - - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); - - return TRUE; -} - -// -// ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM) -// -// ЦЕЛЬ: Обрабатывает сообщения в главном окне. -// -// WM_COMMAND - обработать меню приложения -// WM_PAINT - Отрисовка главного окна -// WM_DESTROY - отправить сообщение о выходе и вернуться -// -// LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch (message) - { - case WM_COMMAND: - { - int wmId = LOWORD(wParam); - // Разобрать выбор в меню: - switch (wmId) - { - case IDM_ABOUT: - DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); - break; - case IDM_EXIT: - DestroyWindow(hWnd); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - } - break; - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hWnd, &ps); - // TODO: Добавьте сюда любой код прорисовки, использующий HDC... - EndPaint(hWnd, &ps); - } - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; + switch (message) + { + case WM_WCW: + if (lParam == WM_RBUTTONDOWN && wParam == IDI_TRAYICON) + { + SetForegroundWindow(hWnd); + POINT pt; + GetCursorPos(&pt); + int idMenu = TrackPopupMenu(hPopup, TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL); + if (idMenu == ID_POPUPMENU_HELP && !pressed) + { + pressed = TRUE; + if (MessageBox(hWnd, szHelp, szTitle, MB_OK | MB_TOPMOST) == IDOK) pressed = FALSE; + } + if (idMenu == ID_POPUPMENU_EXIT) SendMessage(hWnd, WM_CLOSE, NULL, NULL); + } + break; + + case WM_DESTROY: + if (KeyboardHook) UnhookWindowsHookEx(KeyboardHook); + if (hMenu) DestroyMenu(hMenu); + Shell_NotifyIcon(NIM_DELETE, &nid); + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; } -// Обработчик сообщений для окна "О программе". -INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(lParam); - switch (message) - { - case WM_INITDIALOG: - return (INT_PTR)TRUE; + pkhs = (KBDLLHOOKSTRUCT*)lParam; + bool bLCTRL, bLWIN; + GetAsyncKeyState(VK_LCONTROL) < 0 ? bLCTRL = TRUE : bLCTRL = FALSE; + GetAsyncKeyState(VK_LWIN) < 0 ? bLWIN = TRUE : bLWIN = FALSE; - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - return (INT_PTR)FALSE; + if ((bLCTRL && bLWIN && pkhs->vkCode == 0x43) && !pressed) + { + pressed = TRUE; + HWND fgWindow = GetForegroundWindow(); + if (fgWindow) + { + HWND parentWindow = fgWindow; + while (TRUE) + { + parentWindow = GetParent(fgWindow); + if (parentWindow) fgWindow = parentWindow; + else break; + } + + WINDOWPLACEMENT wp = { 0 }; + wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(fgWindow, &wp); + if (wp.showCmd == SW_SHOWNORMAL) + { + int fgW = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + int fgH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + int fgX = dtCenterX - (fgW / 2); + int fgY = dtCenterY - (fgH / 2); + wp.rcNormalPosition.left = fgX; + wp.rcNormalPosition.top = fgY; + wp.rcNormalPosition.right = fgX + fgW; + wp.rcNormalPosition.bottom = fgY + fgH; + SendMessage(fgWindow, WM_ENTERSIZEMOVE, NULL, NULL); + SetWindowPlacement(fgWindow, &wp); + SendMessage(fgWindow, WM_EXITSIZEMOVE, NULL, NULL); + } + } + pressed = FALSE; + } + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +VOID ShowError(HINSTANCE hInstance, UINT uID) +{ + WCHAR szErrorText[MAX_LOADSTRING]; // Текст ошибки + LoadStringW(hInstance, uID, szErrorText, MAX_LOADSTRING); + MessageBox(hWnd, szErrorText, szTitle, MB_OK | MB_ICONERROR); } diff --git a/wCenterWindow/wCenterWindow.ico b/wCenterWindow/wCenterWindow.ico index b3ec03b..a743458 100644 Binary files a/wCenterWindow/wCenterWindow.ico and b/wCenterWindow/wCenterWindow.ico differ diff --git a/wCenterWindow/wCenterWindow.rc b/wCenterWindow/wCenterWindow.rc index 5a5fefe..931f160 100644 Binary files a/wCenterWindow/wCenterWindow.rc and b/wCenterWindow/wCenterWindow.rc differ diff --git a/wCenterWindow/wCenterWindow.vcxproj b/wCenterWindow/wCenterWindow.vcxproj index f9b82c6..566c43f 100644 --- a/wCenterWindow/wCenterWindow.vcxproj +++ b/wCenterWindow/wCenterWindow.vcxproj @@ -123,12 +123,14 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + None Windows true true - true + false + false @@ -152,7 +154,7 @@ - + @@ -163,7 +165,6 @@ - diff --git a/wCenterWindow/wCenterWindow.vcxproj.filters b/wCenterWindow/wCenterWindow.vcxproj.filters index 46226a2..88303ad 100644 --- a/wCenterWindow/wCenterWindow.vcxproj.filters +++ b/wCenterWindow/wCenterWindow.vcxproj.filters @@ -21,10 +21,10 @@ Файлы заголовков - + Файлы заголовков - + Файлы заголовков @@ -39,9 +39,6 @@ - - Файлы ресурсов - Файлы ресурсов