changeset 188:03f179597782

Make WinXP themes work with windows resources
author Frank Benoit <benoit@tionex.de>
date Sat, 15 Mar 2008 00:33:19 +0100
parents bcdc37794717
children f804bcfb9e49
files README.txt dwt.exe.manifest dwt.rc dwt.res dwt/internal/win32/OS.d
diffstat 5 files changed, 93 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/README.txt	Mon Mar 10 17:08:22 2008 +0100
+++ b/README.txt	Sat Mar 15 00:33:19 2008 +0100
@@ -40,6 +40,27 @@
 -L/SUBSYSTEM:windows:5
 Without this option, DWT renderes some controls not correctly. Eg. table headers are not shown.
 
+
+WinXP Theming and Controls
+==========================
+With WinXP it is required to make windows use a manifest.
+There are several ways to make this manifest available.
+1.) Place the manifest file in the same directory where the .exe is.
+    E.g.
+        application.exe
+        application.exe.manifest
+2.) Link the content of the manifest to the application as a windows resource.
+3.) Have another program that uses resource injection to put the manifest into the application
+4.) Let the application write the manifest to a an external file and load it.
+    This had problems in the past, some applications on some machines did not load images.
+
+1. .. 3.) Seems to work reliable.
+
+ * Using 2.
+   compile the dwt.rc/dwt.exe.manifest files with rcc.exe from the digitalmars to create the dwt.res.
+     rcc dwt.rc
+   link the resulting dwt.res with the -L/rc:dwt.res
+
 Changes/Additions to SWT
 ========================
   o MessageBox can be instantiated without parent. Use the Ctor "this( int style )",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt.exe.manifest	Sat Mar 15 00:33:19 2008 +0100
@@ -0,0 +1,1 @@
+<?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="X86" name="DWT" type="win32"/><description>D Widget Toolkit</description><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt.rc	Sat Mar 15 00:33:19 2008 +0100
@@ -0,0 +1,3 @@
+ 
+2 24 "dwt.exe.manifest"
+
Binary file dwt.res has changed
--- a/dwt/internal/win32/OS.d	Mon Mar 10 17:08:22 2008 +0100
+++ b/dwt/internal/win32/OS.d	Sat Mar 15 00:33:19 2008 +0100
@@ -19,6 +19,7 @@
 import dwt.internal.C;
 import dwt.internal.Library;
 import tango.sys.SharedLib : SharedLib;
+import tango.sys.Common : SysError;
 static import tango.stdc.stdlib;
 
 import tango.stdc.string : memset;
@@ -167,9 +168,11 @@
 
     /* Forward references */
     public static const int HEAP_ZERO_MEMORY = 0x8;
-    public static const int ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x00000008;
-    public static const int ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x00000010;
-    public static const int MANIFEST_RESOURCE_ID = 2;
+    public static const int ACTCTX_FLAG_RESOURCE_NAME_VALID    = 0x00000008;
+    public static const int ACTCTX_FLAG_SET_PROCESS_DEFAULT    = 0x00000010;
+    public static const int ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x00000020;
+    public static const int ACTCTX_FLAG_OVERRIDEMANIFEST_VALID = 0x00000100;
+    public static const TCHAR* MANIFEST_RESOURCE_ID = cast(TCHAR*)2;
     public static const int SM_DBCSENABLED = 0x2A;
     public static const int SM_IMMENABLED = 0x52;
     public static const int LANG_KOREAN = 0x12;
@@ -248,6 +251,16 @@
         WIN32_MINOR = info.dwMinorVersion;
         WIN32_VERSION = VERSION (WIN32_MAJOR, WIN32_MINOR);
 
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            loadLib( Symbols_Kernel32, `Kernel32.dll` );
+        }
+
+        //PORTING_CHANGE: made by version
+        //IsUnicode = !IsWin32s && !IsWin95;
+
+        /* Load the manifest to force the XP Theme */
+        enableVisualStyles();
+
         // when to load uxtheme
         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
             loadLib( Symbols_UxTheme, `UxTheme.dll` );
@@ -261,16 +274,6 @@
         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 0)) {
             loadLib( Symbols_Imm32, `Imm32.dll` );
         }
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
-            loadLib( Symbols_Kernel32, `Kernel32.dll` );
-        }
-
-        //PORTING_CHANGE: made by version
-        //IsUnicode = !IsWin32s && !IsWin95;
-
-        /* Load the manifest to force the XP Theme */
-        
-        enableVisualStyles();
 
         /* Make the process DPI aware for Windows Vista */
         if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) OS.SetProcessDPIAware ();
@@ -346,95 +349,66 @@
         SHELL32_MINOR = dvi.dwMinorVersion;
         SHELL32_VERSION = VERSION (SHELL32_MAJOR, SHELL32_MINOR);
     }
-    
+
     /**************************************************************************
-    
+
     **************************************************************************/
