[MSW] mark wx apps as being DPI aware?

125 views
Skip to first unread message

Vadim Zeitlin

unread,
Mar 12, 2010, 4:10:00 AM3/12/10
to wx-dev
Hello,

I wonder if we shouldn't add a "<dpiAware>true</dpiAware>" to our manifest
or call SetProcessDPIAware() in wxMSW startup code as hopefully wx apps
should indeed be "DPI aware", i.e. work with different/higher than default
DPI. Has anyone already tested doing this by chance? If so, did this result
in any problems?

Thanks,
VZ

Vaclav Slavik

unread,
Mar 12, 2010, 4:19:19 AM3/12/10
to wx-...@googlegroups.com
On Fri, 2010-03-12 at 10:10 +0100, Vadim Zeitlin wrote:
> or call SetProcessDPIAware()

MSDN recommends against this. Plus, it would be the wrong thing to do
when using wx in extensions loaded into host processes (WinSparkle,
plugins, ...).

Vaclav

signature.asc

Vadim Zeitlin

unread,
Mar 12, 2010, 4:45:29 AM3/12/10
to wx-...@googlegroups.com
On Fri, 12 Mar 2010 10:19:19 +0100 Vaclav Slavik <vsl...@fastmail.fm> wrote:

VS> On Fri, 2010-03-12 at 10:10 +0100, Vadim Zeitlin wrote:
VS> > or call SetProcessDPIAware()
VS>
VS> MSDN recommends against this.

It does but I don't understand their explanation (what race condition?) so
I don't know why exactly shouldn't we do this.

VS> Plus, it would be the wrong thing to do when using wx in extensions
VS> loaded into host processes (WinSparkle, plugins, ...).

This is a good point though. However if we call it from IMPLEMENT_APP (but
not IMPLEMENT_APP_NO_MAIN), i.e. from application entry point only, it
should address this problem, shouldn't it?

Regards,
VZ

Vaclav Slavik

unread,
Mar 12, 2010, 6:51:27 AM3/12/10
to wx-...@googlegroups.com
On Fri, 2010-03-12 at 10:45 +0100, Vadim Zeitlin wrote:
> On Fri, 12 Mar 2010 10:19:19 +0100 Vaclav Slavik <vsl...@fastmail.fm> wrote:
>
> VS> On Fri, 2010-03-12 at 10:10 +0100, Vadim Zeitlin wrote:
> VS> > or call SetProcessDPIAware()
> VS>
> VS> MSDN recommends against this.
>
> It does but I don't understand their explanation (what race condition?)

As they say, if something caches the value at startup. "Race condition"
is misnomer.

Anyway, using manifest is the recommended solution, so why not do it?
IOW, what benefit does doing it in code have? I don't see any.

Another advantage to keeping it in the manifest: if the wx-using app
itself is not DPI aware (say, because of some custom drawing code), then
it can be fixed by modifying the manifest, without having to patch wx
source code.

> This is a good point though. However if we call it from IMPLEMENT_APP (but
> not IMPLEMENT_APP_NO_MAIN), i.e. from application entry point only, it
> should address this problem, shouldn't it?

Yes, but see above.

Vaclav

signature.asc

Vadim Zeitlin

unread,
Mar 12, 2010, 6:55:23 AM3/12/10
to wx-...@googlegroups.com
On Fri, 12 Mar 2010 12:51:27 +0100 Vaclav Slavik <vsl...@fastmail.fm> wrote:

VS> Anyway, using manifest is the recommended solution, so why not do it?

Because our manifest is used with very few compilers. In fact I think it's
only used with VC7 as other compilers don't support manifests and later
versions of VC use the manifest generated by the compiler.

VS> Another advantage to keeping it in the manifest: if the wx-using app
VS> itself is not DPI aware (say, because of some custom drawing code), then
VS> it can be fixed by modifying the manifest, without having to patch wx
VS> source code.
VS>
VS> > This is a good point though. However if we call it from IMPLEMENT_APP (but
VS> > not IMPLEMENT_APP_NO_MAIN), i.e. from application entry point only, it
VS> > should address this problem, shouldn't it?
VS>
VS> Yes, but see above.

