Map mouse position from hwnd to HWND_DESKTOP - windows

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.

Related

recalibrate ball in pong so the edge hits first, not the centre in Processing

I've recently built a game of pong for a UNI assignment in Processing, but whenever the ball hits the top, bottom, side of the screen or the 'paddle' it only bounces back once half the ball is off the screen. I just want the edge of the ball to hit first rather than the centre, but am unsure where my code is going wrong. I hope this makes sense, I'm a definite beginner.
Here is my code for reference
//underwater pong
float x, y, speedX, speedY;
float diam = 10;
float rectSize = 200;
float diamHit;
PImage bg;
PImage img;
int z;
void setup() {
size(920, 500);
smooth();
fill(255);
stroke(255);
imageMode(CENTER);
bg = loadImage("underthesea.jpg");
img = loadImage("plastic.png");
reset();
}
void reset() {
x = width/2;
y = height/2;
//allows plastic to bounce
speedX = random(5, 5);
speedY = random(5, 5);
}
void draw() {
background(bg);
image(img, x/2, y);
rect(0, 0, 20, height);
rect(width/2, mouseY-rectSize/2, 50, rectSize);
//allows plastic to bounce
x += speedX;
y += speedY;
// if plastic hits movable bar, invert X direction
if ( x > width-30 && x < width -20 && y > mouseY-rectSize/2 && y < mouseY+rectSize/2 ) {
speedX = speedX * -1;
}
// if plastic hits wall, change direction of X
if (x < 25) {
speedX *= -1.1;
speedY *= 1.1;
x += speedX;
}
// if plastic hits up or down, change direction of Y
if ( y > height || y < 0 ) {
speedY *= -1;
}
}
void mousePressed() {
reset();
}
I wasn't able to run your code because I am missing the background and plastic images, but here's what's probably going wrong. I'm not 100% since I do not know the dimensions of your images either.
You are using imageMode(CENTER). See the documentation for details.
From the docs:
imageMode(CENTER) interprets the second and third parameters of image() as the image's center point. If two additional parameters are specified, they are used to set the image's width and height.
This treats the coordinates you input into the image function as the center of the image.
Your first issue is that you are placing your image at x/2 but doing all your collision checks with x in mind. x does not represent the middle of your image, because you're drawing it at x/2.
Then I'm not sure if you are doing your horizontal collision checks right, as you are checking against hardcoded values. I do know you are doing your vertical collision checks wrong. You are checking if the center of the image is at the top of the canvas, 0, or the bottom of the canvas, height. This means that your image will already have moved out of the screen halfway.
If you want to treat the image coordinates as the center of your image, you need to check the left edge of the image at x - imageWidth / 2, the right edge at X+ imageWidth / 2, the top edge at y - imageWidth / 2 (remember the y coordinates are 0 at the top of the canvas and increase towards the bottom) and the bottom at y - imageWidth / 2. Here's a great website which goes into more detail on 2d collision detection, i'd highly recommend you give it a read. It's an awesome website.

Handling Window Movement after setting GWL_STYLE to 0

i want to have a border and title less window so i do SetWindowLongPtrW( window_handle, GWL_STYLE, 0 );
After that i can't move my Window so in my WndProc i do
if( message == WM_NCHITTEST ) {
RECT rc;
GetClientRect( hwnd, &rc );
MapWindowPoints( hwnd, GetParent( hwnd ), (LPPOINT)&rc, 2 );
int mouseX = LOWORD( lParam ) - rc.left;
int mouseY = HIWORD( lParam ) - rc.top;
POINT p;
p.x = mouseX;
p.y = mouseY;
return PtInRect( &rc, p ) ? HTCAPTION : DefWindowProc( hwnd, message, wParam, lParam );
}
It works, the first time i move the window. After i once stop clicking with the mouse it won't move again :/
SetWindowLongPtrW( window_handle, GWL_STYLE, 0 ); will hide the window, assuming it doesn't cause more serious problems. Use GetWindowLongPtr and combine that with valid window styles, or hide the window using ShowWindow
The error you have described is unrelated. You are attempting to find the screen coordinates of the window using GetClientRect and MapWindowPoints. The result will not be exact because the window may have borders and title bar.
Use GetWindowRect instead. This will give you screen coordinates of the window.
You can compare that with the mouse position LOWORD(lParam) and HIWORD(lParam). This is already screen coordinates. This code will move the screen every where the mouse lands in window:
RECT rc;
GetWindowRect(hwnd, &rc);
int mouseX = LOWORD(lparam);
int mouseY = HIWORD(lparam);
Don't subtract rc.left and rc.top from mouse position. That would convert the coordinates in client coordinates (roughly). Your code may work when window is on top-left corner of the screen, but it won't work later when window is moved.
Use ScreenToClient if you wish to work in client window coordinates.

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);

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.

GetPixel always returns CLR_INVALID

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.

Resources