В Windows 10 я экспериментировал с заменой функции «Привязка окна» для лучшей работы с ультраширокими мониторами.Хотя у меня не было проблем с захватом курсоров Windows Key + для обработки сочетаний клавиш, теперь я хочу определить, когда другое окно приложения было перетащено в верхнюю / правую / левую / нижнюю часть текущего монитора.
Текущий код:
#include <iostream>
#include <Windows.h>
HHOOK _hook_keyboard;
KBDLLHOOKSTRUCT kbdStruct;
CONST int HORIZONTAL_SLOTS = 4;
CONST int VERTICAL_SLOTS = 1;
// horizontalPosition/verticalPosition specifies which "slot" starting at 0 to place Window in
// horizontalSlots/verticalSlots specifies how many slots to divide the screen into
void MoveAndResizeActiveWindow(int horizontalPosition, int verticalPosition, int horizontalSlots, int verticalSlots)
{
// get work area on primary monitor
HWND currentWindow = GetForegroundWindow();
if (currentWindow != NULL)
{
HMONITOR currentMonitor = MonitorFromWindow(currentWindow, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
if (GetMonitorInfo(currentMonitor, &monitorInfo))
{
long width = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
long height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
long snappedWidth = width / horizontalSlots;
long snappedHeight = height / verticalSlots;
long snappedLeft = (snappedWidth * horizontalPosition) + monitorInfo.rcWork.left;
long snappedTop = (snappedHeight * verticalPosition) + monitorInfo.rcWork.top;
MoveWindow(currentWindow, snappedLeft, snappedTop, snappedWidth, snappedHeight, true);
}
}
}
LRESULT __stdcall HookCallbackKeyboard(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL bEatkeystroke = false;
short keyState;
if (nCode >= 0)
{
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
switch (wParam)
{
case WM_KEYDOWN:
keyState = GetAsyncKeyState(VK_LWIN);
if (keyState)
{
switch (kbdStruct.vkCode)
{
case VK_LEFT:
bEatkeystroke = true;
break;
case VK_RIGHT:
bEatkeystroke = true;
break;
case VK_UP:
bEatkeystroke = true;
break;
case VK_DOWN:
bEatkeystroke = true;
break;
};
};
break;
case WM_KEYUP:
keyState = GetAsyncKeyState(VK_LWIN);
if (keyState)
{
switch (kbdStruct.vkCode)
{
case VK_LEFT:
MoveAndResizeActiveWindow(0, 0, 4, 1);
bEatkeystroke = true;
break;
case VK_RIGHT:
MoveAndResizeActiveWindow(3, 0, 4, 1);
bEatkeystroke = true;
break;
break;
case VK_UP:
MoveAndResizeActiveWindow(1, 0, 4, 1);
bEatkeystroke = true;
break;
case VK_DOWN:
MoveAndResizeActiveWindow(2, 0, 4, 1);
bEatkeystroke = true;
break;
};
}
break;
};
}
if (bEatkeystroke)
{
return 1;
}
else
{
return CallNextHookEx(_hook_keyboard, nCode, wParam, lParam);
}
}
void SetHook()
{
if (!(_hook_keyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallbackKeyboard, NULL, 0)))
{
MessageBox(NULL, L"Failed to install hook on keyboard!", L"Error", MB_ICONERROR);
}
}
int main(int argc, char** argv[])
{
SetHook();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Любые предложения, как определить, когда Windows была перетащена в определенное место на экране?
В соответствии с рекомендациями в ответах на оригинальный вопрос, которые я пытался использовать SetWinEventHookс помощью следующего кода, планируя ограничить EVENT_MIN и EVENT_MAX после исправления событий, которые нужно отслеживать, чтобы они были отработаны.
g_hook_winevent = SetWinEventHook(
EVENT_MIN, EVENT_MAX,
NULL, // Handle to DLL.
HandleWinEvent, // The callback.
0, 0, // Process and thread IDs of interest (0 = all)
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
LONG idObject, LONG idChild,
DWORD dwEventThread, DWORD dwmsEventTime)
{
// process event here
}
Хотя это легко отслеживает начало или конец перемещения Windows с помощью EVENT_SYSTEM_MOVESIZESTART и EVENT_SYSTEM_MOVESIZEEND, я не вижусобытие здесь, которое отслеживает перемещение окна до EVENT_SYSTEM_MOVESIZEEND.
Хотя это будет работать, если только удачный вариант, в идеале я хочу иметь возможность определять местоположение окна с начала EVENT_SYSTEM_MOVESIZESTART до завершения EVENT_SYSTEM_MOVESIZEEND.При тестировании с помощью блокнота единственное событие, которое возникает во время перемещения, это EVENT_OBJECT_NAMECHANGE, которое, кажется, постоянно срабатывает во время перемещения окна, по крайней мере, с помощью Блокнота.Однако, основываясь на описании в документации Я не уверен, подходит ли это для моего варианта использования: «свойство Name объекта изменилось. Система отправляет это событие для следующих элементов пользовательского интерфейса: флажок, курсор, управление просмотром списка, кнопка, переключатель, управление строкой состояния, управление просмотром дерева и объект окна. Серверные приложения отправляют это событие для своих доступных объектов. "