Skip to content

Commit

Permalink
predefined rectangle capture sizes
Browse files Browse the repository at this point in the history
and enforce selection size to be multiple of 2
  • Loading branch information
mmozeiko committed Nov 24, 2023
1 parent 8c4655d commit f9c6dc2
Showing 1 changed file with 127 additions and 31 deletions.
158 changes: 127 additions & 31 deletions wcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static HICON gIcon1;
static HICON gIcon2;
static UINT WM_TASKBARCREATED;
static HCURSOR gCursorArrow;
static HCURSOR gCursorClick;
static HCURSOR gCursorResize[10];
static HFONT gFont;
static HFONT gFontBold;
Expand All @@ -107,6 +108,8 @@ static BOOL gRectSelected;
static POINT gRectSelection[2];
static POINT gRectMousePos;
static int gRectResize;
static int gRectSetSize[2];
static BOOL gRectSetSizeClick;

// globals
static HWND gWindow;
Expand Down Expand Up @@ -536,6 +539,8 @@ static void CaptureRectangleInit(void)
gRectHeight = Height;
gRectSelected = FALSE;
gRectResize = WCAP_RESIZE_NONE;
gRectSetSize[0] = gRectSetSize[1] = 0;
gRectSetSizeClick = FALSE;

SetCursor(gCursorResize[WCAP_RESIZE_NONE]);
SetWindowPos(gWindow, HWND_TOPMOST, Info.rcMonitor.left, Info.rcMonitor.top, Width, Height, SWP_SHOWWINDOW);
Expand Down Expand Up @@ -673,6 +678,17 @@ BOOL EnableHotKeys(void)
return Success;
}

static void AdjustRectSizeMultipleOf2(int Adjust, int Ref)
{
int W = gRectSelection[Ref].x - gRectSelection[Adjust].x;
W = (W + (W > 0)) & ~1;
gRectSelection[Adjust].x = gRectSelection[Ref].x - W;

int H = gRectSelection[Ref].y - gRectSelection[Adjust].y;
H = (H + (H > 0)) & ~1;
gRectSelection[Adjust].y = gRectSelection[Ref].y - H;
}

static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
if (Message == WM_CREATE)
Expand Down Expand Up @@ -733,45 +749,62 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
{
if (gRectContext)
{
int X = GET_X_LPARAM(LParam);
int Y = GET_Y_LPARAM(LParam);

int Resize = gRectSelected ? GetPointResize(X, Y) : WCAP_RESIZE_NONE;
if (Resize == WCAP_RESIZE_NONE)
if (gRectSetSize[0])
{
// inital rectangle will be empty
gRectSelection[0].x = gRectSelection[1].x = X;
gRectSelection[0].y = gRectSelection[1].y = Y;
gRectSelected = FALSE;

gRectSetSizeClick = TRUE;
gRectSelection[1].x = gRectSelection[0].x + gRectSetSize[0];
gRectSelection[1].y = gRectSelection[0].y + gRectSetSize[1];
InvalidateRect(Window, NULL, FALSE);
}
else
{
// resizing direction
gRectMousePos = (POINT){ X, Y };
}
int X = GET_X_LPARAM(LParam);
int Y = GET_Y_LPARAM(LParam);

gRectResize = Resize;
SetCapture(Window);
int Resize = gRectSelected ? GetPointResize(X, Y) : WCAP_RESIZE_NONE;
if (Resize == WCAP_RESIZE_NONE)
{
// inital rectangle will be empty
gRectSelection[0].x = gRectSelection[1].x = X;
gRectSelection[0].y = gRectSelection[1].y = Y;
gRectSelected = FALSE;

InvalidateRect(Window, NULL, FALSE);
}
else
{
// resizing direction
gRectMousePos = (POINT){ X, Y };
}

gRectResize = Resize;
SetCapture(Window);
}
return 0;
}
}
else if (Message == WM_LBUTTONUP)
{
if (gRectContext)
{
if (gRectSelected)
if (gRectSetSizeClick)
{
// fix the selected rectangle coordinates, so next resizing starts on the correct side
int X0 = min(gRectSelection[0].x, gRectSelection[1].x);
int Y0 = min(gRectSelection[0].y, gRectSelection[1].y);
int X1 = max(gRectSelection[0].x, gRectSelection[1].x);
int Y1 = max(gRectSelection[0].y, gRectSelection[1].y);
gRectSelection[0] = (POINT){ X0, Y0 };
gRectSelection[1] = (POINT){ X1, Y1 };
gRectSetSizeClick = FALSE;
}
else
{
if (gRectSelected)
{
// fix the selected rectangle coordinates, so next resizing starts on the correct side
int X0 = min(gRectSelection[0].x, gRectSelection[1].x);
int Y0 = min(gRectSelection[0].y, gRectSelection[1].y);
int X1 = max(gRectSelection[0].x, gRectSelection[1].x);
int Y1 = max(gRectSelection[0].y, gRectSelection[1].y);
gRectSelection[0] = (POINT){ X0, Y0 };
gRectSelection[1] = (POINT){ X1, Y1 };
}
ReleaseCapture();
}
ReleaseCapture();
return 0;
}
}
Expand All @@ -782,33 +815,46 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
int X = GET_X_LPARAM(LParam);
int Y = GET_Y_LPARAM(LParam);

