snow flurry
d64803c1a9
git-svn-id: svn://vcs.sdm.2ki.xyz/Grabby/trunk@11 27729192-006e-004d-b9b5-06fbd0ef7001
231 lines
4.8 KiB
C
231 lines
4.8 KiB
C
#include "stdafx.h"
|
|
#include "Bitmap.h"
|
|
|
|
LRESULT CALLBACK OverlayWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
#define OVERLAY_CLASS _T("GrabbyOverlay")
|
|
#define OVERLAY_TITLE _T("Grabby Overlay")
|
|
|
|
// Static function to store and retrieve the overlay-chosen rect.
|
|
static void
|
|
SetGetRect(BOOL set, RECT *r)
|
|
{
|
|
static RECT rcMain = {0};
|
|
if (r) {
|
|
if (set) {
|
|
CopyMemory(&rcMain, r, sizeof(RECT));
|
|
} else {
|
|
CopyMemory(r, &rcMain, sizeof(RECT));
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
GetChosenRect(RECT *rcOut)
|
|
{
|
|
SetGetRect(FALSE, rcOut);
|
|
return;
|
|
}
|
|
|
|
int
|
|
CreateOverlay(HINSTANCE hInstance,
|
|
Screen *scrn)
|
|
{
|
|
HWND hWnd = NULL;
|
|
RECT rcScreen = {0};
|
|
MSG msg = {0};
|
|
BOOL bRet;
|
|
WNDCLASSEX wcClass = {
|
|
sizeof(WNDCLASSEX),
|
|
CS_HREDRAW | CS_VREDRAW,
|
|
OverlayWndProc,
|
|
0,
|
|
0,
|
|
hInstance,
|
|
LoadIcon(NULL, IDI_APPLICATION),
|
|
LoadCursor(NULL, IDC_CROSS),
|
|
(HBRUSH)( COLOR_WINDOW + 1 ),
|
|
OVERLAY_TITLE,
|
|
OVERLAY_CLASS,
|
|
NULL
|
|
};
|
|
|
|
if (!RegisterClassEx(&wcClass)) {
|
|
return -1;
|
|
}
|
|
|
|
if (!GetRgnBox(scrn->hScreenRgn, &rcScreen)) {
|
|
UnregisterClass(OVERLAY_CLASS, hInstance);
|
|
return -1;
|
|
}
|
|
|
|
hWnd = CreateWindowEx(
|
|
WS_EX_TOPMOST,
|
|
OVERLAY_CLASS,
|
|
OVERLAY_TITLE,
|
|
WS_VISIBLE | WS_POPUP,
|
|
rcScreen.left,
|
|
rcScreen.top,
|
|
rcScreen.right - rcScreen.left,
|
|
rcScreen.bottom - rcScreen.top,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
scrn);
|
|
|
|
if (!hWnd) {
|
|
UnregisterClass(OVERLAY_CLASS, hInstance);
|
|
return -1;
|
|
}
|
|
|
|
ShowWindow(hWnd, SW_SHOWNORMAL);
|
|
|
|
while ((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0) {
|
|
if (bRet == -1) {
|
|
// TODO: error handling
|
|
break;
|
|
} else {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
if (hWnd) DestroyWindow(hWnd);
|
|
UnregisterClass(OVERLAY_CLASS, hInstance);
|
|
|
|
return (int)msg.wParam;
|
|
}
|
|
|
|
// Left, Top, Right, Bottom
|
|
#define POINT2RECT(a,b) { \
|
|
min(a.x, b.x), \
|
|
min(a.y, b.y), \
|
|
max(a.x, b.x), \
|
|
max(a.y, b.y) \
|
|
}
|
|
|
|
LRESULT CALLBACK
|
|
OverlayWndProc(HWND hWnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HDC hDC = NULL;
|
|
PAINTSTRUCT ps = {0};
|
|
static POINTS ptStart = {0}, // Starting drag point
|
|
ptCur = {0}; // Current/end drag point
|
|
static BOOL isDrag = FALSE; // Are we mid-drag?
|
|
static Screen *scrn = NULL; // Screen data
|
|
static RECT rcScreen = {0};
|
|
static HGDIOBJ hOldObj = NULL;
|
|
|
|
switch (uMsg) {
|
|
case WM_CREATE:
|
|
{
|
|
HDC dcWnd = GetDC(hWnd);
|
|
// Get the Screen object passed in from CreateWindowEx
|
|
HBITMAP hOldBmp = NULL;
|
|
LPCREATESTRUCT csCreate = (LPCREATESTRUCT)lParam;
|
|
if (csCreate && csCreate->lpCreateParams) {
|
|
scrn = (Screen *)csCreate->lpCreateParams;
|
|
if (!scrn) {
|
|
// uhhhhhhhhh
|
|
MessageBox(hWnd,
|
|
_T("Couldn't get screen info for mysterious reasons !?"),
|
|
_T("Fatal Error"),
|
|
MB_OK | MB_ICONERROR);
|
|
PostQuitMessage(1);
|
|
return 1;
|
|
}
|
|
|
|
GetRgnBox(scrn->hScreenRgn, &rcScreen);
|
|
|
|
if (!SnapScreen(scrn)) {
|
|
MessageBox(hWnd,
|
|
_T("Couldn't store screen data !!"),
|
|
_T("Fatal Error"),
|
|
MB_OK | MB_ICONERROR);
|
|
PostQuitMessage(1);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
/* PASSTHRU */
|
|
case WM_PAINT:
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
|
|
if (scrn->hBitmap) {
|
|
// Draw the "background"
|
|
if (!BitBlt(hDC,
|
|
ps.rcPaint.left,
|
|
ps.rcPaint.top,
|
|
ps.rcPaint.right - ps.rcPaint.left,
|
|
ps.rcPaint.bottom - ps.rcPaint.top,
|
|
scrn->hdcBitmap,
|
|
rcScreen.left + ps.rcPaint.left,
|
|
rcScreen.top + ps.rcPaint.top,
|
|
SRCCOPY))
|
|
{
|
|
// walk it off, I guess...
|
|
OutputDebugString(_T("Failed to blit background to DC..."));
|
|
}
|
|
}
|
|
|
|
if (isDrag && hDC) {
|
|
RECT rcOuter = POINT2RECT(ptStart, ptCur);
|
|
DrawFocusRect(hDC, &rcOuter);
|
|
}
|
|
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
case WM_MOUSEMOVE:
|
|
if (isDrag && (wParam & MK_LBUTTON)) {
|
|
POINTS ptPrev = ptCur;
|
|
ptCur = MAKEPOINTS(lParam);
|
|
if ((ptCur.x != ptStart.x) &&
|
|
(ptCur.y != ptStart.y))
|
|
{
|
|
RECT rcPrevDmg = POINT2RECT(ptStart, ptPrev);
|
|
// Expand out a little bit to contain the focus rect
|
|
rcPrevDmg.left--;
|
|
rcPrevDmg.right++;
|
|
rcPrevDmg.top--;
|
|
rcPrevDmg.bottom++;
|
|
InvalidateRect(hWnd, &rcPrevDmg, TRUE);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case WM_LBUTTONDOWN:
|
|
if (!isDrag) {
|
|
// Start the drag operation and set the origin
|
|
ptStart = ptCur = MAKEPOINTS(lParam);
|
|
isDrag = TRUE;
|
|
}
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
if (isDrag) {
|
|
// Done dragging, store the rect and get out of here
|
|
RECT rcFinal = POINT2RECT(ptStart, ptCur);
|
|
|
|
SetGetRect(TRUE, &rcFinal);
|
|
isDrag = FALSE;
|
|
PostQuitMessage(0);
|
|
}
|
|
break;
|
|
case WM_KEYUP:
|
|
if (wParam != VK_ESCAPE) {
|
|
break;
|
|
}
|
|
/* PASSTHRU */
|
|
case WM_RBUTTONUP:
|
|
// We treat right click as Escape
|
|
PostQuitMessage(1);
|
|
break;
|
|
default:
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
} |