Get current coordinates of a window (C++) - c++

I'm trying to get the x and y coordinates of a specific window relative to the screen (e.g. If the window's position on the screen is (100, 300) then I should retrieve an x-coordinate of 100 and a y-coordinate of 300). How can I achieve this so that I can assign the coordinates to some variables?
int x = /*Get x-coordinate*/;
int y = /*Get y-coordinate*/;

On Vista and later with Aero glass enabled, you have to use DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) to account for glass padding.
Otherwise, you can use GetWindowRect() instead, which does not account for glass padding.

RECT rect;
GetWindowRect(window, &rect);
int x = rect.left;
int y = rect.top;

Related

How to shift the start coordinates of the client area on the window?

I have refereed below article to draw a custom frame area with DWM.
Custom Window Frame Using DWM
After removing the standard frame, non client area is not exist in the frame.
void CMainFrame::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
int nTHight = 30; /*The title bar height*/
RECT * rc;
RECT aRect;
RECT bRect;
RECT bcRect;
if(bCalcValidRects == TRUE)
{
CopyRect(&aRect,&lpncsp->rgrc[1]);
CopyRect(&bRect,&lpncsp->rgrc[0]);
bcRect.left = bRect.left;
bcRect.top = bRect.top - nTHight;
bcRect.right = bRect.right;
bcRect.bottom = bRect.bottom;
CopyRect(&lpncsp->rgrc[0],&bcRect);
CopyRect(&lpncsp->rgrc[1],&bRect);
CopyRect(&lpncsp->rgrc[2],&aRect);
}
else
{
rc = (RECT *)lpncsp;
rc->left = rc->left;
rc->top = rc->top - nTHight;
rc->right = rc->right;
rc->bottom = rc->bottom;
}
CFrameWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
}
Because the entire window is client region, I have to adjust the UI control placement for the frame, but I don't know how to handle this problem.
For example, below red rectangle (all UI component) should be shifted into the original coordinate of the client area before removing the non client part.
CWnd::GetWindowRect gives you the rectangle of the window on screen. The dimensions of the caption, border, and scroll bars, if present, are included.
CWnd::GetClientRect gives you the client rectangel of the window. The left and top members will be 0. The right and bottom members will contain the width and height of the window.
CWnd::ScreenToClientand CWnd::ClientToScreen calculate a point or rectangle from the client area to screen coordinates and back to screen.
AdjustWindowRect calculates the required window rectangle, based on the client rectangle of the window.
Here is afunction which calcualtes the margins of a window:
void CalculateWndMargin( const CWnd &wnd, int &leftM, int &rightM , int &topM, int &bottomM )
{
CRect wndRect;
wnd.GetWindowRect( wndRect );
CRect screenRect;
wnd.GetClientRect( screenRect );
wnd.ClientToScreen( screenRect );
leftM = screenRect.left - wndRect.left;
rightM = wndRect.right - screenRect.right;
topM = screenRect.top - wndRect.top;
bottomM = wndRect.bottom - screenRect.bottom;
}

Taking a screenshot from the selected area(QRubberBand) on Qt

I am trying to create a Qt application to take screenshot from the selected area on screen. For now I am using QRubberBand to select an area of the screen.
It works like this.
When the Capture Button clicked an overlay transparent widget will popup(fullscreen but without frames)
I am using QRubberBand to select an area on the transparent widget.
Now I have to take the screenshot of the part which I selected.
I am thinking I have to pass the dimensions I get from selecting the QRubberBand to this:
screen->grabWindow( WId window, int x = 0, int y = 0, int width = -1, int height = -1 );
So how do I get the info I need from the QRubberBand?
I am stuck here, so someone please help me!
In your OnMouseRelease event you can get the rect of the QRubberBand using geometry(). Next using the QRect::getRect you can extract the position of the rectangle's top-left corner to x and y, and its dimensions to width and height. :
const QRect & selectRect = mRubberBand->geometry();
int x, y, width, height;
selectRect.getRect(&x, &y, &width, &height);

How to use grabWindow to take a screenshot of only a certain region of a window?