if (WParam & MK_LBUTTON)
if (gRectSetSize[0])
{
SetCursor(gCursorClick);
InvalidateRect(Window, NULL, FALSE);
}
else if (gRectSetSizeClick)
{
InvalidateRect(Window, NULL, FALSE);
}
else if (WParam & MK_LBUTTON)
{
BOOL Update = FALSE;

if (gRectResize == WCAP_RESIZE_TL || gRectResize == WCAP_RESIZE_L || gRectResize == WCAP_RESIZE_BL)
{
// left moved
gRectSelection[0].x = X;
AdjustRectSizeMultipleOf2(0, 1);
Update = TRUE;
}
else if (gRectResize == WCAP_RESIZE_TR || gRectResize == WCAP_RESIZE_R || gRectResize == WCAP_RESIZE_BR)
{
// right moved
gRectSelection[1].x = X;
AdjustRectSizeMultipleOf2(1, 0);
Update = TRUE;
}

if (gRectResize == WCAP_RESIZE_TL || gRectResize == WCAP_RESIZE_T || gRectResize == WCAP_RESIZE_TR)
{
// top moved
gRectSelection[0].y = Y;
AdjustRectSizeMultipleOf2(0, 1);
Update = TRUE;
}
else if (gRectResize == WCAP_RESIZE_BL || gRectResize == WCAP_RESIZE_B || gRectResize == WCAP_RESIZE_BR)
{
// bottom moved
gRectSelection[1].y = Y;
AdjustRectSizeMultipleOf2(1, 0);
Update = TRUE;
}

Expand All @@ -831,6 +877,7 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
// no resize means we're selecting initial rectangle
gRectSelection[1].x = X;
gRectSelection[1].y = Y;
AdjustRectSizeMultipleOf2(1, 0);
if (gRectSelection[0].x != gRectSelection[1].x && gRectSelection[0].y != gRectSelection[1].y)
{
// when we have non-zero size rectangle, we're good with initial stage
Expand All @@ -848,6 +895,12 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
{
int Resize = gRectSelected ? GetPointResize(X, Y) : WCAP_RESIZE_NONE;
SetCursor(gCursorResize[Resize]);

if (Resize == WCAP_RESIZE_NONE)
{
// in case hovering over resize text
InvalidateRect(Window, NULL, FALSE);
}
}

return 0;
Expand Down Expand Up @@ -1044,13 +1097,15 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
{
if (gRectContext)
{
int X = Paint.rcPaint.left;
int Y = Paint.rcPaint.top;
int W = Paint.rcPaint.right - Paint.rcPaint.left;
int H = Paint.rcPaint.bottom - Paint.rcPaint.top;
{
int X = Paint.rcPaint.left;
int Y = Paint.rcPaint.top;
int W = Paint.rcPaint.right - Paint.rcPaint.left;
int H = Paint.rcPaint.bottom - Paint.rcPaint.top;

// draw darkened screenshot
BitBlt(Context, X, Y, W, H, gRectDarkContext, X, Y, SRCCOPY);
// draw darkened screenshot
BitBlt(Context, X, Y, W, H, gRectDarkContext, X, Y, SRCCOPY);
}

if (gRectSelected)
{
Expand All @@ -1072,6 +1127,46 @@ static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM WParam, LPA
SetTextColor(Context, RGB(255, 255, 255));
SetBkMode(Context, TRANSPARENT);
ExtTextOutW(Context, X1, Y1, 0, NULL, Text, TextLength, NULL);

SelectObject(Context, gFontBold);
SetTextAlign(Context, TA_BOTTOM | TA_LEFT);
SetTextColor(Context, RGB(255, 255, 255));

const WCHAR TextResize[] = L"Resize: ";

SIZE Size;
GetTextExtentPoint32W(Context, TextResize, _countof(TextResize) - 1, &Size);
ExtTextOutW(Context, X0, Y0, 0, NULL, TextResize, _countof(TextResize) - 1, NULL);

int X = X0;
SelectObject(Context, gFont);

POINT CursorPos;
GetCursorPos(&CursorPos);
ScreenToClient(Window, &CursorPos);

gRectSetSize[0] = gRectSetSize[1] = 0;

int Sizes[][2] = { { 800, 600 }, { 1280, 720 }, { 1920, 1080 }, { 2560, 1440 } };
for (int i=0; i<_countof(Sizes); i++)
{
X += Size.cx;

TextLength = StrFormat(Text, L"%dx%d ", Sizes[i][0], Sizes[i][1]);
GetTextExtentPoint32W(Context, Text, TextLength, &Size);

RECT Rect = { X, Y0 - Size.cy, X + Size.cx, Y0 };
BOOL Hovering = PtInRect(&Rect, CursorPos);
SetTextColor(Context, Hovering ? RGB(255, 255, 255) : RGB(192, 192, 192));
ExtTextOutW(Context, X, Y0, 0, NULL, Text, TextLength, NULL);

if (Hovering)
{
gRectSetSize[0] = Sizes[i][0];
gRectSetSize[1] = Sizes[i][1];
SetCursor(gCursorClick);
}
}
}
else
{
Expand Down Expand Up @@ -1273,6 +1368,7 @@ void WinMainCRTStartup()
QueryPerformanceFrequency(&gTickFreq);

gCursorArrow = LoadCursor(NULL, IDC_ARROW);
gCursorClick = LoadCursor(NULL, IDC_HAND);
gCursorResize[WCAP_RESIZE_NONE] = LoadCursor(NULL, IDC_CROSS);
gCursorResize[WCAP_RESIZE_M] = LoadCursor(NULL, IDC_SIZEALL);
gCursorResize[WCAP_RESIZE_T] = gCursorResize[WCAP_RESIZE_B] = LoadCursor(NULL, IDC_SIZENS);
Expand Down

0 comments on commit f9c6dc2

Please sign in to comment.