Presumably we could have some wxApp::MSWDisableDPIAware() or something
like this if the need really arises...

Regards,
VZ

Vaclav Slavik

unread,
Mar 12, 2010, 7:07:12 AM3/12/10
to wx-...@googlegroups.com
On Fri, 2010-03-12 at 12:55 +0100, Vadim Zeitlin wrote:
> Because our manifest is used with very few compilers.

Are you sure? An executable *must* have a manifest to be able to use
Common Controls 6...

> other compilers don't support manifests

It's just a resource item, any resource compiler supports them, VC just
adds friendlier UI for them.

Vaclav

signature.asc

Vadim Zeitlin

unread,
Mar 12, 2010, 7:18:45 AM3/12/10
to wx-...@googlegroups.com
On Fri, 12 Mar 2010 13:07:12 +0100 Vaclav Slavik <vsl...@fastmail.fm> wrote:

VS> On Fri, 2010-03-12 at 12:55 +0100, Vadim Zeitlin wrote:
VS> > Because our manifest is used with very few compilers.
VS>
VS> Are you sure?

I'm sure that we don't use our manifest with VC8+ as the compiler
generates one itself. But while in VC10 you can check the "DPI aware"
option in the manifest options page, you don't have it in VC[89]. And even
with VC10 you need to know about it and remember to do it. Which is an
extra burden I'd like to avoid.

VS> > other compilers don't support manifests
VS>
VS> It's just a resource item, any resource compiler supports them, VC just
VS> adds friendlier UI for them.

Yes, you're right, the other compilers should be fine. But the problem
still remains for VC8+... I guess the official way to fix it for VC10 would
be to provide a .props file for wx which would define this option. But I
don't know how does it work exactly and this still wouldn't work for 8 and
9. So you probably start seeing why I prefer to just call a function...

Regards,
VZ

Peter Cawley

unread,
Mar 12, 2010, 7:39:28 AM3/12/10
to wx-...@googlegroups.com
On Fri, Mar 12, 2010 at 12:07 PM, Vaclav Slavik <vsl...@fastmail.fm> wrote:
> On Fri, 2010-03-12 at 12:55 +0100, Vadim Zeitlin wrote:
>>  Because our manifest is used with very few compilers.
>
> Are you sure? An executable *must* have a manifest to be able to use
> Common Controls 6...

VC8 and VC9 get the appropriate code in their manifest files due to
this section of wx/defs.h:
#if (!defined wxUSE_NO_MANIFEST || wxUSE_NO_MANIFEST == 0 ) && \
( defined _MSC_FULL_VER && _MSC_FULL_VER >= 140040130 )

#define WX_CC_MANIFEST(cpu) \
"/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' \
processorArchitecture='"cpu"' \
publicKeyToken='6595b64144ccf1df' \
language='*'\""

#if defined _M_IX86
#pragma comment(linker, WX_CC_MANIFEST("x86"))
#elif defined _M_X64
#pragma comment(linker, WX_CC_MANIFEST("amd64"))
#elif defined _M_IA64
#pragma comment(linker, WX_CC_MANIFEST("ia64"))
#else
#pragma comment(linker, WX_CC_MANIFEST("*"))
#endif

#endif /* !wxUSE_NO_MANIFEST && _MSC_FULL_VER >= 140040130 */

Other compilers get the entire manifest from this bit in wx.rc:
// Visual Studio 2005 generates the manifest automatically and so we
// shouldn't include it in the resources manually:
#if !defined(WX_MSC_FULL_VER) || WX_MSC_FULL_VER < 140040130

// see "about isolated applications" topic in MSDN
#ifdef ISOLATION_AWARE_ENABLED
#define wxMANIFEST_ID 2
#else
#define wxMANIFEST_ID 1
#endif

#if defined(WX_CPU_AMD64)
wxMANIFEST_ID 24 "wx/msw/amd64.manifest"
#elif defined(WX_CPU_IA64)
wxMANIFEST_ID 24 "wx/msw/ia64.manifest"
#elif defined(WX_CPU_X86)
wxMANIFEST_ID 24 "wx/msw/wx.manifest"
#endif

