определение, находится ли окно в границах рабочего стола c ++ - PullRequest
3 голосов
/ 22 января 2011

Я написал некоторый код, чтобы определить, находится ли определенное окно в границах рабочего стола.Почему-то это не работает.Для каждого окна, независимо от того, находится оно внутри или снаружи рабочего стола, возвращается false.Что-то здесь ужасно не так, но, глядя на этот кусок кода в течение 3 часов, я все еще не знаю, в чем проблема.Если я пытаюсь прочитать структуру RECT из указателя, отправленного в WPARAM PMSG, я получаю AccessViolationException.Почему это происходит?

Мой код выглядит следующим образом и всегда возвращает false:

static bool IsInBounds(HWND window)
{
    DEVMODE d;
    d.dmSize = sizeof(DEVMODE);
    BOOL b = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
    if(b == FALSE)
    {
        PostMessage(FindWindow(NULL, L"Window #1"), RegisterWindowMessage(L"FMSG"), (WPARAM)window, NULL);
    }
    RECT R;
    GetWindowRect(window, &R);
    POINT p = POINT();
    p.x = (LONG)d.dmPelsWidth;
    p.y = (LONG)d.dmPelsHeight;
    PostMessage(FindWindow(NULL, L"Window #1"), RegisterWindowMessage(L"PMSG"), (WPARAM)&R, d.dmPelsWidth);
    if(R.right < 0 || R.bottom < 0 || R.left > (LONG)d.dmPelsWidth || R.top > (LONG)d.dmPelsHeight)
    {
        return false;
    }
    return true;
}

EDIT: после вызова IsInBounds, который возвратил ошибку 1400 (Неверный дескриптор окна), ноперед возвратом из ответного обратного вызова я позвонил IsWindow(window), чтобы проверить, действителен ли мой дескриптор.Правда в том, что это на деле действительная ручка!Как это может быть, что GetWindowRect говорит, что его недействительный дескриптор?

EDIT: я попытался MonitorFromWindow как sujested, но он возвратил NULL, и вызов GetLastError привел к ошибке №1400, что мне уже знакомо.Похоже, что MonitorFromWindow неявно вызывает GetWindowRect.Меня не волнует размер, но есть ли другой способ получить координаты окна из дескриптора?

Ответы [ 3 ]

4 голосов
/ 22 января 2011

PostMessage(FindWindow(NULL, L"Window #1"), RegisterWindowMessage(L"PMSG"), (WPARAM)&R, d.dmPelsWidth); не будет работать, если «Окно № 1» находится в другом процессе, вы не можете просто передать перекрестный процесс указателя RECT, если вам нужно передать нечто большее, чем перекрестный процесс указателя, используйте WM_COPYDATA.Даже если это не кросс-процесс, тот факт, что вы используете PostMessage, а не SendMessage, означает, что RECT, вероятно, находится вне области действия к моменту обработки сообщения!* MonitorFromWindow с MONITOR_DEFAULTTONULL должно быть всем, что вам нужно.

3 голосов
/ 23 января 2011

(1) Простой

RECT rDesk = { 0 };
GetBystemParametersInfo(SPI_GETWORKAREA, 0, &rDesk, 0);
RECT rWnd;
GetWindowRect(wnd, &rWnd);
POINT pttl = { rWnd.left, rWnd.top);
POINT ptbr = { rWnd.right, rWnd.bottom);
if (PtInRect(&rDesk, pttl) && PtInRect(&rDesk, ptbr)) 
   // ....

SPI_GETWORKAREA запрашивает область рабочего стола (в отличие от экрана, который включает панель задач и т. Д.) Замените GetSystemParametersInfo на GetMonitorInfo для поддержки несколькихмониторы.

(2) GetWindowRect
Принадлежит ли целевое окно процессу с повышенными правами или процессу, выполняющемуся в другом контексте безопасности?

(3) Другие замечания
Для RegisterMessage не используйте такие неуникальные имена.В конце концов, это работает в масштабе всей системы.Я ставлю точку встраивания GUID в их имя.

PostMessage уже упоминалось: он асинхронный, и вы можете передавать указатели перекрестного процесса.

Я не понимаю, почему вам нужно передать дескриптор окна другому, не связанному с ним окну.

2 голосов
/ 22 января 2011

PostMessage() асинхронный, и вы отправляете указатель на локальную переменную вашей функции (RECT R).Эта локальная переменная, скорее всего, исчезнет к тому времени, когда получатель приступит к обработке сообщения.

Кроме того, вам следует проверить возвращаемое значение GetWindowRect(), чтобы убедиться, что оно не завершилось ошибкой.*

Еще одна вещь, вы, вероятно, должны вернуться, если EnumDisplaySettings() не удалось.Тесты в строке 16 будут бессмысленными, если DEVMODE d не заполнено.

...