Sandboxie/SandboxiePlus/SandMan/Helpers/FindTool.cpp

402 lines
9.6 KiB
C++

#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;
}