#endif // !defined(WX_MSC_FULL_VER) || WX_MSC_FULL_VER < 140040130

VC9 (and maybe VC8, but I don't have a copy on-hand) has a project
property "Additional Manifest Files" for listing "additional user
manifest fragment files to merge into the manifest", which looks like
a good way to add stuff to the compiler-generated manifest, but it
seems that there is no way to automatically set that setting from a
#pragma or similar directive.

Vaclav Slavik

unread,
Mar 12, 2010, 7:56:14 AM3/12/10
to wx-...@googlegroups.com
On Fri, 2010-03-12 at 13:18 +0100, Vadim Zeitlin wrote:
> So you probably start seeing why I prefer to just call a function...

Yes.

Vaclav

signature.asc

Vaclav Slavik

unread,
Apr 15, 2010, 8:48:35 AM4/15/10
to wx-...@googlegroups.com
On Fri, 2010-03-12 at 10:10 +0100, Vadim Zeitlin wrote:
> should indeed be "DPI aware", i.e. work with different/higher than
> default DPI. Has anyone already tested doing this by chance? If so,
> did this result in any problems?

To (finally) answer your question, Poedit seems to work just fine when
compiled as "DPI aware".

Vaclav

signature.asc

David Swofford

unread,
Jan 10, 2014, 2:16:05 PM1/10/14
to wx-...@googlegroups.com
Sorry to dredge up this old thread, but there is indeed a problem with calling SetProcessDPIAware() from wxWidgets.

I think the scenario tested by Vaclav (Poedit) involves an application that uses wx for its GUI interface.  My own app use the native WinAPI and is not DPI aware.  (FWIW, I was not aware that it wasn't DPI aware until I tried to update to version 0.4 of Vaclav's winSparkle plug-in and discovered that my own interface was completely borked after winSparkle had put up a dialog box.)

I eventually tracked the problem down to the wxSetProcessDPIAware() call issued from main.cpp of wxWidgets (wish I could have those 2 days back :-) ).  The problem, as I understand it, is that on MSW, once SetProcessDPIAware is called, it changes the setting for the entire process, and any subsequent calls have--as documented--no effect.  It doesn't matter that winSparkle was running on a separate thread, so the following comment at line 406 of main.cpp:

    // Note that we intentionally do it here and not in wxApp, so that it
    // doesn't happen if wx code is hosted in another app (e.g. a plugin).

… seems misleading to me.  If wx code is hosted in another app and it calls SetProcessDPIAware, then Windows assumes that the entire app is DPI-aware from that point on.  This is exactly the scenario Vaclav was worried about in his initial reply to Vadim's inquiry about whether it was a good idea.

