Discussion:
Why GetWindowRect gives wrong values by 8 pixels?
(too old to reply)
JiiPee
2016-04-09 11:08:55 UTC
Permalink
Why does GetWindowRect give like 8 pixels too wide area when I call it
for a window? I get the windows handle by
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

and then do:
CRect rect;
::GetWindowRect(hWnd, rect);

But for example if I maximize my notepad and take its rect with this, it
gives:
-8, -8 as a top left. Should be 0,0. Also I can see that if I place the
Notepad somewhere else on desktop the same happens.
R.Wieser
2016-04-09 11:48:34 UTC
Permalink
JiiPee,
Post by JiiPee
But for example if I maximize my notepad and take its rect
with this, it gives: -8, -8 as a top left.
Thats correct. The *client-area* gets enlarged to fit the full screen,
which means that the window the client-area is in must be bigger that that
(to accomodate the windows borders).
Post by JiiPee
Also I can see that if I place the Notepad somewhere else
on desktop the same happens.
I don't think the result will be -8, -8 every time. So, how have you come
to that conclusion (what method did you use) ?

Regards,
Rudy Wieser
Post by JiiPee
Why does GetWindowRect give like 8 pixels too wide area when I call it
for a window? I get the windows handle by
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
CRect rect;
::GetWindowRect(hWnd, rect);
But for example if I maximize my notepad and take its rect with this, it
-8, -8 as a top left. Should be 0,0. Also I can see that if I place the
Notepad somewhere else on desktop the same happens.
JiiPee
2016-04-09 15:47:46 UTC
Permalink
Post by R.Wieser
JiiPee,
Post by JiiPee
But for example if I maximize my notepad and take its rect
with this, it gives: -8, -8 as a top left.
Thats correct. The *client-area* gets enlarged to fit the full screen,
which means that the window the client-area is in must be bigger that that
(to accomodate the windows borders).
Post by JiiPee
Also I can see that if I place the Notepad somewhere else
on desktop the same happens.
I don't think the result will be -8, -8 every time. So, how have you come
to that conclusion (what method did you use) ?
I mean it gives: windox.X - 8 (not sure if its always 8 though) as x
coordinate. I can see it becouse I take a screenshot and it always takes
more than the notepad (it takes some pixels from the background as well,
from the wall paper).

So I get a full screenshot of the notepad plus some extra from the wall
paper. How can I fix this so that I would get only the notepad? But in
this screenshot it does not seem to take extra pixels at the top side of
the notepad (or only little). So its not equal on every side, but on
left/right side its always something like 8.
R.Wieser
2016-04-09 16:07:23 UTC
Permalink
JiiPee,
I can see it becouse I take a screenshot ...
And there you have TWO problems: It might just be as you describe, but it
could as easily be that that screenshot software does something you do not
expect from it ...
But in this screenshot
And thats problem #3: I have absolutily *no idea* what that "this
screenshot" is you are referring to, nor how you made it (which program ---
something you wrote yourself ?)

Hint: You could do worse than to try to describe the problem AND what you
use to evoke it to us as if we have absolutily no knowledge of what you are
busy with -- something thats actually even true (at least for me, as I'm not
a mindreader) :-)

Regards,
Rudy Wieser
Post by R.Wieser
JiiPee,
Post by JiiPee
But for example if I maximize my notepad and take its rect
with this, it gives: -8, -8 as a top left.
Thats correct. The *client-area* gets enlarged to fit the full screen,
which means that the window the client-area is in must be bigger that that
(to accomodate the windows borders).
Post by JiiPee
Also I can see that if I place the Notepad somewhere else
on desktop the same happens.
I don't think the result will be -8, -8 every time. So, how have you come
to that conclusion (what method did you use) ?
I mean it gives: windox.X - 8 (not sure if its always 8 though) as x
coordinate. I can see it becouse I take a screenshot and it always takes
more than the notepad (it takes some pixels from the background as well,
from the wall paper).
So I get a full screenshot of the notepad plus some extra from the wall
paper. How can I fix this so that I would get only the notepad? But in
this screenshot it does not seem to take extra pixels at the top side of
the notepad (or only little). So its not equal on every side, but on
left/right side its always something like 8.
JiiPee
2016-04-09 17:05:03 UTC
Permalink
Post by R.Wieser
JiiPee,
I can see it becouse I take a screenshot ...
And there you have TWO problems: It might just be as you describe, but it
could as easily be that that screenshot software does something you do not
expect from it ...
no, its my own code, only like 15 lines of code to use that rectangle
and then copy that part from the screen. I checked and they all use that
rect as it is.... so they do not increase the rect. So am sure there is
nothing wrong with that code.

