From: Paul N on
I'm trying to write a program to give the colour values of a point on
the screen. (I think this sort of tool is called an eye-dropper.) My
program is based in the Blowup program in Petzold, and I've included
the interesting bits below.

What is supposed to happen is that, to start it going, you click
within the client area. This captures the mouse. Then, if you click
outside the client area, the window shows the values for the point
that you clicked on. Clicking within the client area un-captures the
mouse and so puts things back to normal.

Most of it works. Clicking within the client area does appear to
capture the mouse; clicking in the client area again un-captures it
again. And, when it is captured, the first time you click outside the
client area, it does seem to give the values for this point. But
clicking a second time outside the client area doesn't seem to work.
It's as if the first click loses the capture. Am I doing something
wrong?

Also, Petzold sems to suggest that the mouse cursor can be set for
when it is captured. But in my program, although I get the cross-hairs
cursor within the client area, it turns to a different cursor
(depending on what it is passing over) as soon as it leaves my
program's window - even before the first click, while it is presumably
properly captured. Am I doing something wrong, or mis-understanding
something?

Thanks for any help.
Paul.

void write(HDC hdc, int x, int y, LPCTSTR str) {
TextOut(hdc, x, y, str, lstrlen(str));
}

void repaint(HWND hWnd) {
InvalidateRect(hWnd, NULL, TRUE);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static int capture, result;
static TCHAR buff[30];
static POINTS pts;
static POINT p;
static RECT rect;
static COLORREF col;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;

case WM_CREATE:
capture = FALSE;
result = FALSE;
break;

case WM_LBUTTONDOWN:
if (!capture) {
capture = TRUE;
SetCapture(hWnd);
SetCursor(LoadCursor(NULL, IDC_CROSS));
repaint(hWnd); }
else {
pts = MAKEPOINTS(lParam);
POINTSTOPOINT(p, pts);
GetClientRect(hWnd, &rect);
if (PtInRect(&rect, p)) {
capture = FALSE;
result = FALSE;
ReleaseCapture();
repaint(hWnd); }
else {
result = TRUE;
hdc = CreateDC(_TEXT("DISPLAY"), NULL, NULL, NULL);
ClientToScreen(hWnd, &p);
col = GetPixel(hdc, p.x, p.y);
_stprintf(buff, _TEXT("Result: R %d, G%d, B %d"), GetRValue(col),
GetGValue(col), GetBValue(col));
DeleteDC(hdc);
repaint(hWnd); } }
break;

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
if (!capture)
write(hdc, 0, 0, _TEXT("Click in window to begin capture"));
else {
write(hdc, 0, 0, _TEXT("Captured - click outside window to test
point"));
write(hdc, 0, 20, _TEXT("Click inside window to end capture")); }
if (result)
write(hdc, 0, 60, buff);

EndPaint(hWnd, &ps);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
From: Seetharam on
Try handling WM_CAPTURECHANGED and see the value of lParam( the
window that is taking teh capture away ). That way you would know what
is actually happening once you click outside your client area.

-Seetharam
From: Paul N on
On 26 Jan, 23:13, Seetharam <smi...(a)gmail.com> wrote:
> Try handling WM_CAPTURECHANGED and see the value of  lParam( the
> window that is taking teh capture away ). That way you would know what
> is actually happening once you click outside your client area.

I haven't tried exactly doing that, as I don't know the handles of any
of the other windows anyway. But I've tried a few things and it seems
that, with my original code, the capture is lost just after the
mouseclick message - before the repaint message.

I've tried adding the following:

case WM_CAPTURECHANGED:
if (capture) {
SetForegroundWindow(hWnd);
SetCapture(hWnd); }
break;

and it works a bit better, but it's still not reliable, and I don't
see why I need to do it anyway.