This commit is contained in:
parent
82393e190e
commit
06046ad336
|
@ -0,0 +1,401 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
//
|
||||||
|
// WinSpy Finder Tool.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2002 by J Brown
|
||||||
|
// Freeware
|
||||||
|
//
|
||||||
|
// This is a standalone file which implements
|
||||||
|
// a "Finder Tool" similar to that used in Spy++
|
||||||
|
//
|
||||||
|
// There are two functions you must use:
|
||||||
|
//
|
||||||
|
// 1. BOOL MakeFinderTool(HWND hwnd, WNDFINDPROC wfp)
|
||||||
|
//
|
||||||
|
// hwnd - handle to a STATIC control to base the tool around.
|
||||||
|
// MakeFinderTool converts this control to the correct
|
||||||
|
// style, adds the bitmaps and mouse support etc.
|
||||||
|
//
|
||||||
|
// wfn - Event callback function. Must not be zero.
|
||||||
|
//
|
||||||
|
// Return values:
|
||||||
|
// TRUE for success, FALSE for failure
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 2. UINT CALLBACK WndFindProc(HWND hwndTool, UINT uCode, HWND hwnd)
|
||||||
|
//
|
||||||
|
// This is a callback function that you supply when using
|
||||||
|
// MakeFinderTool. This callback can be executed for a number
|
||||||
|
// different events - described by uCode.
|
||||||
|
//
|
||||||
|
// hwndTool - handle to the finder tool
|
||||||
|
//
|
||||||
|
// hwnd - handle to the window which has been found.
|
||||||
|
//
|
||||||
|
// uCode - describes the event. Can be one of the following values.
|
||||||
|
//
|
||||||
|
// WFN_BEGIN : tool is about to become active.
|
||||||
|
// WFN_SELCHANGING : sent when tool moves from window-window.
|
||||||
|
// WFN_SELCHANGED : sent when final window is selected.
|
||||||
|
// WFN_CANCELLED : Tool cancelled. hwnd is not valid (0)
|
||||||
|
//
|
||||||
|
// Return values:
|
||||||
|
// Return value is only checked for WFN_BEGIN. Return 0 (zero)
|
||||||
|
// to continue, -1 to prevent tool from being used. Otherwise,
|
||||||
|
// return 0 (zero) for all other messages
|
||||||
|
//
|
||||||
|
|
||||||
|
#define STRICT
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include "FindTool.h"
|
||||||
|
|
||||||
|
#define INVERT_BORDER 3
|
||||||
|
|
||||||
|
HWND WindowFromPointEx(POINT pt, BOOL fShowHidden);
|
||||||
|
|
||||||
|
static LONG lRefCount = 0;
|
||||||
|
|
||||||
|
static HCURSOR hOldCursor;
|
||||||
|
static HHOOK draghook = 0;
|
||||||
|
static HWND draghookhwnd = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle to the two dragger bitmaps
|
||||||
|
//
|
||||||
|
static HBITMAP hBitmapDrag1, hBitmapDrag2;
|
||||||
|
static HCURSOR hCursor;
|
||||||
|
|
||||||
|
//is the finder-tool being dragged??
|
||||||
|
static BOOL fDragging = FALSE;
|
||||||
|
|
||||||
|
// Old window procedure...?
|
||||||
|
static WNDPROC oldstaticproc;
|
||||||
|
|
||||||
|
|
||||||
|
static HWND hwndCurrent;
|
||||||
|
|
||||||
|
|
||||||
|
// show hidden windows
|
||||||
|
static BOOL fShowHidden = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Invert the specified window's border
|
||||||
|
//
|
||||||
|
void InvertWindow(HWND hwnd, BOOL fShowHidden)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
RECT rect2;
|
||||||
|
RECT rectc;
|
||||||
|
HDC hdc;
|
||||||
|
int x1,y1;
|
||||||
|
|
||||||
|
int border = INVERT_BORDER;
|
||||||
|
|
||||||
|
if(hwnd == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//window rectangle (screen coords)
|
||||||
|
GetWindowRect(hwnd, &rect);
|
||||||
|
|
||||||
|
//client rectangle (screen coords)
|
||||||
|
GetClientRect(hwnd, &rectc);
|
||||||
|
ClientToScreen(hwnd, (POINT *)&rectc.left);
|
||||||
|
ClientToScreen(hwnd, (POINT *)&rectc.right);
|
||||||
|
//MapWindowPoints(hwnd, 0, (POINT *)&rectc, 2);
|
||||||
|
|
||||||
|
x1 = rect.left;
|
||||||
|
y1 = rect.top;
|
||||||
|
OffsetRect(&rect, -x1, -y1);
|
||||||
|
OffsetRect(&rectc, -x1, -y1);
|
||||||
|
|
||||||
|
if(rect.bottom - border * 2 < 0)
|
||||||
|
border = 1;
|
||||||
|
|
||||||
|
if(rect.right - border * 2 < 0)
|
||||||
|
border = 1;
|
||||||
|
|
||||||
|
if(fShowHidden == TRUE)
|
||||||
|
hwnd = 0;
|
||||||
|
|
||||||
|
hdc = GetWindowDC(hwnd);
|
||||||
|
|
||||||
|
if(hdc == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//top edge
|
||||||
|
//border = rectc.top-rect.top;
|
||||||
|
SetRect(&rect2, 0,0,rect.right, border);
|
||||||
|
if(fShowHidden == TRUE) OffsetRect(&rect2, x1, y1);
|
||||||
|
InvertRect(hdc, &rect2);
|
||||||
|
|
||||||
|
//left edge
|
||||||
|
//border = rectc.left-rect.left;
|
||||||
|
SetRect(&rect2, 0,border,border, rect.bottom);
|
||||||
|
if(fShowHidden == TRUE) OffsetRect(&rect2, x1, y1);
|
||||||
|
InvertRect(hdc, &rect2);
|
||||||
|
|
||||||
|
//right edge
|
||||||
|
//border = rect.right-rectc.right;
|
||||||
|
SetRect(&rect2, border,rect.bottom-border,rect.right, rect.bottom);
|
||||||
|
if(fShowHidden == TRUE) OffsetRect(&rect2, x1, y1);
|
||||||
|
InvertRect(hdc, &rect2);
|
||||||
|
|
||||||
|
//bottom edge
|
||||||
|
//border = rect.bottom-rectc.bottom;
|
||||||
|
SetRect(&rect2, rect.right-border, border,rect.right, rect.bottom-border);
|
||||||
|
if(fShowHidden == TRUE) OffsetRect(&rect2, x1, y1);
|
||||||
|
InvertRect(hdc, &rect2);
|
||||||
|
|
||||||
|
|
||||||
|
ReleaseDC(hwnd, hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlashWindowBorder(HWND hwnd, BOOL fShowHidden)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < 3 * 2; i++)
|
||||||
|
{
|
||||||
|
InvertWindow(hwnd, fShowHidden);
|
||||||
|
Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadFinderResources()
|
||||||
|
{
|
||||||
|
hBitmapDrag1 = LoadBitmap(GetModuleHandle(0), L"FINDER_FULL");
|
||||||
|
hBitmapDrag2 = LoadBitmap(GetModuleHandle(0), L"FINDER_EMPTY");
|
||||||
|
|
||||||
|
hCursor = LoadCursor(GetModuleHandle(0), L"FINDER_CURSOR");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeFinderResources()
|
||||||
|
{
|
||||||
|
DeleteObject(hBitmapDrag1);
|
||||||
|
DeleteObject(hBitmapDrag2);
|
||||||
|
|
||||||
|
DestroyCursor(hCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
WNDFINDPROC GetWndFindProc(HWND hwnd)
|
||||||
|
{
|
||||||
|
return (WNDFINDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT FireWndFindNotify(HWND hwndTool, UINT uCode, HWND hwnd)
|
||||||
|
{
|
||||||
|
WNDFINDPROC wfp = GetWndFindProc(hwndTool);
|
||||||
|
|
||||||
|
if(wfp != 0)
|
||||||
|
return wfp(hwndTool, uCode, hwnd);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT EndFindToolDrag(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HWND hwndParent;
|
||||||
|
|
||||||
|
hwndParent = GetParent(hwnd);
|
||||||
|
|
||||||
|
InvertWindow(hwndCurrent, fShowHidden);
|
||||||
|
ReleaseCapture();
|
||||||
|
SetCursor(hOldCursor);
|
||||||
|
|
||||||
|
// Remove keyboard hook. This is done even if the user presses ESC
|
||||||
|
UnhookWindowsHookEx(draghook);
|
||||||
|
|
||||||
|
|
||||||
|
fDragging = FALSE;
|
||||||
|
SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmapDrag1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard hook for the Finder Tool.
|
||||||
|
// This hook just monitors the ESCAPE key
|
||||||
|
static LRESULT CALLBACK draghookproc(int code, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
ULONG state = (ULONG)lParam;
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
if(code < 0)
|
||||||
|
return CallNextHookEx(draghook, code, wParam, lParam);
|
||||||
|
|
||||||
|
switch(wParam)
|
||||||
|
{
|
||||||
|
case VK_ESCAPE:
|
||||||
|
|
||||||
|
if(!(state & 0x80000000))
|
||||||
|
{
|
||||||
|
//don't let the current window procedure process a VK_ESCAPE,
|
||||||
|
//because we want it to cancel the mouse capture
|
||||||
|
PostMessage(draghookhwnd, WM_CANCELMODE, 0, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(draghook, code, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LRESULT CALLBACK StaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HWND hwndParent;
|
||||||
|
|
||||||
|
switch(msg)
|
||||||
|
{
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
|
||||||
|
// Ask the callback function if we want to proceed
|
||||||
|
if(FireWndFindNotify(hwnd, WFN_BEGIN, 0) == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fDragging = TRUE;
|
||||||
|
|
||||||
|
SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmapDrag2);
|
||||||
|
|
||||||
|
hwndParent = GetParent(hwnd);
|
||||||
|
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
hwndCurrent = hwnd;
|
||||||
|
InvertWindow(hwndCurrent, fShowHidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SetCapture(hwnd);
|
||||||
|
hOldCursor = SetCursor(hCursor);
|
||||||
|
|
||||||
|
// Install keyboard hook to trap ESCAPE key
|
||||||
|
// We could just set the focus to this window to receive
|
||||||
|
// normal keyboard messages - however, we don't want to
|
||||||
|
// steal focus from current window when we use the drag tool,
|
||||||
|
// so a hook is a stealthier way to monitor key presses
|
||||||
|
draghookhwnd = hwnd;
|
||||||
|
draghook = SetWindowsHookEx(WH_KEYBOARD, draghookproc, GetModuleHandle(0), 0);
|
||||||
|
|
||||||
|
// Current window has changed
|
||||||
|
FireWndFindNotify(hwnd, WFN_SELCHANGED, hwndCurrent);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
if(fDragging == TRUE)
|
||||||
|
{
|
||||||
|
//MoveFindTool(hwnd, wParam, lParam);
|
||||||
|
|
||||||
|
POINT pt;
|
||||||
|
HWND hWndPoint;
|
||||||
|
|
||||||
|
pt.x = (short)LOWORD(lParam);
|
||||||
|
pt.y = (short)HIWORD(lParam);
|
||||||
|
|
||||||
|
ClientToScreen(hwnd, (POINT *)&pt);
|
||||||
|
|
||||||
|
hWndPoint = WindowFromPointEx(pt, fShowHidden);
|
||||||
|
|
||||||
|
if(hWndPoint == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(hWndPoint != hwndCurrent)
|
||||||
|
{
|
||||||
|
InvertWindow(hwndCurrent, fShowHidden);
|
||||||
|
|
||||||
|
FireWndFindNotify(hwnd, WFN_SELCHANGED, hWndPoint);
|
||||||
|
InvertWindow(hWndPoint, fShowHidden);
|
||||||
|
|
||||||
|
hwndCurrent = hWndPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
|
||||||
|
// Mouse has been release, so end the find-tool
|
||||||
|
if(fDragging == TRUE)
|
||||||
|
{
|
||||||
|
fDragging = FALSE;
|
||||||
|
|
||||||
|
EndFindToolDrag(hwnd, wParam, lParam);
|
||||||
|
FireWndFindNotify(hwnd, WFN_END, hwndCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Sent from the keyboard hook
|
||||||
|
case WM_CANCELMODE:
|
||||||
|
|
||||||
|
// User has pressed ESCAPE, so cancel the find-tool
|
||||||
|
if(fDragging == TRUE)
|
||||||
|
{
|
||||||
|
fDragging = FALSE;
|
||||||
|
|
||||||
|
EndFindToolDrag(hwnd, wParam, lParam);
|
||||||
|
FireWndFindNotify(hwnd, WFN_CANCELLED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_NCDESTROY:
|
||||||
|
|
||||||
|
// When the last finder tool has been destroyed, free
|
||||||
|
// up all the resources
|
||||||
|
if(InterlockedDecrement(&lRefCount) == 0)
|
||||||
|
{
|
||||||
|
FreeFinderResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallWindowProc(oldstaticproc, hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL MakeFinderTool(HWND hwnd, WNDFINDPROC wfp)
|
||||||
|
{
|
||||||
|
DWORD dwStyle;
|
||||||
|
|
||||||
|
// If this is the first finder tool, then load
|
||||||
|
// the bitmap and mouse-cursor resources
|
||||||
|
if(InterlockedIncrement(&lRefCount) == 1)
|
||||||
|
{
|
||||||
|
LoadFinderResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply styles to make this a picture control
|
||||||
|
dwStyle = GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
|
||||||
|
// Turn OFF styles we don't want
|
||||||
|
dwStyle &= ~(SS_RIGHT | SS_CENTER | SS_CENTERIMAGE);
|
||||||
|
dwStyle &= ~(SS_ICON | SS_SIMPLE | SS_LEFTNOWORDWRAP);
|
||||||
|
|
||||||
|
// Turn ON styles we must have
|
||||||
|
dwStyle |= SS_NOTIFY;
|
||||||
|
dwStyle |= SS_BITMAP;
|
||||||
|
|
||||||
|
// Now apply them..
|
||||||
|
SetWindowLong(hwnd, GWL_STYLE, dwStyle);
|
||||||
|
|
||||||
|
// Set the default bitmap
|
||||||
|
SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmapDrag1);
|
||||||
|
|
||||||
|
// Set the callback for this control
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wfp);
|
||||||
|
|
||||||
|
// Subclass the static control
|
||||||
|
oldstaticproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)StaticProc);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef FINDTOOL_INCLUDED
|
||||||
|
#define FINDTOOL_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef UINT (CALLBACK * WNDFINDPROC) (HWND hwndTool, UINT uCode, HWND hwnd);
|
||||||
|
|
||||||
|
//
|
||||||
|
// uCode can be one of these values:
|
||||||
|
//
|
||||||
|
#define WFN_BEGIN 0 // tool is about to become active. hwnd(0)
|
||||||
|
#define WFN_SELCHANGED 1 // sent when tool moves from window-window.
|
||||||
|
#define WFN_END 2 // sent when final window has been selected.
|
||||||
|
#define WFN_CANCELLED 3 // Tool canceled. hwnd is not valid (0)
|
||||||
|
|
||||||
|
#define WFN_CTRL_DOWN 4 // <Control> key was pressed
|
||||||
|
#define WFN_CTRL_UP 5 // <Control> key was released
|
||||||
|
#define WFN_SHIFT_DOWN 6 // <Shift> key was pressed
|
||||||
|
#define WFN_SHIFT_UP 7 // <Shift> key was released
|
||||||
|
|
||||||
|
#define WFN_CAPTURE 8 // Capture key pressed
|
||||||
|
|
||||||
|
BOOL MakeFinderTool (HWND hwnd, WNDFINDPROC wfp);
|
||||||
|
void InvertWindow (HWND hwnd, BOOL fShowHidden);
|
||||||
|
void FlashWindowBorder (HWND hwnd, BOOL fShowHidden);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,157 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue