GetPixel always returns CLR_INVALID - winapi

I'm trying to read the pixel color of a given window. The window is not mine. The window may not have focus or be at foreground. I don't know if it matters, does it? I have the window handle, so I do:
HDC hdc = GetDC(m_window);
if (hdc)
{
COLORREF color = GetPixel(hdc,x,y);
if(color == CLR_INVALID)
{
wxLogDebug("COLOR DATA INVALID");
}
else
{
wxLogDebug("COLOR DATA 0x%x", color);
}
x and y are screen coordinates that lie inside the window. Don't know why this is not working. Any ideas?

You should convert x, y into client coordinates with ScreenToClient Function.

Related

WinApi, disabling all controls in a rect area

Is there an api to disable all controls in a rect area?
I am trying to write something like that:
GetClientRect(hWnd, rect);
DisableControls(rect);
GetClientRect gets the client area (left and top are always 0), you need to use GetWindowRect to figure out where a child window is.
All child controls are in the client area and you can just disable the parent window and all children will also stop accepting input.
It does seem a little contrived to disable based on a rectangle instead of a list of known controls but I suppose it might be useful in some cases.
static BOOL CALLBACK DisableChildrenInRectProc(HWND hWnd, LPARAM Param)
{
RECT *pParentRect = (RECT*) Param, r, ir;
if (GetWindowRect(hWnd, &r) && IntersectRect(&ir, &r, pParentRect))
{
EnableWindow(hWnd, FALSE);
}
return TRUE;
}
HWND hWnd = ...
RECT r;
GetWindowRect(hWnd, &r);
r.bottom = r.top + (r.bottom - r.top) / 2; // In this example, only disable controls in the top half.
EnumChildWindows(hWnd, DisableChildrenInRectProc, (LPARAM) &r);
I don't believe there is one. Use EnumChildWindows, GetWindowRect and some coordinate mapping via ScreenToClient. For overlap testing you could use IntersectRect.

Map mouse position from hwnd to HWND_DESKTOP

Hello how i can map mouse position from local area window to screen window?
in code :
//Get x & y mouse coord...
Point.x = GET_X_LPARAM(lParam);
Point.y = GET_Y_LPARAM(lParam);
//Translate to Screen
MapWindowPoints(hWnd, HWND_DESKTOP, &Point, 1);
//not work!
SetCursorPos(Point.x, Point.y);
ok try next..
POINT Point;
Point.x = GET_X_LPARAM(lParam);
Point.y = GET_Y_LPARAM(lParam);
ClientToScreen(hWnd, &Point);
SetCursorPos(Point.x, Point.y); // not work!
Just saying something "not work!" is not helpful. Are the x and y coordinates what you expect?
Converting LPARAM client coordinates to screen coordinates and calling SetCursorPos is not going to move the mouse because the mouse pointer is already there!
If your application is not DPI-aware and you are running on a high DPI system then the coordinates of your application might not be the real coordinates but in your case I'm guessing that you are just not setting x and y to the "correct" values.

Are the coordinates in WINDOWPOS on WM_WINDOWPOSCHANGED in parent coordinates or screen coordinates?

Quick and simple one this time. I have a subclassed tab control that handles WM_WINDOWPOSCHANGED to, when not SWP_NOSIZE, resize its content. It passes the WINDOWPOS lParam's cx and cy fields to TCM_ADJUSTRECT to get the content rect size.
I need to do this on command as well (after changing tabs, say). However, I can't just do a dummy resize to the same size; even with an explicit SetWindowPos(), real Windows seems to add SWP_NOSIZE itself if the size doesn't change. So I want to write the analogous code to my WM_WINDOWPOSCHANGED handler.
My question is: what coordinate system are the coordinates given to WM_WINDOWPOSCHANGED given in, parent coordinates or screen coordinates? GetWindowRect() returns screen coordinates, so I'd like to know if I need to convert the coordinates to get the same values that I would get in WM_WINDOWPOSCHANGED. The documentation for WM_WINDOWPOSCHANGED doesn't say; neither does the documentation for WINDOWPOS.
Thanks.
WINDOWPOS, GetWindowRect, GetCursorPos, etc. give screen coordinates. When you use SetWindowPos you have to supply coordinates in relation to parent. This is straight forward for main window and popup windows which use screen coordinates. For moving child windows, you can use ScreenToClient and ClientToScreen for conversion.
For example, this will find the coordinates of OK button in relation to top-left corner of dialog box:
RECT rcOK;
HWND hitem = ::GetDlgItem(m_hWnd, IDOK);
GetWndRect(rcOK, hitem, m_hWnd);
void GetWndRect(RECT &rect, HWND item, HWND parent)
{
::GetWindowRect(item, &rect);//screen coordinates of OK button
POINT offset{ 0 };
ClientToScreen(parent, &offset); //Top-left (0,0) of client area of dialog -> screen coordinates
rect.left -= offset.x;
rect.right -= offset.x;
rect.top -= offset.y;
rect.bottom -= offset.y;
//client coordinates of OK button in relation to Dialog's Top-Right
}
Now we can move up the OK button by 10px:
rc.top -= 10;
rc.bottom -= 10;
::SetWindowPos(hitem, 0, rc.left, rc.top, 0, 0, SWP_NOSIZE);

WM_NCHITTEST not changing mouse cursor

I have a Layered Window (WS_EX_LAYERED) that implements a custom NCHITTEST and NCCALCSIZE to make the client rect of my window the same as the window rect. My window sizes and paints correctly; I can return HTBOTTOM from WM_NCHITTEST when the cursor is near the bottom edge of my window to cause a vertical-resize-window-from-the-bottom type action. However, I am not getting the vertical resize cursor. Is there way a do fix this without having to implement WM_SETCURSOR and test the pointer's position vs the edges of the windows?
Here's a snippet of my code:
case WM_NCCALCSIZE:
// Bypass DefWindowProc, so the Window Rect == Client Rect
return 0;
case WM_NCHITTEST: {
RECT w;
::GetWindowRect(hwnd, &w);
// Compare the mouse X/Y vs the rect of the window to detect
// resizing from the bottom edges
int r = HTCLIENT;
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
if (w.bottom - y < 10) {
// If I was not using NCHITTEST, I should get a verticle resize pointer here
if (x - w.left < 10)
r = HTBOTTOMLEFT;
else if (w.right - x < 10)
r = HTBOTTOMRIGHT;
else
r = HTBOTTOM;
}
return r;
}
You need to handle the WM_SETCURSOR message - the low-order word of lParam specifies the hit-test code.
For instance,
case WM_SETCURSOR:
switch (LOWORD(lParam))
{
case HTBOTTOM:
SetCursor(LoadCursor(0, IDC_SIZENS));
return 0;
}
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);