-    
-    public static void enableVisualStyles()
-    {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
-            const char[] manifest = 
-            `<?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="X86" 
-                    name="dwt" 
-                    type="win32"/>
-                <description>D Widget Toolkit</description>
-                <dependency>
-                    <dependentAssembly>
-                        <assemblyIdentity type="win32" 
-                            name="Microsoft.Windows.Common-Controls" 
-                            version="6.0.0.0" processorArchitecture="X86" 
-                            publicKeyToken="6595b64144ccf1df" 
-                            language="*"/>
-                    </dependentAssembly>
-                </dependency>
-            </assembly>`;
-
-            scope temp = new tango.io.TempFile.TempFile(tango.io.TempFile.TempFile.Permanent);
-            temp.write(manifest);
-            temp.detach();
-
-            ACTCTX actctx;
-            actctx.cbSize = actctx.sizeof;
-            actctx.dwFlags = 0;
-            actctx.lpSource = StrToTCHARz( 0, temp.toString );
-
-            // Create the activation context
-            HANDLE hActCtx = OS.CreateActCtx(&actctx);
-
-            // Did we fail creating the activation context?
-            if (hActCtx is INVALID_HANDLE_VALUE){
-                Trace.formatln("The Activation Context could not be created");
-            } else {
-                // Activate the context and make use of it
-                ULONG_PTR ulpActivationCookie;
-                if (!OS.ActivateActCtx(hActCtx, &ulpActivationCookie)){
-                    Trace.formatln("The Activation Context failed to load");
-                }
+
+    public static void enableVisualStyles() {
+        void printError( char[] msg ){
+            char[] winMsg = SysError.lastMsg();
+            char[2000] buf;
+            Trace.formatln("{}: {}", msg, CodePage.from( winMsg, buf ) );
+        }
+        TCHAR[] buffer = new TCHAR[ MAX_PATH ];
+        buffer[] = 0;
+        HANDLE hModule = OS.GetLibraryHandle ();
+        while (OS.GetModuleFileName (hModule, buffer.ptr, buffer.length ) is buffer.length ) {
+            buffer.length = buffer.length + MAX_PATH;
+            buffer[] = 0;
+        }
+        auto hHeap = OS.GetProcessHeap ();
+        int byteCount = buffer.length * TCHAR.sizeof;
+        TCHAR* pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+
+        ACTCTX pActCtx;
+        pActCtx.cbSize = ACTCTX.sizeof;
+        pActCtx.dwFlags = 0
+            | ACTCTX_FLAG_RESOURCE_NAME_VALID
+            | ACTCTX_FLAG_SET_PROCESS_DEFAULT
+            ;
+        pActCtx.lpSource = pszText;
+        pActCtx.lpApplicationName = pszText;
+        pActCtx.lpResourceName = MANIFEST_RESOURCE_ID;
+        HANDLE hActCtx = OS.CreateActCtx (&pActCtx);
+        if (hActCtx is INVALID_HANDLE_VALUE){
+            printError("CreateActCtx failed" );
+        }
+        else{
+            ULONG_PTR ulpActivationCookie;
+            if (!OS.ActivateActCtx(hActCtx, &ulpActivationCookie)){
+                printError("ActivateActCtx failed" );
             }
-
-            temp.path.remove();
-
-/+         
-            //if (System.getProperty (NO_MANIFEST) is null) {
-                TCHAR[] buffer = new TCHAR[ MAX_PATH ];
-                HANDLE hModule = OS.GetLibraryHandle ();
-                while (OS.GetModuleFileName (hModule, buffer.ptr, buffer.length ) is buffer.length ) {
-                    buffer.length = buffer.length + MAX_PATH;
-                }
-                auto hHeap = OS.GetProcessHeap ();
-                int byteCount = buffer.length * TCHAR.sizeof;
-                TCHAR* pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, HEAP_ZERO_MEMORY, byteCount);
-                OS.MoveMemory (pszText, buffer.ptr, byteCount);
-                ACTCTX pActCtx;
-                pActCtx.cbSize = ACTCTX.sizeof;
-                pActCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT;
-                pActCtx.lpSource = pszText;
-                pActCtx.lpResourceName = cast(TCHAR*)MANIFEST_RESOURCE_ID;
-                HANDLE hActCtx = OS.CreateActCtx (&pActCtx);
-                if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
-                uint lpCookie;
-                OS.ActivateActCtx (hActCtx, &lpCookie);
-                /*
-                * NOTE:  A single activation context is created and activated
-                * for the entire lifetime of the program.  It is deactivated
-                * and released by Windows when the program exits.
-                */
-        //}
-+/
+        }
+
+        if (pszText !is null){
+            OS.HeapFree (hHeap, 0, pszText);
         }
+
+        /*
+        * NOTE:  A single activation context is created and activated
+        * for the entire lifetime of the program.  It is deactivated
+        * and released by Windows when the program exits.
+        */
     }
-    
+
     /**************************************************************************
-    
+
     **************************************************************************/
-         
+
     /* Flag used on WinCE */
-    
+
     static const int SYS_COLOR_INDEX_FLAG = OS.IsWinCE ? 0x40000000 : 0x0;
 
     /*