For now, I've just built a version of wx that doesn't break my own program, but I wasn't sure whether to post this as a bug report or not, as you have already discussed it and accepted the change.  But my own opinion is that you should remove the wxSetProcessDPIAware  call so that it doesn't cause the kinds of problems for others that it did for me.  (And, I acknowledge that there might have been a way to avoid modifying wx by bypassing the version of wxEntry that calls wxSetProcessDPIAware, but I don't understand either winSparkle or wxWidgets to easily figure out whether this is the case.)

Dave

David Connet

unread,
Jan 11, 2014, 12:18:02 PM1/11/14
to wx-...@googlegroups.com
Out of curiosity, I started reading some of this (I've kind of ignored
DPI-awareness so far). As of Win8.1, SetProcessDPIAware is superseded by
SetProcessDPIAwareness (allows setting system-aware or per-monitor-aware)

Also, the tutorial (the link in main.cpp) states that your application
manifest takes precedence (and SetProcessDPIAwareness will fail). So it
would seem that you could specifically mark your app as not aware in the
manifest and not need a special wx build.

As an aside, the MSDN-SetProcessDPIAware page has some interesting notes
(copied from
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633543%28v=vs.85%29.aspx):
- SetProcessDPIAware is available for use in the operating systems
specified in the Requirements section. It may be altered or unavailable
in subsequent versions. Instead, use SetProcessDPIAwareness.
- Note SetProcessDPIAware is subject to a possible race condition if a
DLL caches dpi settings during initialization. For this reason, it is
recommended that dpi-aware be set through the application (.exe)
manifest rather than by calling SetProcessDPIAware.
- DLLs should accept the dpi setting of the host process rather than
call SetProcessDPIAware themselves. To be set properly, dpiAware should
be specified as part of the application (.exe) manifest.

Dave


On 1/10/2014 11:16 AM, David Swofford wrote:
> Sorry to dredge up this old thread, but there is indeed a problem with
> calling SetProcessDPIAware() from wxWidgets.
>
> I think the scenario tested by Vaclav (Poedit) involves an application
> that uses wx for its GUI interface. My own app use the native WinAPI
> and is not DPI aware. (FWIW, I was not aware that it wasn't DPI aware
> until I tried to update to version 0.4 of Vaclav's winSparkle plug-in
> and discovered that my own interface was completely borked after
> winSparkle had put up a dialog box.)
>
> I eventually tracked the problem down to the wxSetProcessDPIAware() call
> issued from main.cpp of wxWidgets (wish I could have those 2 days back
> :-) ). The problem, as I understand it, is that on MSW, once
> SetProcessDPIAware is called, it changes the setting for the entire
> process, and any subsequent calls have--as documented--no effect. It
> doesn't matter that winSparkle was running on a separate thread, so the
> following comment at line 406 of main.cpp:
>
> // Note that we intentionally do it here and not in wxApp, so that it
> // doesn't happen if wx code is hosted in another app (e.g. a plugin).
>
> � seems misleading to me. If wx code is hosted in another app and it
> calls SetProcessDPIAware, then Windows assumes that the entire app is
> DPI-aware from that point on. This is exactly the scenario Vaclav was
> worried about in his initial reply to Vadim's inquiry about whether it
> was a good idea.
>
> For now, I've just built a version of wx that doesn't break my own
> program, but I wasn't sure whether to post this as a bug report or not,
> as you have already discussed it and accepted the change. But my own
> opinion is that you should remove the wxSetProcessDPIAware call so that
> it doesn't cause the kinds of problems for others that it did for me.
> (And, I acknowledge that there might have been a way to avoid
> modifying wx by bypassing the version of wxEntry that calls
> wxSetProcessDPIAware, but I don't understand either winSparkle or
> wxWidgets to easily figure out whether this is the case.)
>
> Dave
>
> On Thursday, April 15, 2010 8:48:35 AM UTC-4, V�clav Slav�k wrote:
>
> On Fri, 2010-03-12 at 10:10 +0100, Vadim Zeitlin wrote:
> > should indeed be "DPI aware", i.e. work with different/higher than
> > default DPI. Has anyone already tested doing this by chance? If so,
> > did this result in any problems?
>
> To (finally) answer your question, Poedit seems to work just fine when
> compiled as "DPI aware".
>
> Vaclav
>
> --
> To unsubscribe, send email to wx-dev+un...@googlegroups.com
> or visit http://groups.google.com/group/wx-dev
>

Vadim Zeitlin

unread,
Jan 12, 2014, 9:22:07 AM1/12/14
to wx-...@googlegroups.com
On Fri, 10 Jan 2014 11:16:05 -0800 (PST) David Swofford wrote:

DS> Sorry to dredge up this old thread, but there is indeed a problem with
DS> calling SetProcessDPIAware() from wxWidgets.

Thanks for reporting it!

DS> I think the scenario tested by Vaclav (Poedit) involves an application that
DS> uses wx for its GUI interface. My own app use the native WinAPI and is not
DS> DPI aware. (FWIW, I was not aware that it wasn't DPI aware until I tried
DS> to update to version 0.4 of Vaclav's winSparkle plug-in and discovered that
DS> my own interface was completely borked after winSparkle had put up a dialog
DS> box.)

Not nice :-(

DS> I eventually tracked the problem down to the wxSetProcessDPIAware() call
DS> issued from main.cpp of wxWidgets (wish I could have those 2 days back :-)
DS> ). The problem, as I understand it, is that on MSW, once
DS> SetProcessDPIAware is called, it changes the setting for the entire
DS> process, and any subsequent calls have--as documented--no effect. It
DS> doesn't matter that winSparkle was running on a separate thread, so the
DS> following comment at line 406 of main.cpp:
DS>
DS> // Note that we intentionally do it here and not in wxApp, so that it
DS> // doesn't happen if wx code is hosted in another app (e.g. a plugin).
DS>
DS> … seems misleading to me.

