Hi I created a dialog box within win32:
ABOUTBOX DIALOG DISCARDABLE 32, 32, 180, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,66,80,50,14
ICON "ID_MYICON_2",IDC_STATIC,0,0,48,48
CTEXT "comment1",IDC_STATIC,40,12,100,8
CTEXT "comment2",IDC_STATIC,7,40,166,8
CTEXT "comment3",IDC_STATIC,7,52,166,8
END
The icon file contains different sizes of images i.e. 16x16, 32x32, 48x48 etc however the code above only allows it do be displayed as 32x32. Even if i change it to
ICON "ID_MYICON_2",IDC_STATIC,0,0,16,16
.. it still shows as 32x32. How do you fully control icon size? My original intention was to display a bmp.
Any help most appreciated.
It is behavior by design. See Static Control Styles:
The style ignores the CreateWindow parameters nWidth and nHeight; the
control automatically sizes itself to accommodate the icon. As it uses
the LoadIcon function, the SS_ICON style can load only icons of
dimensions SM_CXICON and SM_CYICON. This restriction can be bypassed
by using the SS_REALSIZEIMAGE style in addition to SS_ICON.
Also, nothing prevents you from loading 48x48 icon programmatically and passing it to the control.
Related
I want a window which behaves identically to normal Overlapped window, except it does not have capton bar when maximized (to make more room for the client area).
I can remove WS_CAPTION|WS_SYSMENU from the window style.
However, I cannot find way to get window position and size right:
A normal window is maximized by expanding work area rectangle with border width. This makes border to "hang" outside. When I remove WS_CAPTION, the border is different (3 vs 4 pixels in my case) so I have to reposition the window somehow.
What I have tried:
First change style, then maximize: this does not maximize to work area, but to full screen instead. Looks like this is a feature of window manager that relies on WS_CAPTION style. Other than that, the border is "hanging" correctly.
First maximize, then change style, position and size:
I can't find API to get the maximized size and position. However, work area of closest monitor looks good to me.
I can't find API to expand window rect with appropriate "hanging border". AdjustWindowRectEx is almost there, however non-client area is not the same as border (obviously it also includes caption and menu). I also tried to do the math myself using GetSystemMetrics values, but it seems too unpredictable. The border could be SM_CXSIZEFRAME, or SM_CXSIZEFRAME+SM_CXPADDEDBORDER, or SM_CXFIXEDFRAME, and maybe this depends on OS version, theme and whatever.
Is it possible to do this in a robust, "official" way?
I put my own answer below but it is too hacked.
You are already removing the caption. If you don't want to show the borders, then remove the borders as well. Get ready to restore the border later. Find the desktop rectangle, and position the window in to that rectangle. The full screen window can have WS_OVERLAPPED or WS_POPUP flag with no caption and no borders. Example:
void switch_view()
{
RECT rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
if(style & WS_CAPTION)
{
SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPED);
SetWindowLongPtr(hwnd, GWL_EXSTYLE, 0);
SetWindowPos(hwnd, NULL, 0, 0, rc.right, rc.bottom,
SWP_SHOWWINDOW | SWP_FRAMECHANGED);
}
else
{
SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
}
}
This is what I get after many attempts.
The border problem is solved. As suggested by others, I remove border together with caption. Therefore no need to calculate it. There is also no need to calculate border for captioned window with border, because this is special-cased by window manager.
To obtain and maintain the right size, I use MonitorFromWindow and GetMonitorInfo. The position and size are applied together with style change (both ways) and also in WM_SIZE handler. Watching WM_SIZE allows to recover from external minimize-restore events, as well as TaskBar change etc.
For unknown reason, moving with Win+Arrow keys does not work. This issue only exists when the window is in maximized state and without caption. Using this workaround:
in WM_WINDOWPOSCHANGING set WS_CAPTION style. This allows window to move correctly. Afterwards, the WM_SIZE handler applies the right style/position/size again.
Approach that failed: use restored window rather than maximized. In this case there is too much going wrong in restore-move-maximize-restore lifecycle (either restore or maximize goes to wrong monitor).
I am creating a dialog with a tab control. Each tab should show different set of controls, so I have created child dialog boxes in resource editor to behave like pages.
I have used instructions from this post to do this.
In resource editor I made dialog boxes without border, set their styles to Child, removed system menu, and I have set flags Control and Control Parent to true.
In my child dialog box procedures I have handled WM_INITDIALOG by adding EnableThemeDialgTexture(handleOfmyDialog, ETDT_ENABLETAB); and returning TRUE. No WM_ERASEBKGND, WM_PAINT or WM_CTLCOLORDLG have been overridden.
In main dialog box that contains tab control, I have created "child dialogs" with CreateDialog function, and have used MoveWindow to properly position them.
I did not use EndDialog to destroy "child dialogs" on IDCANCEL or WM_CLOSE, I think that they will get destroyed automatically.
I have used Visual Studio 2013 on Windows 8.1 to do all this.
There seems to be no problem on Windows 7 and Windows 8.1, but maybe my eyes are playing tricks with me, since the background color of the tab control is similar to the default background color of the dialog box. The problem is best seen on Windows XP, as shown on the picture below:
How can I make background color of "child dialogs" ( and their child controls like checkbox/trackbar/radio button/static control ) to be transparent ( match the background color of tab control )?
Thank you.
This is a pretty straight-forward problem. You can't see the mistake on later Windows version because they no longer use a gradient for the "texture". EnableThemeDialogTexture() worked just fine, your dialog certainly has the same texture as your tabcontrol. The brush origin starts at the upper-left corner of the dialog. Like it does for the tabcontrol. But the dialog is not positioned correctly, now the gradients are mis-aligned and the dialog no longer blends.
You need to move the dialog so it is located correctly inside the tab page area. The relevant line of code from the MSDN article:
// Size the dialog box.
SetWindowPos(hwndDlg, NULL,
0, 0, // <=== here!
rcTab.right + cyMargin + (2 * GetSystemMetrics(SM_CXDLGFRAME)),
rcTab.bottom + rcButton.bottom + (2 * cyMargin)
+ (2 * GetSystemMetrics(SM_CYDLGFRAME))
+ GetSystemMetrics(SM_CYCAPTION),
SWP_NOMOVE | SWP_NOZORDER);
Positioned at (0, 0) in the client area of the tabcontrol, now the gradients align.
Hans’ observation is right, but with the wrong conclusions.
Indeed, EnableThemeDialogTexture() worked: There clearly is a gradient on the background of the Slider control. And indeed it does not line up with the tab control’s background.
However, this is not an alignment problem. The gradient you see on the Slider control is the correct gradient according to EnableThemeDialogTexture(). The gradient on the background is actually the wrong one. You can clearly see it with enhanced contrast – the background gradient is blocky and coarse, while the Slider’s gradient is perfectly fine.
I observed this exact behavior when the main window had the WS_CLIPCHILDREN style set while the Z order was wrong (tab above child). Move the child dialog boxes to the top of the Z order via SetWindowPos(child, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE) and it should align perfectly and not be blocky any more.
I have a button which is created in the WM_CREATE function of a Win32 Application with the following code:
hChangeWorldButton = CreateWindowEx(NULL,
"BUTTON",
"OK",
WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
2,
2,
25,
25,
hWnd,
(HMENU)CHANGEWORLD_BUTTON,
GetModuleHandle(NULL),
NULL);
SendMessage(hChangeWorldButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)worldBmp);
I would like the button to show only the image. Not the background and border.
How can I do this? I have tried many different button styles from MSDN but nothing seems to fit my needs. I was thinking of using BS_OWNERDRAW but it seems a bit overkill. Or is it the only solution?
Finally, how can I change the cursor to be a hand when it's hovering over the button?
No button style is available that results in the visual representation you are after. You would have to go with BS_OWNERDRAW here.
As an alternative you could use a Static Control with the SS_NOTIFY style instead. A static control allows you to get the visual representation you want, and the SS_NOTIFY styles allows you to respond to mouse input. However, you will not be able to implement a keyboard interface.
While I have not tried this myself, it may also be possible to get the desired effect by using a Command Link (BS_COMMANDLINK), and setting the caption to an empty string.
To eliminate the button's background and border simply make the button smaller than the bitmap.
I have an application that compiles ok (mingw) and runs ok, however the edit control that is created has scroll bars but the vertical scroll bar doesn't do anything. The same executable works fine on WinXP. Also, the edit control has both vertical and horizontal scroll bars, the horizontal works just fine, but vertical does not. The vertical scroll bar is visible and clickable, but nothing happens...
Following code is used when creating the edit control:
HWND hwndEdit = CreateWindow(TEXT("EDIT"), TEXT("Edit control"),
WS_OVERLAPPED | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_READONLY | WS_SIZEBOX,
1000, 480, 400, 500, NULL, 0, GetModuleHandle(NULL), NULL);
SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM) TEXT(""));
SendMessage(hwndEdit, EM_LIMITTEXT, 0, 0);
Following code is used repeatedly to add text to edit control:
char test[] = "test";
SendMessage(hWndDbg, EM_SETSEL, 0x7FFFFFFF, 0x7FFFFFFF); // Undo any selection and move to end.
SendMessage(hWndDbg, EM_REPLACESEL, 0, (LPARAM) temp);
Finally found the fix. It seems in WinXP the edit control does not have to have a parent window defined, in Win7 it is required for the vertical scroll bar to work, horizontal scroll bar works in Win7 even without parent window defined.
Note that vertical scroll bars even make sense on single-line edit controls. In this case, WM_VSCROLL must be set, and ES_AUTOVSCROLL not. (EM_AUTOVSCROLL means EM_AutoHIDEVScroll.) The alternative UpDown control makes more programming efford than capturing VM_VSROLL messages, and then changing the (typically numerical) value inside the edit control.
Unluckily, the MS Visual Studio built-in Resource Editor won't let you add WM_VSROLL to single-line edits! You must do this by adding this bit by editing the .RC file in text mode.
Similar to the fact that this Resource Editor won't let you add a default text to the control, which is still supported by the resource loader.
Use GetDesktopWindow() as hWndParent parameter. It works on Win7.
I've got a dialog box where I need to display the standard Information icon. Here's my RC code:
ICON "",IDC_ICON_INFORMATION,18,70,21,20
I process the WM_INITDIALOG message as follows:
HICON aIcn = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(m_hWnd, IDC_ICON_INFORMATION, STM_SETICON, (WPARAM) aIcn, 0);
Everything works great under 96 DPI: the static control displays a 32x32-pixel icon.
However, when I switch to higher DPI's (through right-clicking on the Desktop, choosing Screen resolution, and clicking Make or other items larger or smaller) the icon does not scale! Since everything else scales nicely, the icon looks visually much smaller than the neighboring text. I would expect that on 144 DPI (150%) the icon dimensions will be 48x48 pixels. I did declare my application as DPI-aware through an XML manifest.
The damnedest thing is that when I use my own custom-made icon (also coming from the RC file), everything scales perfectly. Furthermore, the MessageBox function called with the MB_ICONINFORMATION flag does display a scaled version of the icon, as well.
Given these thoughts, I assume of the following:
The static control with the SS_ICON style can display scaled versions of icons.
The icon resource that contains the standard Information icon has a scaled version of the icon (48x48).
What am I doing wrong then?
Use LoadImage() instead of LoadIcon(), and specify the cxDesired and cyDesired params with the values you get from GetSystemMetrics(SM_CYICON) and GetSystemMetrics(SM_CXICON).
Or maybe just declaring your app as DPI aware could be enough? You can try that easily by simple creating a text file making it a manifest file.
See the example in the remarks section for the SetProcessDPIAware API