Also, when I maximize notepad, i can see that its frame hits the desktop
left corner (but does not go over it). And we get that -8, so obviously
there is something happening there with GetWindowRectangle.
Post by R.Wieser
But in this screenshot
And thats problem #3: I have absolutily *no idea* what that "this
screenshot" is you are referring to, nor how you made it (which program ---
something you wrote yourself ?)
ok, but this is not even needed... this information how I did it,
becaouse as I said if I set notepad exatcly at the top left of the
screen it gives wrong -8,-8 , the GetWinRect function. There is not need
to really investigate other things untill this problem is first
solved... you agree? Why does rect return -8,-8 even though the notapads
frame is not outside the screen?
Post by R.Wieser
Hint: You could do worse than to try to describe the problem AND what you
use to evoke it to us as if we have absolutily no knowledge of what you are
busy with -- something thats actually even true (at least for me, as I'm not
a mindreader) :-)
my opinion is that it is not needed to discuss more than why we get that
-8,-8. That error needs to be solved first... and then the others...

Its like investigating why something is flying wrongly... well, we can
investigate the flying object, but maybe its better to go to the source
first and see how it was shot... error there really tells everything and
we do not need to even investigate things after that.
Post by R.Wieser
Regards,
Rudy Wieser
R.Wieser
2016-04-09 18:51:59 UTC
Permalink
JiiPee,
Post by JiiPee
no, its my own code, only like 15 lines of code to use
that rectangle and then copy that part from the screen.
I'm afraid I can't help you any further. You've got problems with some code
you wrote yourself, but all we currently have to work with is a complaint
about a single function which does exactly what it should do, with an
expected -8,-8 top-left result for a full-screen app. That function does
not seem to be the problem at all.

Regards,
Rudy Wieser
Post by JiiPee
Post by R.Wieser
JiiPee,
I can see it becouse I take a screenshot ...
And there you have TWO problems: It might just be as you describe, but it
could as easily be that that screenshot software does something you do not
expect from it ...
no, its my own code, only like 15 lines of code to use that rectangle
and then copy that part from the screen. I checked and they all use that
rect as it is.... so they do not increase the rect. So am sure there is
nothing wrong with that code.
Also, when I maximize notepad, i can see that its frame hits the desktop
left corner (but does not go over it). And we get that -8, so obviously
there is something happening there with GetWindowRectangle.
Post by R.Wieser
But in this screenshot
And thats problem #3: I have absolutily *no idea* what that "this
screenshot" is you are referring to, nor how you made it (which program ---
something you wrote yourself ?)
ok, but this is not even needed... this information how I did it,
becaouse as I said if I set notepad exatcly at the top left of the
screen it gives wrong -8,-8 , the GetWinRect function. There is not need
to really investigate other things untill this problem is first
solved... you agree? Why does rect return -8,-8 even though the notapads
frame is not outside the screen?
Post by R.Wieser
Hint: You could do worse than to try to describe the problem AND what you
use to evoke it to us as if we have absolutily no knowledge of what you are
busy with -- something thats actually even true (at least for me, as I'm not
a mindreader) :-)
my opinion is that it is not needed to discuss more than why we get that
-8,-8. That error needs to be solved first... and then the others...
Its like investigating why something is flying wrongly... well, we can
investigate the flying object, but maybe its better to go to the source
first and see how it was shot... error there really tells everything and
we do not need to even investigate things after that.
Post by R.Wieser
Regards,
Rudy Wieser
JiiPee
2016-04-09 22:52:04 UTC
Permalink
Post by R.Wieser
JiiPee,
Post by JiiPee
no, its my own code, only like 15 lines of code to use
that rectangle and then copy that part from the screen.
I'm afraid I can't help you any further. You've got problems with some code
you wrote yourself, but all we currently have to work with is a complaint
about a single function which does exactly what it should do, with an
expected -8,-8 top-left result for a full-screen app. That function does
not seem to be the problem at all.
but why is there -8? its not becouse of the frame, becouse the frame it
touching the edge of the screen
JiiPee
2016-04-10 09:08:26 UTC
Permalink
I posted the code below, in the other post...
JiiPee
2016-04-09 15:49:46 UTC
Permalink
Post by R.Wieser
JiiPee,
Post by JiiPee
But for example if I maximize my notepad and take its rect
with this, it gives: -8, -8 as a top left.
Thats correct. The *client-area* gets enlarged to fit the full screen,
which means that the window the client-area is in must be bigger that that
(to accomodate the windows borders).
but its not about the client area of the notepad.... it gives the full
notapad rectangle, I can see. It is the full notepad rectangle plus some
extra.
Geoff
2016-04-09 15:51:08 UTC
Permalink
Post by JiiPee
Why does GetWindowRect give like 8 pixels too wide area when I call it
for a window? I get the windows handle by
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
CRect rect;
::GetWindowRect(hWnd, rect);
But for example if I maximize my notepad and take its rect with this, it
-8, -8 as a top left. Should be 0,0. Also I can see that if I place the
Notepad somewhere else on desktop the same happens.
This is correct. The WindowRect is defined in terms of the desktop
coordinates and includes the thickness of the window borders.

