Sandboxie/SandboxiePlus/SandMan/Helpers/WindowFromPointEx.cpp

158 lines
3.9 KiB
C++

#include "stdafx.h"
//
// WindowFromPointEx.c
//
// Copyright (c) 2002 by J Brown
// Freeware
//
// HWND WindowFromPointEx(POINT pt)
//
// Provides a better implementation of WindowFromPoint.
// This function can return any window under the mouse,
// including controls nested inside group-boxes, nested
// dialogs etc.
//
#define STRICT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <tchar.h>
static HWND hwndGlobal;
static HWND hwndButton;
static BOOL g_fShowHidden;
static DWORD dwArea;
//
// Callback function used with FindBestChild
//
static BOOL CALLBACK FindBestChildProc(HWND hwnd, LPARAM lParam)
{
RECT rect;
DWORD a;
POINT pt;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
GetWindowRect(hwnd, &rect);
// Is the mouse inside this child window?
if (PtInRect(&rect, pt))
{
// work out area of child window
a = (rect.right - rect.left) * (rect.bottom - rect.top);
// if this child window is smaller than the
// current "best", then choose this one
if (a < dwArea && (IsWindowVisible(hwnd) || g_fShowHidden == TRUE))
{
dwArea = a;
hwndGlobal = hwnd;
}
}
return TRUE;
}
//
// The problem:
//
// WindowFromPoint API is not very good. It cannot cope
// with odd window arrangements, i.e. a group-box in a dialog
// may contain a few check-boxes. These check-boxes are not
// children of the groupbox, but are at the same "level" in the
// window-hierachy. WindowFromPoint will just return the
// first available window it finds which encompasses the mouse
// (i.e. the group-box), but will NOT be able to detect the contents.
//
// Solution:
//
// We use WindowFromPoint to start us off, and then step back one
// level (i.e. from the parent of what WindowFromPoint returned).
//
// Once we have this window, we enumerate ALL children of this window
// ourselves, and find the one that best fits under the mouse -
// the smallest window that fits, in fact.
//
// I've tested this on a lot of different apps, and it seems
// to work flawlessly - in fact, I haven't found a situation yet
// that this method doesn't work on.....we'll see!
//
// Inputs:
//
// hwndFound - window found with WindowFromPoint
// pt - coordinates of mouse, in screen coords
// (i.e. same coords used with WindowFromPoint)
//
static HWND FindBestChild(HWND hwndFound, POINT pt)
{
HWND hwnd;
DWORD dwStyle;
dwArea = -1; // Start off again
hwndGlobal = 0;
hwnd = GetParent(hwndFound);
dwStyle = GetWindowLong(hwndFound, GWL_STYLE);
// The original window might already be a top-level window,
// so we don't want to start at *it's* parent
if (hwnd == 0 || (dwStyle & WS_POPUP))
hwnd = hwndFound;
// Enumerate EVERY child window.
//
// Note to reader:
//
// You can get some real interesting effects if you set
// hwnd = GetDesktopWindow()
// fShowHidden = TRUE
// ...experiment!!
//
EnumChildWindows(hwnd, FindBestChildProc, MAKELPARAM(pt.x, pt.y));
if (hwndGlobal == 0)
hwndGlobal = hwnd;
return hwndGlobal;
}
//
// Find window under specified point (screen coordinates)
//
HWND WindowFromPointEx(POINT pt, BOOL fShowHidden)
{
HWND hWndPoint;
g_fShowHidden = fShowHidden;
//
// First of all find the parent window under the mouse
// We are working in SCREEN coordinates
//
hWndPoint = WindowFromPoint(pt);
if (hWndPoint == 0)
return 0;
// WindowFromPoint is not too accurate. There is quite likely
// another window under the mouse.
hWndPoint = FindBestChild(hWndPoint, pt);
//if we don't allow hidden windows, then return the parent
if (!g_fShowHidden)
{
while (hWndPoint && !IsWindowVisible(hWndPoint))
hWndPoint = GetParent(hWndPoint);
}
return hWndPoint;
}