WIN32: Duplicate Standard Button Control (disabled Icon / hotkey underline) in Owner Draw Button? - winapi

So for the simple feat of wanting to put an icon on the right side of button text instead of the left resulted in having to use owner draw buttons (but someone here said Custom Draw is actually available if using visual themes). Okay, fine, but now I'm finding you can't really duplicate what Windows standard buttons do when it's not in owner draw mode.
For a normal enabled button I can get the look correct by checking if visual styles are available or not and then using either the DrawThemeBackground() / DrawThemeText() or DrawFrameControl() / DrawText(). However the hot key underline character is shown even when alt key is not pressed, the default buttons don't show it until alt pressed.
For a disabled button, I can't duplicate the disabled look of the icon placed on the button. I tried DrawState() over DrawIconEx() but that looks like the old Windows 3.1 type grey graphic not the visual style dimmed graphic. I see there is a DrawThemeIcon() for an image list, I guess I could try that (I'd have to test non visual style mode to see if DrawState() matches when not using visual styles).
Also, as you hover over the button, the state doesn't change, I understand that if using owner draw, that doesn't occur, maybe it would still work with Custom Draw?
So the two main questions are:
1 - Is there something built-in to the button / owner draw to handle the underlined hotkey only when alt was pressed?
Update to Question 1: I found DT_HIDEPREFIX in DrawText() and using Custom Draw there is the CDIS_SHOWKEYBOARDCUES flag. However with Owner Draw I'm not sure if there is a flag someplace?
2 - How do you draw an icon for a button that is disabled to match what default buttons do?
TIA!!

For shortcut underline you can use WM_QUERYUISTATE to ask if it should be hidden or visible
DWORD draw_text_flags = ...;
if ( SendMessage( control_hwnd, WM_QUERYUISTATE, 0, 0 ) & UISF_HIDEACCEL ) != 0 )
{
// hide prefix
draw_text_flags |= DT_HIDEPREFIX;
}
// some combination of PBS_DEFAULTED, PBS_DISABLED, PBS_HOT, PBS_NORMAL, PBS_PRESSED;
int state = ...;
DrawThemeText( theme, hdc, BP_PUSHBUTTON, state, text, text_len, draw_text_flags, 0, rect );

Answer to Q2: If you create an HIMAGELIST using ILC_COLOR32 | ILC_MASK, and use ILD_NORMAL|ILD_BLEND25 on ImageList_Draw() it gives the same look as windows default buttons for a disabled button.

Based on responses from #Remy-Lebeau and #Daniel-Sęk and reviewing various projects on CodeProject, I create an easy to use class to handle this. It can be found at CodeProject. Thanks Guys.

Related

"Always show selection" doesn't work on CListCtrl in list mode

I want a user to be able to select item(s) in my CListCtrl and then click on a button to act on those items. But when the focus is lost from the list, the selection is no longer shown, even if I set 'Always show selection' to true:
This happens both in the dialog test facility, and in my compiled application. I use list-mode, and have no icons, only text.
To reproduce:
Create a new dialog in the resource editor
Place a list-view control.
Set View = List in the properties
Set Always Show Selection = True in the properties
Add a button to the dialog
Press Ctrl-T to test the dialog
Select item(s) on the list, then press the button
..and the text is not visibly selected at all. Or is it... I can just
barely sort of see some very very faint selection in my screenshot - I
think. It's so faint I am not 100% certain it's there!
In addition to my comments: well, there you have it - they are selected, and in a different color, but it seems your screen settings are a bit off. Maybe your color settings, a high contrast mode, or the color setting for selected items in Windows.
The gray color in your screenshot is: #f7f3f7 - light gray, so you might have a problem seeing it, depending on the settings.
An interesting and very lightweight tool to check those things (zoom in, see the color values) is ZoomPlus. I use it every day, and there seems to be source code available too.

Dialog box as a tab page has different background color from a tab control it belongs

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.

Programmatically scrolling a Windows edit control

Is there any way to programmatically scroll a single-line edit control in Windows?
For example, if the text in an edit control is too large to display at once, then the default behavior when the edit control gets the focus is to select all text and show the end of the text. I'd like to instead show the beginning of the text (while still leaving all text selected).
Although there's (apparently) no API for scrolling to the beginning and selecting all text, it seems to work to simulate the keystrokes that would do the same:
#ifndef CTRL
#define CTRL(x) (x&037)
#endif
SendMessage(edit_handle, WM_KEYDOWN, VK_HOME, 0);
SendMessage(edit_handle, WM_CHAR, CTRL('A'), 0);
You can either call SetScrollPos or send the WM_VSCROLL/WM_HSCROLL message directly to the window. You can find the full list of scroll functions here.

GTK - Don't highlight buttons on select / hover

I'm trying to write a kiosk GUI in ruby/gtk on ubuntu. I'm pretty fluent in ruby, but new to writing GUIs and not great with linux.
I'm using a touch screen, and am using our own images for buttons, e.g.
button_image = Gtk::Image.new(Gdk::Pixbuff.new "images/button_image.png")
#button = Gtk::Button.new
#button.add(button_image)
#button.set_relief(Gtk::RELIEF_NONE)
My issue is that when the buttons are pressed or remain selected (or hovered over, although this is less relevant with a touch screen), gtk shows fat, square borders around them. Obviously it's applying gtk's prelight / selected / active lighting to the buttons. I've tried changing the button properties in various ways, and also tryied hacking apart my theme, and while I can modify how the highlighting looks, I can't seem to completely get rid of it. Changing the color of the highlight via my theme is easy, but if I remove my setting there's still a default I can't get rid of.
Does anyone know if there's a way to stop it, or possibly make it transparent? Thanks in advance!
Sounds like you want to use exactly your image for the whole button, instead of putting an image inside the normal GtkButton - but still use all the normal behavior of the button.
The easiest way to do this is to just override the drawing. If you are on gtk2, connect to the "expose-event" signal, do your drawing there, and return true so that the default handler doesn't get run. If you are on gtk3, connect to the "draw" signal and do the same.
I tried meddling with the drawing as Federico suggested, but found that the most direct way to address this was instead to use an event box rather than a button. Event boxes accept clicks just like buttons, but don't respond to selecting, hovering, etc. In ruby, the code looks like this:
image = Gtk::Image.new("myfile.png")
event_box = Gtk::EventBox.new.add(image)
event_box.visible_window = false
event_box.signal_connect("button_press_event") do
puts "Clicked."
end
Most of this is exactly like a button; the *visible_window* method, obviously, keeps the event box from being visible under the button image.

How to create full screen window with MFC?

I want to create full screen topmost (screen saver) window with MFC? How to create such full screen window in MFC? I tried to create win32 application and i am able to create fullscreen top most window but i want to create using MFC so later i can put different MFC controls on that window?
Please help me.
Thanks,
Jim.
I think removing the border from the dialog resource and showing the window as maximized (ShowWindow(SW_SHOWMAXIMIZED)) should do the job.
As for topmost use the System Modal style in the dialog resource.
I do it with a Dialog Box app. In the resource editor properties for the dialog resource, set Border=None and Title Bar=False to eliminate all border elements. In OnInitDialog, use the following to resize the dialog to the entire desktop:
CRect rcDesktop;
rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
rcDesktop.right = rcDesktop.left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
rcDesktop.bottom = rcDesktop.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
MoveWindow(rcDesktop, FALSE);
This code works on multiple monitors, unlike maximizing the window.
No need to worry about making the window topmost, Windows will display it on a dedicated desktop with no other windows present.
You should be able to adapt the example code here to do what you want:
MSDN: Initializing a dialog box

Resources