Perhaps you were thinking in terms of the client rectangle?
JiiPee
2016-04-09 17:10:46 UTC
Permalink
Post by Geoff
This is correct. The WindowRect is defined in terms of the desktop
coordinates and includes the thickness of the window borders.
not sure if we are talking about the same thing. This is what happens:
the rectangle of notepad is (*including the frame, menu... everything*):
Rect(100,100, 300, 350)
ok... then if I take the windowrectangle with that function it gives:
Rect(92,92, 308, 353)... something like that. So this is not about
client area....
Post by Geoff
Perhaps you were thinking in terms of the client rectangle?
which client you are talking about ?
Geoff
2016-04-09 18:03:52 UTC
Permalink
Post by JiiPee
Post by Geoff
This is correct. The WindowRect is defined in terms of the desktop
coordinates and includes the thickness of the window borders.
Rect(100,100, 300, 350)
Rect(92,92, 308, 353)... something like that. So this is not about
client area....
Post by Geoff
Perhaps you were thinking in terms of the client rectangle?
which client you are talking about ?
I was referring to using GetClientRect rather than GetWindowRect.
JiiPee
2016-04-09 23:07:52 UTC
Permalink
Post by JiiPee
which client you are talking about ?
I was referring to using GetClientRect rather than GetWindowRect.
but that does not give the notepads frame, only the text control
Geoff
2016-04-10 01:58:21 UTC
Permalink
Post by JiiPee
Post by JiiPee
which client you are talking about ?
I was referring to using GetClientRect rather than GetWindowRect.
but that does not give the notepads frame, only the text control
I cannot offer you any more advice since it's no longer clear to me
what your goal is or whether you are asking the right question.

I will offer this:
Consider using the window's device context and deal with the rectangle
in its DC rather than it's desktop position:

CWindowDC winDC(pWnd);
pWnd->GetWindowRect(rect);
int nBPP = winDC.GetDeviceCaps(BITSPIXEL) *
winDC.GetDeviceCaps(PLANES);
if (nBPP < 24)
nBPP = 24;
bStat = image.Create(rect.Width(), rect.Height(), nBPP);
ASSERT(bStat);
if (!bStat)
return;
CImageDC imageDC(image);
::BitBlt(imageDC, 0, 0, rect.Width(), rect.Height(), winDC, 0, 0,
SRCCOPY);

This code is from Microsoft AllVCSamples, the DLLScreenCap project.
JiiPee
2016-04-10 09:01:12 UTC
Permalink
Post by Geoff
Post by JiiPee
Post by JiiPee
which client you are talking about ?
I was referring to using GetClientRect rather than GetWindowRect.
but that does not give the notepads frame, only the text control
I cannot offer you any more advice since it's no longer clear to me
what your goal is or whether you are asking the right question.
Consider using the window's device context and deal with the rectangle
CWindowDC winDC(pWnd);
pWnd->GetWindowRect(rect);
But, I dont understand how would this work better than my version
becouse here you will also do exactly the same this:

