158 lines
4.1 KiB
C++
158 lines
4.1 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 alot of different apps, and it seems
|
|
// to work flawlessly - in fact, I havn'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;
|
|
}
|
|
|