How do I trigger the WinForms DpiChanged event? - winforms

(No, I can't upgrade this codebase to .NET Core or newer yet.)
I have an app that's primarily Windows Forms, and partially WPF. When font size changes at runtime, WPF reacts correctly. Windows Forms, instead, doesn't even seem to realize anything has changed unless I restart. For example, the Control.DeviceDpi property (which wasn't even introduced until 4.7) shows the value that was accurate at startup, not the current one.
My app.manifest has:
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
</asmv3:windowsSettings>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<dpiAwareness>PerMonitorV2, PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
My app.config has:
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
But 4.7 did introduce a Control.DpiChanged event, only it never seems to fire.
Yet, if I override WndProc and listen to WM_DPICHANGED, that does fire. This code seems to suggest that the event should fire.
Apparently, it doesn't because this code conditionally turns it off. But I'm not sure which portion I don't qualify for. (I'm on Windows 10 21H1, so more recent than RS2.)

Related

Multi-Touch in Silverlight - doesn't recognizes the touch point

I'm having this Silverlight project which I'm working on. I'm currently trying to add Multi-Touch functionality to it, and I'm having difficulties.
It seems like the system doesn't recognizes the touch point immediately when I'm touching down on a point, but only when I'm releasing it.
This affects the map control I have - its not supporting pan, and the zoom doesn't work properly.
I suspect that this might be because of a Context Menu on Right Click that I use (to be specific, it's Telerik's RadContextMenu).
Can anybody tell me what is wrong or what is interfering the Multi-Touch behavior?
Maybe you're setting the windowless param to:
<param name="windowless" value="true" />
Apparently multi-touch functionality doesn't work when using this setting, along with other things:
http://msdn.microsoft.com/en-us/library/cc838156%28v=vs.95%29.aspx
Sadly, it looks like all of the official documentations doesn't mention the multi-touch functionality limitations.

EnableCacheVisualization not working

I know I've made this work before but now I don't know what I am doing wrong.
I create a new hosted Silverlight application.
I added a button object on the MainPage.xaml setting CacheMode="BitmapCache"
I edited my default.apsx file to add the following lines to the silverlight object tag :
<param name="EnableCacheVisualization" value="true" />
<param name="EnableGPUAcceleration" value="true" />
<param name="EnableFrameRateCounter" value="true" />
But I cannot see neither the FrameRateCounter or the CacheVisualization... What am I doing wrong here.
Thanks
Make sure the Web Application is set as the startup project and that the Default.aspx is its start page. Also check that your app is compiling without error in some cases VS will just continue and run the original XAP when compiling a new one fails.
Maybe you have some startup code somewhere that sets those options back to False?
Try adding a button which shows the value of System.Windows.Interop.Settings.EnableCacheVisualization.
Otherwise, can you post your html page source?
Thank you both for your help, but I got my answer... It is really stupid, but those functions are not working with "Windows Server 2008"!!! I changed my workstation recently and wasn't aware of that.
got my answer here : http://msdn.microsoft.com/en-us/library/dd833062(v=VS.95).aspx
Hardware acceleration is only enabled on Windows Vista, Windows 7, and
Windows XP. On Windows XP NVidia, ATI, Intel cards with a driver date
post November 2004 is required for hardware acceleration.

Programming In C + Win API: How To Get Windows 7 Look For Controls?

I am programming strictly in C and WinAPI, no C++ or C#. I am a beginner and just learning to draw controls etc. The thing is that when I create Windows or other controls like Command Buttons, they have Windows Native look. Take a look at this:
But in Windows 7, the command buttons look like this:
Now, how do I get command buttons in my program to look like that. Is it even possible?
I am following this tutorial, for reference: http://zetcode.com/gui/winapi/
Thanks.
That's how the controls looked back in the 1990s, before themes (visual styles) were invented. As you've noticed, modern buttons are now painted all fancy-pants with gradients and throbbing and all that. But for backwards-compatibility reasons, you have to specifically request that your controls get that treatment, or they'll fall back to the legacy style.
You do that by specifying a manifest. You can either add one in plain text format to your application's root directory, or you can have Visual Studio (2005 and later) automatically embed one in your EXE.
The second route is the way I'd go. Add the following code to your stdafx.h file to inform the compiler that you want it to add the manifest automatically upon building your project:
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
This MSDN article has more information on visual styles than you could ever want.
And if you really want your application to look native, you need to change the background brush used for the main window. By default, it's set to use the same color as a textbox's background (white).
You want to use the color used to paint 3D controls, instead. Modify the hbrBackground member of your WNDCLASS (or WNDCLASSEX) structure as shown here:
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
Why do you have to add 1? For backwards-compatibility reasons, again. The details are boring. :-)
You enable visual styles for your app by providing an XML manifest, either as a separate file or as an embedded resource. See Enabling Visual Styles for details.
You probably remember when Windows XP arrived with that fresh new look, and you could revert it back to Windows 95/2000 classic appearance, or you could change the color theme. That was called visual styles, which brought to Windows a better theming support.
Visual styles remained as a feature since then. Windows Vista and 7 introduced Aero, but they still allowed using the classic theme. Windows 8 has removed both Aero and the classic theme, and added the Metro theme. High-contrast themes are now part of visual styles and do not have the classic appearance anymore.
Thus, a classic themed application in Windows 7 when it was expected an Aero style, is an issue with the visual style of the application. I'm not sure why but Microsoft did not leave the old classic theme optional while migrating the API to the new look.
So, how do I apply the modern style?
Either way this MSDN article explains how to enable visual styles for your application. I have seen people saying that enabling Unicode (defining UNICODE) would make it, but it is not required. Basically, you just need to write a manifest file specifying version 6 of the common controls DLL as requirement, then embed it as a resource or place under appname.exe.manifest in the executable's directory. A sample manifest would look like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*"
name="CompanyName.ProductName.YourApplication" type="win32"/>
<description>Your application description here.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Windows.Common-Controls"
version="6.0.0.0" type="win32" processorArchitecture="*"
publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
</assembly>
If you go for the embed option, don't forget to have winuser.h included in your resource file. You may also want to initialize the common controls DLL in your WinMain, according to this MinGW guide:
I’ve seen this step missed in some examples, and it can cause some odd behaviors under certain operating system versions and certain conditions, such as buttons being invisible, or dialogs failing to be created.
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);

