In a dialog I have an options button. But I don't want it to be visible all the time, only when the cursor is over the dialog, and have a nice fade in/out.
I've tried several things to make the CButton transparent to it fade in/out, but not successful.
For example, I have tried SetLayeredWindowAttributes and UpdateLayeredWindow but I can't get them to work, probably since the CButton is a child.
Any tips how to set the transparency of a CButton?
I have tried SetLayeredWindowAttributes and UpdateLayeredWindow but I
can't get them to work, probably since the CButton is a child.
Layered child windows are supported since Windows 8:
In order to use layered child windows, the application has to declare
itself Windows 8-aware in the manifest.
To do this, add a manifest section like this to your application through project properties > Manifest Tool > Input and output > Additional manifest files:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>
You propably want to declare support for other Windows versions too.
With the manifest in place, we can now turn a button into a layered window and set the desired transparency (alpha) level:
if( CWnd* pButton = GetDlgItem( IDC_OPTIONS ) )
{
pButton->ModifyStyleEx( 0, WS_EX_LAYERED );
pButton->SetLayeredWindowAttributes( 0, 96, LWA_ALPHA );
}
Adding this code in my overridden CDialog::OnInitDialog(), I got the following result under Win 10:
Note that the button looks like disabled, but this is just coincidence.
To make the button completely opaque again, remove the WS_EX_LAYERED bit:
pButton->ModifyStyleEx( WS_EX_LAYERED, 0 );
If you need to support older OS than Windows 8, you would have to use more involved techniques to achieve the same effect. Just some ideas that come to mind:
Create an owner-drawn or custom-drawn button to have complete control over the appearance of the button, with the ability to fake transparency.
Create an initially hidden button. Create a snapshot of the button as it would look like when visible by sending it a WM_PRINTCLIENT message. Draw the snapshot in place of the actual button with the desired transparency. Show the button once you have reached an alpha value of 255. This is similar to how AnimateWindow() works.
Related
I want to create a window with the following properties:
Thick border ("double border" as described in MSDN)
Not resizable
Icon in the title
Close button in the title
It sounds so simple and we can find this kind of windows everywhere in Windows. But as soon as I disable ability to resize my window I also lose the thick border. Here is the illustration of my problem:
The height of my test window's caption bar is slightly less than that of a Shell property dialog, but I would like it to be the same height.
I have tried to use WinSpy and copy all styles from Explorer's window to mine, but this did not help.
I don't know what's going on under the hood, but I found two solutions:
Switch to the newer Platform Toolset (which means drop support of Windows XP)
Disable resizing by writing custom WM_NCHITTEST handler
The second option is quite simple and I do not want drop Windows XP support for a silly reason. Job is done:
LRESULT CListEditorDlg::OnNcHitTest(CPoint point)
{
LRESULT retVal = CDialog::OnNcHitTest(point);
switch (retVal)
{
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
retVal = HTBORDER;
}
return retVal;
}
The Android device I am using does not have any touchscreen. All it has is a touch pad that can generate KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, etc. However, I am not sure if my Xamarin app is responding to these events. Is there any setting that one can enable to identify current selection among a group of controls.
When I go the device's home screen and use the DPad keys to move around, I see a thin square around the icon that is currently selected. I am hoping there is a similar setting within Xamarin app to turn on this behavior. Regards.
You can simply use CurrentFocus of the activity to get the current focused control. But first of all, when control is focused, it will be highlighted, usually we can modify the control's background to a drawable state list resource for example:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/button_focused" /> <!-- focused -->
<item android:state_hovered="true"
android:drawable="#drawable/button_focused" /> <!-- hovered -->
<item android:drawable="#drawable/button_normal" /> <!-- default -->
</selector>
This visual behavior is for a button to indicate that user has navigated to the control.
When I go the device's home screen and use the DPad keys to move around, I see a thin square around the icon that is currently selected. I am hoping there is a similar setting within Xamarin app to turn on this behavior.
So this thin square can be the designed background for focused state.
I don't know if there is any setting for it, but if you want to do it in code behind to indicate which control is currently focused, as I said at the beginning, you can use CurrentFocus of the activity. For example:
public override bool DispatchKeyEvent(KeyEvent e)
{
if (e.Action == KeyEventActions.Up)
{
if (e.KeyCode == Keycode.DpadDown || e.KeyCode == Keycode.DpadUp
|| e.KeyCode == Keycode.DpadLeft || e.KeyCode == Keycode.DpadRight)
{
var view = this.CurrentFocus;
view.SetBackgroundDrawable(...);
}
}
return base.DispatchKeyEvent(e);
}
Forget to say, if you want to do it in code behind, don't forget to change the background back to its old state when a new control is focused. Emmm, seems the state list resource is the best choice here.
I noticed that when I press PrntScrn while an IRM-protected email is open in Outlook 2013, the email's window is replaced with a solid black rectangle when I paste the screenshot into mspaint.
I'm not aware of any "Screenshot" window message being sent to windows, so how is this feature implemented? I never see any black pixels on my monitors so I don't think it has a keyboard hook to listen for PrntScrn and then paints the window black.
Using the WinAPI function SetWindowDisplayAffinity with the WDA_MONITOR affinity before showing the window.
SetWindowDisplayAffinity(hwnd, WDA_MONITOR); // Should, of course, check return value
ShowWindow(hwnd, SW_NORMAL);
Note this only works in Windows 7 and higher, only for a certain set of "public operating system features and APIs", and only when the window is DWM-composited. See the two paragraphs in the Remarks section of the linked documentation.
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'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