I am currently using the following code to take a screenshot of a window (handle is type HWND):
QPixmap::grabWindow((WId) handle).save("haystack.png", "png");
However, I only need to take a screenshot of a certain region (rectange) of the window.
In my case, the rectangle has the following vertices:
Top-left corner: (536, 535)
Bottom-right corner: (778, 592)
Right from the documentation:
QPixmap QPixmap::grabWindow( WId window,
int x = 0,
int y = 0,
int width = -1,
int height = -1 );

C++ MFC button disappears at window resize

I have a Dialog in MFC C++ that has a CButton attached.
I want to modify OnSize() so that the button will anchor to bottom-left.
if (btn.m_hWnd) {
CRect winRect;
GetWindowRect(&winRect);
int width = winRect.right - winRect.left;
int height = winRect.bottom - winRect.top;
int x = width - wndWidth;
int y = height - wndHeight;
CRect rect;
btn.GetWindowRect(&rect);
rect.left += x;
rect.top += y;
btn.MoveWindow(&rect);
ScreenToClient(&rect);
btn.ShowWindow(SW_SHOW);
}
x and y are the difference of how much the window has changed and will be added to the button's start coordinates.
I am not sure about the last 2 commands (I might as well delete them) but then I run the program the button disappears.
I need to know a way to move the button by x and y.
The original code was using the wrong coordinate system for both the parent dialog, and the button.
A correct way to dock to the bottom left would be like this:
if (btn.m_hWnd) {
CRect winRect;
GetClientRect(&winRect);
CRect rect;
btn.GetWindowRect(&rect);
ScreenToClient(&rect);
int btnWidth = rect.Width();
int btnHeight = rect.Width();
rect.left = winRect.right-btnWidth;
rect.top = winRect.bottom-btnHeight;
rect.right = winRect.right;
rect.bottom = winRect.bottom;
btn.MoveWindow(&rect);
}
OR
if (btn.m_hWnd) {
CRect winRect;
GetClientRect(&winRect);
CRect rect;
btn.GetWindowRect(&rect);
ScreenToClient(&rect);
int btnWidth = rect.Width();
int btnHeight = rect.Width();
btn.SetWindowPos(NULL,winRect.right-btnWidth,winRect.bottom-btnHeight,0,0,SWP_NOSIZE|SWP_NOZORDER);
}
Basically, the answer should be to do ScreenToClient before MoveWindow!
Some more detail: You need to familiarize yourself with what function returns or uses client coordinates (and relative to what these client coordinates are) and which screen coordinates; this is one of the parts of MFC which can be really confusing. As to your question:
CWnd::GetWindowRect returns screen coordinates; CWnd::MoveWindow expects coordinates relative to the parent CWnd (or to the screen if it's a top level window). So before calling MoveWindow, you have to convert the rect returned by GetWindowRect to client coordinates of your parent window; suppose pParent is the CWnd * to the parent window of btn, then your moving code should look like this:
CRect rect;
btn.GetWindowRect(&rect);
pParent->ScreenToClient(&rect); // this line and it's position is important
rect.left += x;
rect.top += y;
btn.MoveWindow(&rect);
If you're in a method of the parent window (as I think you are, since you mention OnSize of the dialog), then just leave out the pParent->. The way you do ScreenToClient at the moment, it has no effect on MoveWindow, since it's executed after it!

How do I set X coordinate of button without changing: y, width, height

I know I can use MoveWindow to move it but I only want to move the button on the x axis. Thanks.
I figured it out. You can get the button's (screen) position using GetWindowRect, then you can use ScreenToClient to get it's location in the form. Example:
RECT buttonScreenRect;
GetWindowRect(hwnd, &buttonScreenRect);
POINT buttonClientPoint;
buttonClientPoint.x = buttonScreenRect.left;
buttonClientPoint.y = buttonScreenRect.top;
ScreenToClient(hwnd, &buttonClientPoint);
MoveWindow(hwnd, 50, buttonClientPoint.y, buttonScreenRect.right - buttonScreenRect.left, buttonScreenRect.bottom - buttonScreenRect.top);
Hope it helps!