WPF Resource Refreshing problem

I using multilanguage solution from this thread Multilanguage in WPF
But i have problem with automaticaly Resource refreshing after language was changed.
Old strings stay in old language, new is traversed propertly.
What is easiest solution to solve this problem, for example refresh all resources in application?
I've worked with localization as well. The problem with it is the changes you make in culture info while your app is running, isn't going to be shown in the UI. The values for the controls do change, but the change isn't notified to the ui of the control. For as far as i've been googling this, i haven't found a reasonable solution for offline applications. Even InitializeComponents isn't doing the trick.
The only solution, allthough i don't like that one very much, is to change the culture, then start up a batch which will close and restart the app with the chosen cultureinfo.
The reason why i don't like this is because you rely on an external file (the batch) and not all applications can just be restarted like that. But it might do the trick.
The easiest solution I've found is to simply reopen the window - if you work with MVVM all the state (or the important state anyway) is preserved in the ViewModel(s) and only the view is refreshed.
I haven't used the extension you linked to, but any of these more advanced systems should handle refresh automatically. In my case, I just used {x:Static res:ResourceName} references to the resources, and refreshed the view when the language changed. Granted, I don't allow changing the language in the more complicated screens... :)

Hosting Windows Shell Explorer in my WPF App

Is it possible to embed the Windows Explorer file/folder browser view in a WPF or a WinForms window?
I basically want to host the file/folder browser as part of my app window. I don't want to re-implement what the shell provides, especially the shell extensions such as TortoiseSVN.
As far as I know, there isn't any File/Folder browser control out of the box in Windows Forms nor WPF.
However there are commercial third-party controls that offer a Windows Explorer-like interface to browse files and folders on disk. Take a look at these products from LogicNP:
FileView Control
FolderView Control
Alternatively, you could host the Windows Forms WebBrowser control in WPF and use it to browse the filesystem, since it is integrated with the Windows shell.
In XAML you could do something like this:
<Window x:Class="Samples.FilesystemBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="Filesystem Browser">
<StackPanel>
<WindowsFormsHost>
<wf:WebBrowser Url="C:\" />
</WindowsFormsHost>
</StackPanel>
</Window>
Note, that with .NET 3.5 SP1 Microsoft added a native WPF WebBrowser control, so you can optionally use that instead:
<Window x:Class="Samples.FilesystemBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Filesystem Browser">
<StackPanel>
<WebBrowser Source="C:\" />
</StackPanel>
</Window>
Windows Vista’s Shell introduced a new control which implements the IExplorerBrowser interface; this is the recommended method of hosting a Windows Shell filesystem view within your application. Developers building applications using .NET can use the wrapped version of the ExplorerBrowser control available in the Windows API CodePack for .NET.
Please note that this interface is only available on Windows Vista and later. If your application needs to run on earlier Windows versions, you will need to fallback to the old WebOC implementation on those platforms.
http://msdn.microsoft.com/en-us/library/bb761909(VS.85).aspx
http://code.msdn.microsoft.com/WindowsAPICodePack
This is recommended over hosting the web browser control due to a Win7 issue described here: http://blogs.msdn.com/ieinternals/archive/2009/12/30/Windows-7-Web-Browser-Control-will-not-browse-file-system.aspx
The approach in my answer isn't one I would necessarily recommend, as it is basically a huge hack. However, it is possible to 'host' pretty much any Windows application inside another. Caveats:
This is a big fat hack
I'm not sure at all how well it plays with the various security features that are e.g. in Vista
You'll be working with low-level and sometimes underdocumented APIs the whole time, and doing things that are not what the original designers anticipated.
I don't know the various APIs well enough to tell you exactly what to do, so this is a very rough sketch...
The basic approach would be to:
Start up a new explorer.exe process
Get its HWnd
Using p/invoke calls into various windows APIs (mostly shell32.dll), re-parent it into a NativeWindow or UserControl of your own.
You can then replace its WndProc message handler with your own, subclassing it to inject your own application-specific behaviors. (C++ example; stackoverflow question WRT calling the old/default WndProc; googling will produce a lot of answers. I've done this before in C# and (ick) VBA) This will let you replace various UI behaviors with your own, albiet at a very low level. (It's dependent on how exactly explorer is implemented: higher-level things like menu clicks can get their own message and so be easier to handle; but other aspects of explorer's behavior you might only get the raw mouse messages.)
You'll want Spy++ in order to figure out what messages happen when.
Yes, this is a great way to build lots of very ugly and fragile code, but it's (a) sometimes the only way to get things working right; and (b) great for learning what's going on under the hood of Windows.Forms / MFC / etc.
I've written an open-source library for embedding windows explorer in .NET applications. You can take a look at http://gong-shell.sourceforge.net/
It exposes WinForms controls, as well as providing a .NET language interface to the Windows Shell. It's licenced under the GPL, so using it in a similarly licensed application is free, however if you want to use it in a commercial application drop me an email and I'm sure we can work something out!

Resources