It is indeed not totally correct. The idea was that plugins usually do not
call wxEntry(), but as the example of WinSparkle shows, this is not always
the case.

DS> For now, I've just built a version of wx that doesn't break my own program,
DS> but I wasn't sure whether to post this as a bug report or not, as you have
DS> already discussed it and accepted the change. But my own opinion is that
DS> you should remove the wxSetProcessDPIAware call so that it doesn't cause
DS> the kinds of problems for others that it did for me. (And, I acknowledge
DS> that there might have been a way to avoid modifying wx by bypassing the
DS> version of wxEntry that calls wxSetProcessDPIAware, but I don't understand
DS> either winSparkle or wxWidgets to easily figure out whether this is the
DS> case.)

The trouble is that I don't see how to fix it neither. If we moved
wxSetProcessDPIAware() call to WinMain() (inside wxIMPLEMENT_WXWIN_MAIN
macro), then it would work for WinSparkle but wouldn't work for any
application using wxWidgets normally but defining its own entry function.
It looks like we need some way to tell wxEntry() to avoid calling
wxSetProcessDPIAware(). And in any case there doesn't seem to be any way to
show DPI aware dialogs from WinSparkle when the main application uses non
DPI-aware GUI toolkit (which should hopefully be rare nowadays...).

Vaclav, do you have any better ideas?
VZ

Václav Slavík

unread,
Jan 12, 2014, 1:47:52 PM1/12/14
to wx-...@googlegroups.com

On 12 Jan 2014, at 15:22, Vadim Zeitlin <va...@wxwidgets.org> wrote:
> It is indeed not totally correct. The idea was that plugins usually do not
> call wxEntry(), but as the example of WinSparkle shows, this is not always
> the case.

I wouldn't worry about WinSparkle too much, it really is a very special case.

> The trouble is that I don't see how to fix it neither. If we moved
> wxSetProcessDPIAware() call to WinMain() (inside wxIMPLEMENT_WXWIN_MAIN
> macro), then it would work for WinSparkle but wouldn't work for any
> application using wxWidgets normally but defining its own entry function.
> It looks like we need some way to tell wxEntry() to avoid calling
> wxSetProcessDPIAware(). And in any case there doesn't seem to be any way to
> show DPI aware dialogs from WinSparkle when the main application uses non
> DPI-aware GUI toolkit (which should hopefully be rare nowadays...).
>
> Vaclav, do you have any better ideas?

What about doing it the apparently recommended way, i.e. using the manifest instead of this call? IOW, let the (wx) user use proper manifest content and e.g. put it into our example/builtin manifests as well, as previously mentioned?

Vaclav

Vadim Zeitlin

unread,
Jan 12, 2014, 2:14:25 PM1/12/14
to wx-...@googlegroups.com
On Sun, 12 Jan 2014 19:47:52 +0100 Václav Slavík wrote:

VS> On 12 Jan 2014, at 15:22, Vadim Zeitlin <va...@wxwidgets.org> wrote:
VS> > It is indeed not totally correct. The idea was that plugins usually do not
VS> > call wxEntry(), but as the example of WinSparkle shows, this is not always
VS> > the case.
VS>
VS> I wouldn't worry about WinSparkle too much, it really is a very special
VS> case.

Isn't this what the dll sample does too though? And people are going to
copy it...

VS> What about doing it the apparently recommended way, i.e. using the
VS> manifest instead of this call? IOW, let the (wx) user use proper
VS> manifest content and e.g. put it into our example/builtin manifests as
VS> well, as previously mentioned?

Yes, this looks like a good idea. The example given in Microsoft
documentation is

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
...
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
...
</assembly>

so it looks that we just need to add asmv3 namespace and the snippet in the
middle to all our include/wx/msw/*.manifest files.

Needless to say, if somebody could do it and test the results, it would be
welcome.

Regards,
VZ
Reply all
Reply to author
Forward
0 new messages