确定窗口是否在桌面边界c ++中

时间:2011-01-22 11:08:20

标签: c++ winapi window bounds

我写了一些代码来确定某个窗口是否在桌面边界内 不知何故,它不起作用。对于每个窗口,无论是在桌面内部还是外部,都会返回false。这里有些东西是非常错误的,但是现在盯着这段代码3个小时之后,我仍然不知道问题出在哪里。如果我尝试从PMSG的WPARAM中发送的指针读取RECT结构,我会得到一个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;
}

编辑: 在调用IsInBounds后,它返回错误号1400(无效的窗口句柄),但在从钩子回调返回之前,我调用了IsWindow(window),看看我的句柄是否仍然有效。事实是:是契约一个有效的句柄! GetWindowRect如何说它是一个无效的句柄?

编辑: 我尝试将MonitorFromWindow作为sujested,但它返回NULL,并且调用GetLastError导致错误号。 1400,这对我来说已经很熟悉了。看起来MonitorFromWindow隐式调用GetWindowRect。我不关心大小,但是是否有另一种方式从句柄获取窗口坐标?

3 个答案:

答案 0 :(得分:4)

如果“Window#1”在另一个进程中,

PostMessage(FindWindow(NULL, L"Window #1"), RegisterWindowMessage(L"PMSG"), (WPARAM)&R, d.dmPelsWidth);将不起作用,您不能只传递一个RECT指针交叉进程,如果您需要传递大于指针交叉进程的内容,请使用WM_COPYDATA。即使它不是跨进程,你使用PostMessage而不是SendMessage的事实意味着在处理消息时RECT可能超出了范围!

使用EnumDisplaySettings有点矫枉过正,使用MONITOR_DEFAULTTONULL的MonitorFromWindow应该就是您所需要的。

答案 1 :(得分:3)

(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 :(得分:2)

PostMessage()是异步的,您正在发送指向函数局部变量的指针(RECT R)。当接收者处理消息时,该局部变量很可能已经消失。

此外,您应该检查GetWindowRect()的返回值,以确保它没有失败。

另一件事,如果EnumDisplaySettings()失败,你应该回来。如果DEVMODE d尚未填写,第16行的测试将是荒谬的。