[OSK] Make the buttons themed
authorBișoc George <fraizeraust99@gmail.com>
Mon, 22 Apr 2019 13:01:18 +0000 (15:01 +0200)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Mon, 29 Apr 2019 19:31:29 +0000 (21:31 +0200)
Our On-Screen Keyboard has a manifest and the buttons (the ones with BS_ICON styles) aren't rendered with the specific theme as it should be but instead it takes the classic theme.

The code relies on NM_CUSTOMDRAW notification, which is more intuitive and efficient than doing owner-drawn operations as NM_CUSTOMDRAW allows the controls to use styles whereas you cannot do it on owner-drawn controls.

CORE-15965

base/applications/osk/CMakeLists.txt
base/applications/osk/main.c
base/applications/osk/osk.h

index 24b64ea..ff58760 100644 (file)
@@ -3,5 +3,5 @@ file(GLOB osk_rc_deps res/*.*)
 add_rc_deps(rsrc.rc ${osk_rc_deps})
 add_executable(osk main.c settings.c rsrc.rc)
 set_module_type(osk win32gui UNICODE)
 add_rc_deps(rsrc.rc ${osk_rc_deps})
 add_executable(osk main.c settings.c rsrc.rc)
 set_module_type(osk win32gui UNICODE)
-add_importlibs(osk comdlg32 winmm shell32 user32 gdi32 advapi32 comctl32 msvcrt kernel32 ntdll)
+add_importlibs(osk comdlg32 uxtheme winmm shell32 user32 gdi32 advapi32 comctl32 msvcrt kernel32 ntdll)
 add_cd_file(TARGET osk DESTINATION reactos/system32 FOR all)
 add_cd_file(TARGET osk DESTINATION reactos/system32 FOR all)
index e12d68d..6f04d78 100644 (file)
@@ -24,6 +24,7 @@ BOOL OSK_DlgCommand(WPARAM wCommand, HWND hWndControl);
 BOOL OSK_ReleaseKey(WORD ScanCode);
 
 INT_PTR APIENTRY OSK_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
 BOOL OSK_ReleaseKey(WORD ScanCode);
 
 INT_PTR APIENTRY OSK_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT APIENTRY OSK_ThemeHandler(HWND hDlg, NMCUSTOMDRAW *pNmDraw);
 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
 
 /* FUNCTIONS ******************************************************************/
 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
 
 /* FUNCTIONS ******************************************************************/
@@ -428,6 +429,58 @@ BOOL OSK_ReleaseKey(WORD ScanCode)
     return TRUE;
 }
 
     return TRUE;
 }
 
+/***********************************************************************
+ *
+ *           OSK_ThemeHandler
+ *
+ *  Function helper which handles theme drawing of controls
+ */
+LRESULT APIENTRY OSK_ThemeHandler(HWND hDlg, NMCUSTOMDRAW *pNmDraw)
+{
+    HTHEME hTheme;
+    HWND hDlgButtonCtrl;
+    INT iState = PBS_NORMAL;
+
+    /* Retrieve the theme handle for the button controls */
+    hDlgButtonCtrl = pNmDraw->hdr.hwndFrom;
+    hTheme = GetWindowTheme(hDlgButtonCtrl);
+
+    /*
+        Begin the painting procedures if we retrieved
+        the theme for control buttons of the dialog.
+    */
+    if (hTheme)
+    {
+        /*
+            The button could be either in normal state or pushed.
+            Retrieve its state and save to a variable.
+        */
+        if (pNmDraw->uItemState & CDIS_DEFAULT)
+        {
+            iState = PBS_DEFAULTED;
+        }
+        else if (pNmDraw->uItemState & CDIS_SELECTED)
+        {
+            iState = PBS_PRESSED;
+        }
+        else if (pNmDraw->uItemState & CDIS_HOT)
+        {
+            iState = PBS_HOT;
+        }
+
+        if (IsThemeBackgroundPartiallyTransparent(hTheme, BP_PUSHBUTTON, iState))
+        {
+            /* Draw the application if the theme is transparent */
+            DrawThemeParentBackground(hDlg, pNmDraw->hdc, &pNmDraw->rc);
+        }
+
+        /* Draw it */
+        DrawThemeBackground(hTheme, pNmDraw->hdc, BP_PUSHBUTTON, iState, &pNmDraw->rc, NULL);
+    }
+
+    return CDRF_SKIPDEFAULT;
+}
+
 /***********************************************************************
  *
  *       OSK_DlgProc
 /***********************************************************************
  *
  *       OSK_DlgProc
@@ -444,6 +497,9 @@ INT_PTR APIENTRY OSK_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
             OSK_DlgTimer();
             return TRUE;
 
             OSK_DlgTimer();
             return TRUE;
 
+        case WM_NOTIFY:
+            return OSK_ThemeHandler(hDlg, (LPNMCUSTOMDRAW)lParam);
+
         case WM_CTLCOLORSTATIC:
             if ((HWND)lParam == GetDlgItem(hDlg, IDC_LED_NUM))
             {
         case WM_CTLCOLORSTATIC:
             if ((HWND)lParam == GetDlgItem(hDlg, IDC_LED_NUM))
             {
@@ -567,6 +623,11 @@ INT_PTR APIENTRY OSK_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
             }
             break;
 
             }
             break;
 
+        case WM_THEMECHANGED:
+            /* Redraw the dialog (and its control buttons) using the new theme */
+            InvalidateRect(hDlg, NULL, FALSE);
+            break;
+
         case WM_CLOSE:
             OSK_DlgClose();
             break;
         case WM_CLOSE:
             OSK_DlgClose();
             break;
index f320d14..a435e69 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * PROJECT:         ReactOS On-Screen Keyboard
  * LICENSE:         GPL - See COPYING in the top level directory
 /*
  * PROJECT:         ReactOS On-Screen Keyboard
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            base/applications/osk/osk.h
  * PURPOSE:         On screen keyboard.
  * PURPOSE:         On screen keyboard.
- * PROGRAMMERS:     Denis ROBERT
+ * COPYRIGHT:       Denis ROBERT
+ *                  Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com)
  */
 
 #ifndef _OSK_H
  */
 
 #ifndef _OSK_H
@@ -16,6 +16,8 @@
 #include <windows.h>
 #include <commctrl.h>
 #include <debug.h>
 #include <windows.h>
 #include <commctrl.h>
 #include <debug.h>
+#include <uxtheme.h>
+#include <vsstyle.h>
 
 #include "main.h"
 
 
 #include "main.h"