(See the follow-up question.)
I have this program that shows a small window and that window shows a rectangle whose color is the same as the color of the pixel under the mouse cursor. Note that it will show the color of the mouse cursor pixel even outside of its native window. As additional fun, I have coded the clipboard support: when the user presses Ctrl+C, the RGB value of the current color will be copied to the clipboard. All works fine, but when I try to resize the window, it lags.
What do you think?
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
const int WIDTH = 300;
const int HEIGHT = 200;
const int TEXT_LINE_HEIGHT = 30;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
VOID WINAPI CopyToClipboard(HWND hwnd);
HWND hwnd;
BOOL ctrlKeyDown = FALSE;
POINT prevPoint;
int WINAPI wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PWSTR pCmdLine,
int nCmdShow) {
prevPoint.x = -1;
prevPoint.y = -1;
const wchar_t CLASS_NAME[] = L"GrabPixlMainWndw";
WNDCLASSEX wc = {};
wc.cbSize = sizeof(wc);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassEx(&wc);
int screenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
int screenHeight = GetSystemMetrics(SM_CYFULLSCREEN);
hwnd = CreateWindowEx(
0,
CLASS_NAME,
L"GrabPixel 1.6",
WS_OVERLAPPEDWINDOW,
(screenWidth - WIDTH) / 2,
(screenHeight - HEIGHT) / 2,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL) {
return 0;
}
HHOOK mouseHook =
SetWindowsHookExA(
WH_MOUSE_LL,
LowLevelMouseProc,
hInstance,
0);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
if (wParam == VK_CONTROL) {
ctrlKeyDown = TRUE;
} else if (wParam == 0x43) {
if (ctrlKeyDown) {
CopyToClipboard(hwnd);
}
}
break;
case WM_KEYUP:
if (wParam == VK_CONTROL) {
ctrlKeyDown = FALSE;
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
RECT rect;
HFONT hFont;
wchar_t buffer[10];
HDC hdc = BeginPaint(hwnd, &ps);
COLORREF color = (COLORREF)wParam;
HBRUSH brush = CreateSolidBrush(color);
GetClientRect(hwnd, &rect);
rect.bottom -= TEXT_LINE_HEIGHT;
// Draw the color rectangle:
hdc = GetDC(hwnd);
FillRect(hdc, &rect, brush);
DeleteObject(brush);
// Draw the RGB rectangle:
brush = CreateSolidBrush(RGB(255, 255, 255));
rect.top = rect.bottom;
rect.bottom += TEXT_LINE_HEIGHT;
FillRect(hdc, &rect, brush);
DeleteObject(brush);
// Print the RGB value of the current pixel:
wsprintf(buffer,
L"#%02x%02x%02x",
GetRValue(color),
GetGValue(color),
GetBValue(color));
hFont = CreateFont(30,
16,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
FF_MODERN,
L"Monospaced");
SetTextColor(hdc, RGB(0, 0, 0));
SelectObject(hdc, hFont);
TextOut(hdc,
5,
rect.bottom - TEXT_LINE_HEIGHT,
buffer,
7);
ReleaseDC(hwnd, hdc);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (wParam == WM_MOUSEMOVE) {
POINT p;
if (GetCursorPos(&p)) {
if (p.x == prevPoint.x && p.y == prevPoint.y) {
// No new pixel:
return 0;
}
prevPoint.x = p.x;
prevPoint.y = p.y;
HDC hdc = GetDC(NULL);
if (hdc != NULL) {
COLORREF color = GetPixel(hdc, p.x, p.y);
PostMessage(hwnd, WM_PAINT, color, color);
}
}
}
return 0;
}
VOID WINAPI CopyToClipboard(HWND hwnd) {
HGLOBAL hglbCopy;
LPSTR lpstrCopy;
if (!OpenClipboard(GetDesktopWindow())) {
return;
}
EmptyClipboard();
POINT point;
if (GetCursorPos(&point)) {
int x = point.x;
int y = point.y;
COLORREF color = GetPixel(GetDC(NULL), x, y);
int r = GetRValue(color);
int g = GetGValue(color);
int b = GetBValue(color);
char buffer[10];
sprintf_s(buffer, "#%02x%02x%02x", r, g, b);
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 10);
if (!hGlobal) {
CloseClipboard();
return;
}
memcpy(GlobalLock(hGlobal), buffer, 10);
GlobalUnlock(hGlobal);
SetClipboardData(CF_TEXT, hGlobal);
CloseClipboard();
GlobalFree(hGlobal);
}
}
```