pWnd->GetWindowRect(rect);


what I do, and thus this would set rect to be: -8,-8. Now, the below
code would (I think) use that -8 and capture again bigger image than
needed. Or does the code below somehow "ignore" or adjust the -8 to 0? I
cannot see it doing it:

::BitBlt(imageDC, 0, 0, rect.Width(), rect.Height(), winDC


here it starts taking the image from coordinates -8,-8 and sure that is
not the top corner of the desktop we see? Or the screen starts from -8?
Post by Geoff
int nBPP = winDC.GetDeviceCaps(BITSPIXEL) *
winDC.GetDeviceCaps(PLANES);
if (nBPP < 24)
nBPP = 24;
bStat = image.Create(rect.Width(), rect.Height(), nBPP);
ASSERT(bStat);
if (!bStat)
return;
CImageDC imageDC(image);
::BitBlt(imageDC, 0, 0, rect.Width(), rect.Height(), winDC, 0, 0,
SRCCOPY);
This code is from Microsoft AllVCSamples, the DLLScreenCap project.
JiiPee
2016-04-10 09:07:55 UTC
Permalink
here is my code (Derived from CImage). where does it go wron?:

BOOL CScreenImage::CaptureRect(const CRect& rect)
{
// detach and destroy the old bitmap if any attached
CImage::Destroy();

// create a screen and a memory device context
HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
// create a compatible bitmap and select it in the memory DC
HBITMAP hBitmap =
::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height());
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);

// bit-blit from screen to memory device context
// note: CAPTUREBLT flag is required to capture layered windows
DWORD dwRop = SRCCOPY | CAPTUREBLT;
BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(),
hDCScreen,
rect.left, rect.top, dwRop);
// attach bitmap handle to this object
Attach(hBitmap);

// restore the memory DC and perform cleanup
::SelectObject(hDCMem, hBmpOld);
::DeleteDC(hDCMem);
::DeleteDC(hDCScreen);

return bRet;
}

BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
CImage::Destroy();

BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
CRect rect;
::GetWindowRect(hWnd, rect);
bRet = CaptureRect(rect);
}
return bRet;
}
Geoff
2016-04-11 01:57:45 UTC
Permalink
Post by JiiPee
BOOL CScreenImage::CaptureRect(const CRect& rect)
{
// detach and destroy the old bitmap if any attached
CImage::Destroy();
// create a screen and a memory device context
HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
// create a compatible bitmap and select it in the memory DC
HBITMAP hBitmap =
::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height());
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);
// bit-blit from screen to memory device context
// note: CAPTUREBLT flag is required to capture layered windows
DWORD dwRop = SRCCOPY | CAPTUREBLT;
BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(),
hDCScreen,
rect.left, rect.top, dwRop);
// attach bitmap handle to this object
Attach(hBitmap);
// restore the memory DC and perform cleanup
::SelectObject(hDCMem, hBmpOld);
::DeleteDC(hDCMem);
::DeleteDC(hDCScreen);
return bRet;
}
BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
CImage::Destroy();
BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
CRect rect;
::GetWindowRect(hWnd, rect);
bRet = CaptureRect(rect);
}
return bRet;
}
Oh. I see this is not your code but comes from:
http://www.codeguru.com/cpp/article.php/c18347/C-Programming-Easy-Screen-Capture-Using-MFCATL.htm

Running the CaptureDemo application I see the behavior you are talking
about.

The demo _almost_ behaves correctly for capturing a non-maximized
window but extends the bottom right corner by 8 points but gets the
-8, -8 for the top left corner of a maximized window and 8 pixels too
large for the extent of the bottom right. It gets correct corner
coordinates for capturing the full screen image.

The question now is, did it ever work correctly?


The solution I found, although it feels like a bit of a hack, was to
use GetWindowInfo to obtain the rcClient rectangle and pass it to
CaptureRect instead of the window rectangle.

BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
WINDOWINFO info;
info.cbSize = sizeof(WINDOWINFO);
BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
//CRect rect;
//::GetWindowRect(hWnd, rect);
::GetWindowInfo(hWnd, &info);
bRet = CaptureRect(info.rcClient);
}
return bRet;
}


I think this might be a legacy problem from earlier versions of
Windows that had borders. Windows 7 thru 10 windows don't have visible
borders anymore and I think when maximized the windows were clipped at
the desktop margins and the borders disappeared. Unfortunately, I
don't have any older systems running anymore on which to test.
Geoff
2016-04-11 02:00:44 UTC
Permalink
Post by Geoff
I think this might be a legacy problem from earlier versions of
Windows that had borders. Windows 7 thru 10 windows don't have visible
borders anymore and I think when maximized the windows were clipped at
the desktop margins and the borders disappeared. Unfortunately, I
don't have any older systems running anymore on which to test.
I should also add, in Windows 10 it appears to me the borders still
exist but are rendered invisible as they allow for a mouse drag target
for resizing.
JiiPee
2016-04-11 06:16:07 UTC
Permalink
Post by Geoff
Post by Geoff
I think this might be a legacy problem from earlier versions of
Windows that had borders. Windows 7 thru 10 windows don't have visible
borders anymore and I think when maximized the windows were clipped at
the desktop margins and the borders disappeared. Unfortunately, I
don't have any older systems running anymore on which to test.
I should also add, in Windows 10 it appears to me the borders still
exist but are rendered invisible as they allow for a mouse drag target
for resizing.
oh cool, I will try that code later
Geoff
2016-04-12 18:46:35 UTC
Permalink
Post by JiiPee
BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
WINDOWINFO info;
info.cbSize = sizeof(WINDOWINFO);
BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
//CRect rect;
//::GetWindowRect(hWnd, rect);
::GetWindowInfo(hWnd, &info);
bRet = CaptureRect(info.rcClient);
}
return bRet;
}
Well, I knew this was too easy a hack and I don't like the results.
This is too simplistic because you have to take into account the style
of the window frame and the state of the window when taking the
borders into account.
Geoff
2016-04-13 09:13:57 UTC
Permalink
Post by Geoff
Post by JiiPee
BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
WINDOWINFO info;
info.cbSize = sizeof(WINDOWINFO);
BOOL bRet = FALSE;
if(::IsWindow(hWnd))
{
//CRect rect;
//::GetWindowRect(hWnd, rect);
::GetWindowInfo(hWnd, &info);
bRet = CaptureRect(info.rcClient);
}
return bRet;
}
Well, I knew this was too easy a hack and I don't like the results.
This is too simplistic because you have to take into account the style
of the window frame and the state of the window when taking the
borders into account.
Here is a "working" solution that is far from perfect and can probably
fail for certain windows. It's very much a hack. I'd like to see
something that works perfectly the way alt-Print Screen works.

BOOL CScreenImage::CaptureWindow(HWND hWnd)
{
CImage image;
WINDOWINFO info;
info.cbSize = sizeof(WINDOWINFO);
BOOL bRet = FALSE;
if (::IsWindow(hWnd))
{
CRect rect;
::GetWindowRect(hWnd, rect);
::GetWindowInfo(hWnd, &info);
if (IsZoomed(hWnd))
{
OutputDebugString("Is Maximized\n");
rect.top += info.cyWindowBorders;
rect.left += info.cxWindowBorders;
rect.bottom -= info.cyWindowBorders;
rect.right -= info.cxWindowBorders;
}
else if (!(info.dwStyle & WS_THICKFRAME))
{
OutputDebugString("Is a popup window\n");
rect.top += info.cyWindowBorders / 4;
rect.left += info.cxWindowBorders / 4;
rect.bottom -= info.cyWindowBorders / 4;
rect.right -= info.cxWindowBorders / 4;
}
else if (info.dwStyle & WS_OVERLAPPEDWINDOW)
{
OutputDebugString("Is a Thickframe window\n");
rect.left += info.cxWindowBorders;
rect.bottom -= info.cyWindowBorders;
rect.right -= info.cxWindowBorders;
}
bRet = CaptureRect(rect);
}
return bRet;
}

Loading...