Capture screen shot with mouse cursor

I have used the following code to get screen shot on Windows.
hdcMem = CreateCompatibleDC (hdc) ;
int cx = GetDeviceCaps (hdc, HORZRES);
int cy = GetDeviceCaps (hdc, VERTRES);
HBITMAP hBitmap(NULL);
hBitmap = CreateCompatibleBitmap (hdc, cx, cy) ;
SelectObject (hdcMem, hBitmap) ;
BitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY);
However, the mouse cursor doesn't show up.
How could I get the cursor? or Is there a library can do that?
Thanks in advance.
After your BitBlt and before you select the bitmap back out of hdcMem, you can do this:
CURSORINFO cursor = { sizeof(cursor) };
::GetCursorInfo(&cursor);
if (cursor.flags == CURSOR_SHOWING) {
RECT rcWnd;
::GetWindowRect(hwnd, &rcWnd);
ICONINFOEXW info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
const int x = cursor.ptScreenPos.x - rcWnd.left - rc.left - info.xHotspot;
const int y = cursor.ptScreenPos.y - rcWnd.top - rc.top - info.yHotspot;
BITMAP bmpCursor = {0};
::GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
::DrawIconEx(hdcMem, x, y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight,
0, NULL, DI_NORMAL);
}
The code above figures out if the cursor is showing, using the global cursor state since you're probably taking a screenshot of a window (or windows) in another process. It then gets the target window coordinates for adjusting from screen. It gets specific info about the cursor, including its hotspot. It computes the drawing position of the icon. Finally, it gets the actual size of the cursor icon so that it can draw it without any stretching.
The only limitations to this approach that I know of are:
You don't get cursor shadows if you have them enabled.
If it's an animated cursor, this just shows the first frame. As far as I know, there's no way to determine the current frame.

Resources