[COMCTL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 17 Feb 2017 10:04:24 +0000 (10:04 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 17 Feb 2017 10:04:24 +0000 (10:04 +0000)
- Add and install a manifest for comctl32 version 5.82.
- Since our comctl32 tries to imitate both version 5 and version 6, register its classes twice, once while having the version 6 manifest active and once when having the version 5 active.
- Register the themed versions of the built in controls while having the version 6 manifest active (and register them as global classes). This breaks theming of built in controls until versioned classes get implemented.
- Do not try to subclass the dialog class. This is incorrect and can lead to problems like in CORE-8534, CORE-12727, CORE-8387. This removes the background texture of the themed tabs which will be implemented in the future in uxtheme using api hooks.
This breaks a great deal of theming but keep in mind that it is in the middle of a transition to have them implemented correctly without the terrible side effects (broken ansi conversion, not always  using themes for built in controls. However comctl32 is now ready for versioned classes to be enabled.
CORE-12285

svn path=/trunk/; revision=73803

reactos/dll/win32/comctl32/comctl32.h
reactos/dll/win32/comctl32/comctl32.manifest
reactos/dll/win32/comctl32/comctl32v5.manifest [new file with mode: 0644]
reactos/dll/win32/comctl32/commctrl.c
reactos/dll/win32/comctl32/rsrc.rc
reactos/dll/win32/comctl32/theming.c

index b570c7f..939654b 100644 (file)
@@ -165,7 +165,7 @@ int MONTHCAL_MonthLength(int month, int year) DECLSPEC_HIDDEN;
 int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace) DECLSPEC_HIDDEN;
 LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second) DECLSPEC_HIDDEN;
 
-extern void THEMING_Initialize(void) DECLSPEC_HIDDEN;
+extern void THEMING_Initialize(HANDLE hActCtx5, HANDLE hActCtx6) DECLSPEC_HIDDEN;
 extern void THEMING_Uninitialize(void) DECLSPEC_HIDDEN;
 extern LRESULT THEMING_CallOriginalClass(HWND, UINT, WPARAM, LPARAM) DECLSPEC_HIDDEN;
 extern void THEMING_SetSubclassData(HWND, ULONG_PTR) DECLSPEC_HIDDEN;
index 4c86137..1d82715 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
-  <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.2600.2982" processorArchitecture="" publicKeyToken="6595b64144ccf1df"/>
+  <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.2600.2982" publicKeyToken="6595b64144ccf1df"/>
   <file name="comctl32.dll">
     <windowClass>Button</windowClass>
     <windowClass>ButtonListBox</windowClass>
@@ -12,7 +12,6 @@
     <windowClass>NativeFontCtl</windowClass>
     <windowClass>ReBarWindow32</windowClass>
     <windowClass>ScrollBar</windowClass>
-    <windowClass>Static</windowClass>
     <windowClass>SysAnimate32</windowClass>
     <windowClass>SysDateTimePick32</windowClass>
     <windowClass>SysHeader32</windowClass>
diff --git a/reactos/dll/win32/comctl32/comctl32v5.manifest b/reactos/dll/win32/comctl32/comctl32v5.manifest
new file mode 100644 (file)
index 0000000..3b8a709
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\r
+  <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="5.82.2600.2982" publicKeyToken="6595b64144ccf1df"/>\r
+  <file name="comctl32.dll">\r
+    <windowClass versioned="no">Button</windowClass>\r
+    <windowClass versioned="no">ButtonListBox</windowClass>\r
+    <windowClass versioned="no">ComboBoxEx32</windowClass>\r
+    <windowClass versioned="no">ComboLBox</windowClass>\r
+    <windowClass versioned="no">Combobox</windowClass>\r
+    <windowClass versioned="no">Edit</windowClass>\r
+    <windowClass versioned="no">Listbox</windowClass>\r
+    <windowClass versioned="no">NativeFontCtl</windowClass>\r
+    <windowClass versioned="no">ReBarWindow32</windowClass>\r
+    <windowClass versioned="no">ScrollBar</windowClass>\r
+    <windowClass versioned="no">SysAnimate32</windowClass>\r
+    <windowClass versioned="no">SysDateTimePick32</windowClass>\r
+    <windowClass versioned="no">SysHeader32</windowClass>\r
+    <windowClass versioned="no">SysIPAddress32</windowClass>\r
+    <windowClass versioned="no">SysLink</windowClass>\r
+    <windowClass versioned="no">SysListView32</windowClass>\r
+    <windowClass versioned="no">SysMonthCal32</windowClass>\r
+    <windowClass versioned="no">SysPager</windowClass>\r
+    <windowClass versioned="no">SysTabControl32</windowClass>\r
+    <windowClass versioned="no">SysTreeView32</windowClass>\r
+    <windowClass versioned="no">ToolbarWindow32</windowClass>\r
+    <windowClass versioned="no">msctls_hotkey32</windowClass>\r
+    <windowClass versioned="no">msctls_progress32</windowClass>\r
+    <windowClass versioned="no">msctls_statusbar32</windowClass>\r
+    <windowClass versioned="no">msctls_trackbar32</windowClass>\r
+    <windowClass versioned="no">msctls_updown32</windowClass>\r
+    <windowClass versioned="no">tooltips_class32</windowClass>\r
+  </file>\r
+</assembly>\r
index 17aa827..1619c3a 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
-#define NAME       L"microsoft.windows.common-controls"
-#define VERSION    L"6.0.2600.2982"
-#define PUBLIC_KEY L"6595b64144ccf1df"
-
-#ifdef __i386__
-#define ARCH L"x86"
-#elif defined __x86_64__
-#define ARCH L"amd64"
-#else
-#define ARCH L"none"
-#endif
-
-static const WCHAR manifest_filename[] = ARCH L"_" NAME L"_" PUBLIC_KEY L"_" VERSION L"_none_deadbeef.manifest";
-
 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
 static LPWSTR COMCTL32_wSubclass = NULL;
@@ -94,17 +80,69 @@ static const WCHAR strCC32SubclassInfo[] = {
     'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
 };
 
-static BOOL create_manifest(BOOL install)
+#ifdef __REACTOS__
+
+#include <strsafe.h>
+
+#define NAME       L"microsoft.windows.common-controls"
+#define VERSION_V5 L"5.82.2600.2982"
+#define VERSION    L"6.0.2600.2982"
+#define PUBLIC_KEY L"6595b64144ccf1df"
+
+#ifdef __i386__
+#define ARCH L"x86"
+#elif defined __x86_64__
+#define ARCH L"amd64"
+#else
+#define ARCH L"none"
+#endif
+
+static const WCHAR manifest_filename[] = ARCH L"_" NAME L"_" PUBLIC_KEY L"_" VERSION L"_none_deadbeef.manifest";
+static const WCHAR manifest_filename_v5[] = ARCH L"_" NAME L"_" PUBLIC_KEY L"_" VERSION_V5 L"_none_deadbeef.manifest";
+
+static WCHAR* GetManifestPath(BOOL create, BOOL bV6)
+{
+    WCHAR *pwszBuf;
+    HRESULT hres;
+
+    pwszBuf = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
+    if (!pwszBuf)
+        return NULL;
+
+    GetWindowsDirectoryW(pwszBuf, MAX_PATH);
+    hres = StringCchCatW(pwszBuf, MAX_PATH, L"\\winsxs");
+    if (FAILED(hres))
+        return NULL;
+    if (create)
+        CreateDirectoryW(pwszBuf, NULL);
+    hres = StringCchCatW(pwszBuf, MAX_PATH, L"\\manifests\\");
+    if (FAILED(hres))
+        return NULL;
+    if (create)
+        CreateDirectoryW(pwszBuf, NULL);
+
+    hres = StringCchCatW(pwszBuf, MAX_PATH, bV6 ? manifest_filename : manifest_filename_v5);
+    if (FAILED(hres))
+        return NULL;
+
+    return pwszBuf;
+}
+
+static BOOL create_manifest(BOOL install, BOOL bV6)
 {
     WCHAR *pwszBuf;
     HRSRC hResInfo;
     HGLOBAL hResData;
     PVOID pManifest;
-    DWORD cchBuf, cbManifest, cbWritten;
+    DWORD cbManifest, cbWritten;
     HANDLE hFile;
     BOOL bRet = FALSE;
 
-    hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFEST", (LPWSTR)RT_MANIFEST);
+    if (bV6)
+        hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFEST", (LPWSTR)RT_MANIFEST);
+    else
+        hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFESTV5", (LPWSTR)RT_MANIFEST);
+
     if (!hResInfo)
         return FALSE;
 
@@ -120,17 +158,10 @@ static BOOL create_manifest(BOOL install)
     if (!pManifest)
         return FALSE;
 
-    cchBuf = GetWindowsDirectoryW(NULL, 0) * sizeof(WCHAR) + sizeof(L"\\winsxs\\manifests\\") + sizeof(manifest_filename);
-    pwszBuf = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, cchBuf * sizeof(WCHAR));
+    pwszBuf = GetManifestPath(TRUE, bV6);
     if (!pwszBuf)
         return FALSE;
 
-    GetWindowsDirectoryW(pwszBuf, cchBuf);
-    lstrcatW(pwszBuf, L"\\winsxs");
-    CreateDirectoryW(pwszBuf, NULL);
-    lstrcatW(pwszBuf, L"\\manifests\\");
-    CreateDirectoryW(pwszBuf, NULL);
-    lstrcatW(pwszBuf, manifest_filename);
     if (install)
     {
         hFile = CreateFileW(pwszBuf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
@@ -155,6 +186,134 @@ static BOOL create_manifest(BOOL install)
     return bRet;
 }
 
+static HANDLE CreateComctl32ActCtx(BOOL bV6)
+{
+    HANDLE ret;
+    WCHAR* pwstrSource;
+    ACTCTXW ActCtx = {sizeof(ACTCTX)};
+
+    pwstrSource = GetManifestPath(FALSE, bV6);
+    if (!pwstrSource)
+    {
+        ERR("GetManifestPath failed! bV6=%d\n", bV6);
+        return INVALID_HANDLE_VALUE;
+    }
+    ActCtx.lpSource = pwstrSource;
+    ret = CreateActCtxW(&ActCtx);
+    HeapFree(GetProcessHeap(), 0, pwstrSource);
+    if (ret == INVALID_HANDLE_VALUE)
+        ERR("CreateActCtxW failed! bV6=%d\n", bV6);
+    return ret;
+}
+
+static void RegisterControls()
+{
+    ANIMATE_Register ();
+    COMBOEX_Register ();
+    DATETIME_Register ();
+    FLATSB_Register ();
+    HEADER_Register ();
+    HOTKEY_Register ();
+    IPADDRESS_Register ();
+    LISTVIEW_Register ();
+    MONTHCAL_Register ();
+    NATIVEFONT_Register ();
+    PAGER_Register ();
+    PROGRESS_Register ();
+    REBAR_Register ();
+    STATUS_Register ();
+    SYSLINK_Register ();
+    TAB_Register ();
+    TOOLBAR_Register ();
+    TOOLTIPS_Register ();
+    TRACKBAR_Register ();
+    TREEVIEW_Register ();
+    UPDOWN_Register ();
+}
+
+static void UnregisterControls()
+{
+    ANIMATE_Unregister ();
+    COMBOEX_Unregister ();
+    DATETIME_Unregister ();
+    FLATSB_Unregister ();
+    HEADER_Unregister ();
+    HOTKEY_Unregister ();
+    IPADDRESS_Unregister ();
+    LISTVIEW_Unregister ();
+    MONTHCAL_Unregister ();
+    NATIVEFONT_Unregister ();
+    PAGER_Unregister ();
+    PROGRESS_Unregister ();
+    REBAR_Unregister ();
+    STATUS_Unregister ();
+    SYSLINK_Unregister ();
+    TAB_Unregister ();
+    TOOLBAR_Unregister ();
+    TOOLTIPS_Unregister ();
+    TRACKBAR_Unregister ();
+    TREEVIEW_Unregister ();
+    UPDOWN_Unregister ();
+}
+
+static void InitializeClasses()
+{
+    HANDLE hActCtx5, hActCtx6;
+    BOOL activated;
+    ULONG_PTR ulCookie;
+
+    /* like comctl32 5.82+ register all the common control classes */
+    /* Register the classes once no matter what */
+    hActCtx5 = CreateComctl32ActCtx(FALSE);
+    activated = (hActCtx5 != INVALID_HANDLE_VALUE ? ActivateActCtx(hActCtx5, &ulCookie) : FALSE);
+    RegisterControls();      /* Register the classes pretending to be v5 */
+    if (activated) DeactivateActCtx(0, ulCookie);
+
+    hActCtx6 = CreateComctl32ActCtx(TRUE);
+    if (hActCtx6 != INVALID_HANDLE_VALUE)
+    {
+        activated = ActivateActCtx(hActCtx6, &ulCookie);
+        RegisterControls();      /* Register the classes pretending to be v6 */
+        if (activated) DeactivateActCtx(0, ulCookie);
+
+        /* Initialize the themed controls only when the v6 manifest is present */
+        THEMING_Initialize (hActCtx5, hActCtx6);
+    }
+}
+
+static void UninitializeClasses()
+{
+    HANDLE hActCtx5, hActCtx6;
+    BOOL activated;
+    ULONG_PTR ulCookie;
+
+    hActCtx5 = CreateComctl32ActCtx(FALSE);
+    activated = (hActCtx5 != INVALID_HANDLE_VALUE ? ActivateActCtx(hActCtx5, &ulCookie) : FALSE);
+    UnregisterControls();
+    if (activated) DeactivateActCtx(0, ulCookie);
+
+    hActCtx6 = CreateComctl32ActCtx(TRUE);
+    if (hActCtx6 != INVALID_HANDLE_VALUE)
+    {
+        activated = ActivateActCtx(hActCtx6, &ulCookie);
+        THEMING_Uninitialize();
+        UnregisterControls();
+        if (activated) DeactivateActCtx(0, ulCookie);
+    }
+}
+
+/***********************************************************************
+ * RegisterClassNameW [COMCTL32.@]
+ *
+ * Register window class again while using as SxS module.
+ */
+BOOLEAN WINAPI RegisterClassNameW(LPCWSTR className)
+{
+    InitializeClasses();
+    return TRUE;
+}
+
+#endif
 
 /***********************************************************************
  * DllMain [Internal]
@@ -192,6 +351,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
            /* Get all the colors at DLL load */
            COMCTL32_RefreshSysColors();
 
+#ifndef __REACTOS__
             /* like comctl32 5.82+ register all the common control classes */
             ANIMATE_Register ();
             COMBOEX_Register ();
@@ -217,10 +377,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 
             /* subclass user32 controls */
             THEMING_Initialize ();
+#else
+            InitializeClasses();
+#endif
+
             break;
 
        case DLL_PROCESS_DETACH:
             if (lpvReserved) break;
+#ifndef __REACTOS__
             /* clean up subclassing */
             THEMING_Uninitialize();
 
@@ -246,7 +411,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
             TRACKBAR_Unregister ();
             TREEVIEW_Unregister ();
             UPDOWN_Unregister ();
-
+#else
+            UninitializeClasses();
+#endif
             /* delete local pattern brush */
             DeleteObject (COMCTL32_hPattern55AABrush);
             DeleteObject (COMCTL32_hPattern55AABitmap);
@@ -991,11 +1158,21 @@ HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
 {
     TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
-    if (!create_manifest(bInstall))
+
+#ifdef __REACTOS__
+
+    if (!create_manifest(bInstall, TRUE))
+    {
+        ERR("Failed to install comctl32 v6 manifest!\n");
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    if (!create_manifest(bInstall, FALSE))
     {
-        ERR("create_manifest failed!\n");
+        ERR("Failed to install comctl32 v5 manifest!\n");
         return HRESULT_FROM_WIN32(GetLastError());
     }
+#endif
 
     return S_OK;
 }
@@ -1856,15 +2033,3 @@ HRESULT WINAPI LoadIconMetric(HINSTANCE hinst, const WCHAR *name, int size, HICO
 
     return LoadIconWithScaleDown(hinst, name, cx, cy, icon);
 }
-
-/***********************************************************************
- * RegisterClassNameW [COMCTL32.@]
- *
- * Register window class again while using as SxS module.
- */
-BOOLEAN WINAPI RegisterClassNameW(LPCWSTR className)
-{
-    /* FIXME: actually register redirected user32 class,
-              comctl32 classes are registered by this module anyway */
-    return TRUE;
-}
index 650f772..0fb8289 100644 (file)
@@ -38,6 +38,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
 
 /* @makedep: comctl32.manifest */
 WINE_MANIFEST RT_MANIFEST comctl32.manifest
+WINE_MANIFESTV5 RT_MANIFEST comctl32v5.manifest
 
 /* @makedep: idt_check.bmp */
 IDT_CHECK BITMAP idt_check.bmp
index 48b03f7..c17f313 100644 (file)
@@ -30,8 +30,6 @@ extern LRESULT CALLBACK THEMING_ButtonSubclassProc (HWND, UINT, WPARAM, LPARAM,
                                                     ULONG_PTR) DECLSPEC_HIDDEN;
 extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM,
                                                    ULONG_PTR) DECLSPEC_HIDDEN;
-extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM,
-                                                    ULONG_PTR) DECLSPEC_HIDDEN;
 extern LRESULT CALLBACK THEMING_EditSubclassProc (HWND, UINT, WPARAM, LPARAM,
                                                   ULONG_PTR) DECLSPEC_HIDDEN;
 extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM,
@@ -48,7 +46,6 @@ static const struct ThemingSubclass
     THEMING_SUBCLASSPROC subclassProc;
 } subclasses[] = {
     /* Note: list must be sorted by class name */
-    {dialogClass,          THEMING_DialogSubclassProc},
     {WC_BUTTONW,           THEMING_ButtonSubclassProc},
     {WC_COMBOBOXW,         THEMING_ComboSubclassProc},
     {comboLboxClass,       THEMING_ListBoxSubclassProc},
@@ -90,7 +87,6 @@ MAKE_SUBCLASS_PROC(2)
 MAKE_SUBCLASS_PROC(3)
 MAKE_SUBCLASS_PROC(4)
 MAKE_SUBCLASS_PROC(5)
-MAKE_SUBCLASS_PROC(6)
 
 static const WNDPROC subclassProcs[NUM_SUBCLASSES] = {
     subclass_proc0,
@@ -98,8 +94,7 @@ static const WNDPROC subclassProcs[NUM_SUBCLASSES] = {
     subclass_proc2,
     subclass_proc3,
     subclass_proc4,
-    subclass_proc5,
-    subclass_proc6
+    subclass_proc5
 };
 
 /***********************************************************************
@@ -108,15 +103,15 @@ static const WNDPROC subclassProcs[NUM_SUBCLASSES] = {
  * Register classes for standard controls that will shadow the system
  * classes.
  */
-void THEMING_Initialize (void)
+void THEMING_Initialize (HANDLE hActCtx5, HANDLE hActCtx6)
 {
     unsigned int i;
     static const WCHAR subclassPropName[] = 
         { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 };
     static const WCHAR refDataPropName[] = 
         { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
-
-    if (!IsThemeActive()) return;
+    ULONG_PTR ulCookie;
+    BOOL ret, bActivated;
 
     atSubclassProp = GlobalAddAtomW (subclassPropName);
     atRefDataProp = GlobalAddAtomW (refDataPropName);
@@ -126,7 +121,13 @@ void THEMING_Initialize (void)
         WNDCLASSEXW class;
 
         class.cbSize = sizeof(class);
-        if (!GetClassInfoExW (NULL, subclasses[i].className, &class))
+
+        bActivated = ActivateActCtx(hActCtx5, &ulCookie);
+        ret = GetClassInfoExW (NULL, subclasses[i].className, &class);
+        if (bActivated)
+            DeactivateActCtx(0, ulCookie);
+
+        if (!ret)
         {
             ERR("Could not retrieve information for class %s\n",
                 debugstr_w (subclasses[i].className));
@@ -134,7 +135,9 @@ void THEMING_Initialize (void)
         }
         originalProcs[i] = class.lpfnWndProc;
         class.lpfnWndProc = subclassProcs[i];
-        
+        class.style |= CS_GLOBALCLASS;
+        class.hInstance = COMCTL32_hModule;
+
         if (!class.lpfnWndProc)
         {
             ERR("Missing proc for class %s\n", 
@@ -142,9 +145,11 @@ void THEMING_Initialize (void)
             continue;
         }
 
+        bActivated = ActivateActCtx(hActCtx6, &ulCookie);
+
         if (!RegisterClassExW (&class))
         {
-            ERR("Could not re-register class %s: %x\n",
+            WARN("Could not re-register class %s: %x\n",
                 debugstr_w (subclasses[i].className), GetLastError ());
         }
         else
@@ -152,6 +157,9 @@ void THEMING_Initialize (void)
             TRACE("Re-registered class %s\n", 
                 debugstr_w (subclasses[i].className));
         }
+
+        if (bActivated)
+            DeactivateActCtx(0, ulCookie);
     }
 }