How to get size of floating toolbar - mfc

How do I get the size of a floating CControlBar in MFC?
I want to obtain a size in screen coordinates.
I have tried
CControlBar *bar_p;
...
bar_p->GetWindowRect(&rect);
which doesn't seem to include the borders, and
bar_p->GetParent()->GetParent()->GetWindowRect(&rect);
which gives a size that is a little too wide and tall.

The problem turned out to be a bug elsewhere in the program. The following does indeed find the rectangle of the CMiniFrameWnd in which the floating toolbar appears
CRect rect;
if(bar_p->IsFloating())
{
bar_p->GetParent()->GetParent()->GetWindowRect(&rect);
..
}

Related

How can I get RGB value of pixel where mouse is on desktop? (GetPixel doesn't match the point....)

I'm trying to make a C++ code that prints the rgb value of pixel where mouse cursor is every second.
I used
GetDC(NULL) for HDC of desktop,
GetCursorPos(&pos) for the position of mouse cursor,
getPixel(hDC, pos.x, pos.y) for the RGB value of the pixel that the mouse cursor points.
Here is my full C++ code.
#include <iostream>
#include <Windows.h>
using namespace std;
int main(){
POINT pos;
int R;
int G;
int B;
while (1) {
GetCursorPos(&pos);
HDC hDC = GetDC(NULL);
COLORREF color=GetPixel(hDC, pos.x, pos.y);
R = GetRValue(color);
G = GetGValue(color);
B = GetBValue(color);
std::cout <<"x : "<<pos.x<<", y : "<<pos.y<<", R : "<< R <<", G : " <<G << ", B : "<<B << endl;
ReleaseDC(NULL, hDC);
Sleep(1000);
}
return 0;
}
When I compiled this,
it prints the rgb value of some pixel every second, however, the pixel doesn't match the pixel where mouse is on.
At first, I just thought that the client of some window may have different point, or the total number of pixels in my laptop is less than 1920x1080 (it's actually 1536x864), so there may be a bug, and it could be solved by just translating the point.
But although for some points, it did work, but most points, it didn't work.
And I tried some test. (The code is compiled using visual studio 2017.)
While the code running, I dragged the console window by mouse. (Note that the console window's Non-client window is almost white. i.e. the RGB value is (255, 255, 255). ) So, the relative position of mouse cursor on the console window doesn't change.
However, the printed rgb value changed!
I suggest that it may be related to the ppi, but I don't know why exactly.
What should I do and know to get the rgb value of pixel that the mouse cursor points?
UPDATED ANSWER: The solution appears to be related to the system's DPI setting and the level of DPI awareness of the application as reported by #정재우 and #Remy Lebeau in the comments. In Windows 10, the relevant setting can be found in:
Settings -> Display -> Scale and Layout
The OP's code works fine if this setting is 100%. Otherwise the coordinates returned by GetCursorPos() are scaled. More information can be found in the following articles:
Windows scaling issues for high-DPI devices
High DPI Desktop Application Development on Windows
Setting the default DPI awareness for a process
ORIGINAL ANSWER (WITH SPECULATION):
Your code appears to display the correct pixel values on my machine, however you may get different results from different screen configurations such as when using multiple monitors as coordinates left of your primary monitor can be given in negative values. However on my Windows 7 machine using multiple monitors, negative mouse coordinates still properly translate.
Additionally, the "client" area of the screen excludes areas like the taskbar, at least this is how I remember older versions of Windows working. To address this possibility, try replacing your GetDC() call with GetWindowDC() or GetDCEx(NULL,NULL,DCX_WINDOW) and see if you get different results.
To help with debugging, add the following call directly after your GetPixel() call to create subtle red pixel artifacts:
SetPixel(hdc,pos.x,pos.y,RGB(255,0,0));
This places a red pixel on the screen from the same spot you just read the pixel value. Observe how near your red pixels are to the actual mouse cursor as you move the mouse around.

MFC picture control changes size when DPI awareness disabled or running on Win7

I made an MFC app for my friend using VS2015 in Win10. It looks like this, which is exactly the same as in resource editor.
.
But when he ran the app on his computer in Win7, the Bitmap image in Picture Control enlarges and covers up some text boxes below, which looks like this.
.
After I searched and realized it may be related with DPI awareness. I disabled DPI-Awareness in property page of Manifest Tool and rebuilt. The same thing happened even when it runs in Win10.
Could someone help me explain the cause of this and find a solution to fix the size of the image control? Thanks.
The main problem is that a dialog from a resource is always measured in DLUs.
And DLUs are calculated from the size of the font, that is used for the dialog.
See this article how dialog base units are calculated.
Now you have a static picture control that is sized in DLUs. The bitmap is just scaled in pixels and is never resized, when you assign it to a static dialog control. And because the real size of the static control depends on the used font, you get different layouts for your dialog and your bitmap.
And because just the font changes when you choose no DPI awareness and because the font changes from windows version to windows version your dialog always look different.
Advice: Paint you picture your own and stretch it accordingly.
Also this stackoverflow question is nice documents and shows the effect of DLUs.
And here some code for auto sizeing picture controls.
An auto-sizing bitmap picture control
A simple image preview class using GDI+
CxImage
Normally, I prefer to keep control in my hand by using SetWindowPos() to set the size of image I want in different situations. You can use below two lines to control/set position and size of your image.
Assume ID of the Picture Control is IDC_STATIC2 then you can use like:
CStatic * pStatic = (CStatic *) GetDlgItem(IDC_STATIC2);
pStatic->SetWindowPos(NULL,20,20,50,50,0);

windows 10 screen coordinates are offset by 7

I'm coding in c++ on windows 10 - straight win32 API.
I wanted to make a window show up in the top right of the screen.
As I was doing this, I noticed that screen coordinates for a maximized window are left=-8, top=-8, right=1936, bottom=1088.
Also, when I position a window so right=1920 and top=0, there's about an 8 pixel gap on the right. I tried moving the window around to see what screen coordinates I got.
rect.left for a nonmaximized window can go from -7 to 1912.
so things are slid by 7 pixels ? WTF microsoft ??
How am I supposed to come up with the rec.right=1913 value to position my window aligned to right side of screen without that dang gap ?
But rect.right of 1920 leaves a gap. So rect.right of 1912 would leave MORE of a gap...
And I need a solution that'll work back to Vista.
Pre win10, that rect.right should be 1920 like ya expect.
Whaaaaat is going on here? I'm about to start throwing knives around !!
Code wise, this is just what GetWindowRect is reporting...
(excuse my weird debugging function)
::GetWindowRect (_wndo, r);
DBG("ExtRc l=`d r=`d t=`d b=`d w=`d h=`d",
r->left, r->right, r->top, r->bottom, r->right-r->left, r->bottom-r->top);
Well thanks to #ChristopherOicles
This is really his answer. Duplicate this as your own (or tweak it, whatever) and I'll accept your's.
What's going on is microsoft wrecking border widths in windows 10.
GetWindowRect returns the outside window coordinates as screen coordinates.
GetClientRect returns the inside the window coordinates.
Up until Windows 10 (F U Win10 !!),
The difference in width and height between them was the width and height of the borders.
Upon win10, the border width reports 16 pixels, so 8 pixels a side.
However, only 1 of those pixels are visible. 7 of them are transparent.
So your window has a transparent 7 pixels to the left, right, and bottom.
So you need to take those transparent 7 pixels into account if you're going to line up the window on the screen programmatically. The user doesn't want that 7 pixel gap next to the screen border !
DwmGetWindowAttribute with the attribute DWMWA_EXTENDED_FRAME_BOUNDS will get you the width and height of the ACTUALLY SHOWING part of the border in screen coordinates. So similar to GetWindowRect, but the rect does not include the invisible-ness.
You're still going to need GetWindowRect most of the time to set the width and height of your window and those 7 pixels per side of invisible-ness are needed to size the window properly programmatically.
So use the difference between the .left of the rect GetWindowRect returns and .left of what DwmTerribleName returns to get that 7 pixels of offset.
In my opinion, whoever did this at Microsoft should be immediately shot.
This is a hoop I didn't need to jump through.
This breaks compatibility with the past.
This is because of the width of the window border and other factors, which vary depending on OS version, user preference, and DPI settings. See the GetSystemMetrics function.

How to center an icon in a QToolButton?

I created a simple 10x10 black box and added it to a QToolButton as follows:
QIcon minIcon;
minIcon.addFile("c:/tmp/black10x10.png");
minButton = new QToolButton;
minButton->setIcon(minIcon);
However, it appears on screen shifted left (image enlarged for convenience):
Some squinting in Gimp told me that grey area to the left is 56 pixels zoomed and grey area to the right is 68. This misalignment is very noticeable even without zoom - that was how I spotted it in the first place. So, how do I center this icon?
P.S. Tried using a QPushButton without text. Same effect.
It's probably a bit late now, but I stumbled across the same issue and found the following code snippet in QTs qstylesheet.cpp
case CT_ToolButton:
if (rule.hasBox() || !rule.hasNativeBorder() || !rule.baseStyleCanDraw())
sz += QSize(3, 3); // ### broken QToolButton
This would increase your even sized icon to be odd sized and therefor not centered. I'm not sure why there's an addition of 3 but the comment suggest it's a fix for something...
Unfortunately this doesn't fix the issue, it just kind of explains the source of it. But it might help someone to find a better solution than "make all your icons odd sized".

Resizing a CStatic control dynamically to fit text

As of now, I'm using the following to code to resize my CStatic controls:
WINDOWPLACEMENT wndpl;
m_myStaticControl.GetWindowPlacement(&wndpl);
// Increase the static box's width
wndpl.rcNormalPosition.right += 10;
m_myStaticControl.SetWindowPlacement(&wndpl);
m_myStaticControl.SetWindowText("Some text");
I obtain the constant (in the above case, 10) by trial-and-error. Because this seems like a really inelegant and hard-to-maintain solution, I want to change this. After some research, I think I have a basic idea; which is:
Get the pixel width and height of the required text using GetTextExtentPoint32.
Get the current window placement of the CStatic control as in code example above.
If the current width < obtained pixel width, add obtained pixel width. Do the same for height.
Set the window placement as in code example above.
Set the window text as in code example above.
Would this be a good, efficient approach? Also, does GetTextExtentPoint32 use pixels or dialog units?