Author: gadamopoulos
Date: Tue May 17 07:57:17 2011
New Revision: 51804

URL: http://svn.reactos.org/svn/reactos?rev=51804&view=rev
Log:
[uxtheme]
- Implement drawing windows caption and borders with themes

Modified:
    branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/nonclient.c

Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/nonclient.c
URL: 
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/nonclient.c?rev=51804&r1=51803&r2=51804&view=diff
==============================================================================
--- branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/nonclient.c [iso-8859-1] 
(original)
+++ branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/nonclient.c [iso-8859-1] 
Tue May 17 07:57:17 2011
@@ -10,6 +10,7 @@
 #include "undocuser.h"
 #include "vfwmsgs.h"
 #include "uxtheme.h"
+#include <tmschema.h>
 
 #include "wine/debug.h"
 
@@ -21,8 +22,136 @@
     HDC hDC;
     HTHEME theme; 
     WINDOWINFO wi;
+    BOOL Active; /* wi.dwWindowStatus isn't correct for mdi child windows */
     HRGN hRgn;
+    int CaptionHeight;
 } DRAW_CONTEXT, *PDRAW_CONTEXT;
+
+typedef enum 
+{
+    CLOSEBUTTON,
+    MAXBUTTON,
+    MINBUTTON,
+    HELPBUTTON
+} CAPTIONBUTTON;
+
+/*
+The following values specify all possible vutton states
+Note that not all of them are documented but it is easy to 
+find them by opening a theme file
+*/
+typedef enum {
+    BUTTON_NORMAL = 1 ,
+    BUTTON_HOT ,
+    BUTTON_PRESSED ,
+    BUTTON_DISABLED ,
+    BUTTON_INACTIVE
+} THEME_BUTTON_STATES;
+
+#define HAS_MENU(hwnd,style)  ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) 
&& GetMenu(hwnd))
+
+#define BUTTON_GAP_SIZE 2
+
+static BOOL 
+IsWindowActive(HWND hWnd, DWORD ExStyle)
+{
+    BOOL ret;
+
+    if (ExStyle & WS_EX_MDICHILD)
+    {
+        ret = IsChild(GetForegroundWindow(), hWnd);
+        if (ret)
+            ret = (hWnd == (HWND)SendMessageW(GetParent(hWnd), 
WM_MDIGETACTIVE, 0, 0));
+    }
+    else
+    {
+        ret = (GetForegroundWindow() == hWnd);
+    }
+
+    return ret;
+}
+
+HICON
+UserGetWindowIcon(HWND hwnd)
+{
+    HICON hIcon = 0;
+
+    SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 
1000, (PDWORD_PTR)&hIcon);
+
+    if (!hIcon)
+        SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 
1000, (PDWORD_PTR)&hIcon);
+
+    if (!hIcon)
+        SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 
1000, (PDWORD_PTR)&hIcon);
+
+    if (!hIcon)
+        hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM);
+
+    if (!hIcon)
+        hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
+
+    if(!hIcon)
+        hIcon = LoadIcon(NULL, IDI_WINLOGO);
+
+    return hIcon;
+}
+
+WCHAR *UserGetWindowCaption(HWND hwnd)
+{
+    INT len = 512;
+    WCHAR *text;
+    text = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, len  * sizeof(WCHAR));
+    if (text) InternalGetWindowText(hwnd, text, len);
+    return text;
+}
+
+static void 
+ThemeDrawTitle(PDRAW_CONTEXT context, RECT* prcCurrent)
+{
+
+}
+
+HRESULT WINAPI ThemeDrawCaptionText(HTHEME hTheme, HDC hdc, int iPartId, int 
iStateId,
+                             LPCWSTR pszText, int iCharCount, DWORD 
dwTextFlags,
+                             DWORD dwTextFlags2, const RECT *pRect, BOOL 
Active)
+{
+    HRESULT hr;
+    HFONT hFont = NULL;
+    HGDIOBJ oldFont = NULL;
+    LOGFONTW logfont;
+    COLORREF textColor;
+    COLORREF oldTextColor;
+    int oldBkMode;
+    RECT rt;
+    
+    hr = GetThemeSysFont(0,TMT_CAPTIONFONT,&logfont);
+
+    if(SUCCEEDED(hr)) {
+        hFont = CreateFontIndirectW(&logfont);
+    }
+    CopyRect(&rt, pRect);
+    if(hFont)
+        oldFont = SelectObject(hdc, hFont);
+        
+    if(dwTextFlags2 & DTT_GRAYED)
+        textColor = GetSysColor(COLOR_GRAYTEXT);
+    else if (!Active)
+        textColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
+    else
+        textColor = GetSysColor(COLOR_CAPTIONTEXT);
+    
+    oldTextColor = SetTextColor(hdc, textColor);
+    oldBkMode = SetBkMode(hdc, TRANSPARENT);
+    DrawTextW(hdc, pszText, iCharCount, &rt, dwTextFlags);
+    SetBkMode(hdc, oldBkMode);
+    SetTextColor(hdc, oldTextColor);
+
+    if(hFont) {
+        SelectObject(hdc, oldFont);
+        DeleteObject(hFont);
+    }
+    return S_OK;
+}
 
 static void
 ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
@@ -31,7 +160,11 @@
 {
     GetWindowInfo(hWnd, &pcontext->wi);
     pcontext->hWnd = hWnd;
+    pcontext->Active = IsWindowActive(hWnd, pcontext->wi.dwExStyle);
     pcontext->theme = OpenThemeData(pcontext->hWnd,  L"WINDOW");
+
+    pcontext->CaptionHeight = pcontext->wi.cyWindowBorders;
+    pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle & 
WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
 
     if(hRgn <= 0)
     {
@@ -57,17 +190,200 @@
     {
         DeleteObject(pcontext->hRgn);
     }
+}
+
+static void 
+ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext, 
+                       RECT* prcCurrent, 
+                       CAPTIONBUTTON buttonId, 
+                       INT iStateId)
+{
+    RECT rcPart;
+    INT ButtonWidth, ButtonHeight, iPartId;
+    
+    ButtonHeight = GetThemeSysSize(pcontext->theme,  pcontext->wi.dwExStyle & 
WS_EX_TOOLWINDOW ? SM_CYSMSIZE : SM_CYSIZE);
+    ButtonWidth = GetThemeSysSize(pcontext->theme,  pcontext->wi.dwExStyle & 
WS_EX_TOOLWINDOW ? SM_CXSMSIZE : SM_CXSIZE);
+
+    switch(buttonId)
+    {
+    case CLOSEBUTTON:
+        iPartId = pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? 
WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
+        break;
+
+    case MAXBUTTON:
+        if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
+        {
+            if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
+                return;
+            else
+                iStateId = BUTTON_DISABLED;
+        }
+
+        iPartId = pcontext->wi.dwStyle & WS_MAXIMIZE ? WP_RESTOREBUTTON : 
WP_MAXBUTTON;
+        break;
+
+    case MINBUTTON:
+        if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
+        {
+            if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
+                return;
+            else
+                iStateId = BUTTON_DISABLED;
+        }
+ 
+        iPartId = WP_MINBUTTON;
+        break;
+
+    default:
+        //FIXME: Implement Help Button 
+        return;
+    }
+
+    ButtonHeight -= 4;
+    ButtonWidth -= 4;
+
+    /* Calculate the position */
+    rcPart.top = prcCurrent->top;
+    rcPart.right = prcCurrent->right;
+    rcPart.bottom = rcPart.top + ButtonHeight ;
+    rcPart.left = rcPart.right - ButtonWidth ;
+    prcCurrent->right -= ButtonWidth + BUTTON_GAP_SIZE;
+
+    DrawThemeBackground(pcontext->theme, pcontext->hDC, iPartId, iStateId, 
&rcPart, NULL);
+}
+
+static void 
+ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+{
+    RECT rcPart;
+    int iPart, iState;
+    HICON hIcon;
+    WCHAR *CaptionText;
+
+    hIcon = UserGetWindowIcon(pcontext->hWnd);
+    CaptionText = UserGetWindowCaption(pcontext->hWnd);
+
+    /* Get the caption part and state id */
+    if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)
+        iPart = WP_SMALLCAPTION;
+    else if (pcontext->wi.dwStyle & WS_MAXIMIZE)
+        iPart = WP_MAXCAPTION;
+    else
+        iPart = WP_CAPTION;
+
+    iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
+
+    /* Draw the caption background*/
+    rcPart = *prcCurrent;
+    rcPart.bottom = pcontext->CaptionHeight;
+    prcCurrent->top = rcPart.bottom;
+    DrawThemeBackground(pcontext->theme, 
pcontext->hDC,iPart,iState,&rcPart,NULL);
+
+    /* Add a padding around the objects of the caption */
+    InflateRect(&rcPart, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE, 
+                         -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE);
+
+    /* Draw the caption buttons */
+    if (pcontext->wi.dwStyle & WS_SYSMENU)
+    {
+        iState = pcontext->Active ? BUTTON_NORMAL : BUTTON_INACTIVE;
+
+        ThemeDrawCaptionButton(pcontext, &rcPart, CLOSEBUTTON, iState);
+        ThemeDrawCaptionButton(pcontext, &rcPart, MAXBUTTON, iState);
+        ThemeDrawCaptionButton(pcontext, &rcPart, MINBUTTON, iState);
+        ThemeDrawCaptionButton(pcontext, &rcPart, HELPBUTTON, iState);
+    }
+    
+    rcPart.top += 3 ;
+
+    /* Draw the icon */
+    if(hIcon && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW))
+    {
+        int IconHeight = GetSystemMetrics(SM_CYSMICON);
+        int IconWidth = GetSystemMetrics(SM_CXSMICON);
+        DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, 
IconHeight, 0, NULL, DI_NORMAL);
+        rcPart.left += IconWidth + 4;
+    }
+
+    rcPart.right -= 4;
+
+    /* Draw the caption */
+    if(CaptionText)
+    {
+        /*FIXME: Use DrawThemeTextEx*/
+        ThemeDrawCaptionText(pcontext->theme, 
+                             pcontext->hDC, 
+                             iPart,
+                             iState, 
+                             CaptionText, 
+                             lstrlenW(CaptionText), 
+                             DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS, 
+                             0, 
+                             &rcPart , 
+                             pcontext->Active);
+        HeapFree(GetProcessHeap(), 0, CaptionText);
+    }
+}
+
+static void 
+ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+{
+
+}
+
+static void 
+DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
+{
+
+}
+
+static void
+ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, PRECT prcCurrent)
+{
+
+}
+
+static void 
+ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT Bar)
+{
+
+}
+
+static void 
+ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
+{
+    if(!(pcontext->wi.dwStyle & WS_VISIBLE))
+        return;
+
+    if(pcontext->wi.dwStyle & WS_MINIMIZE)
+    {
+        ThemeDrawTitle(pcontext, prcCurrent);
+        return;
+    }
+
+    if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION)
+    {
+        ThemeDrawCaption(pcontext, prcCurrent);
+        ThemeDrawBorders(pcontext, prcCurrent);
+    }
+    else
+    {
+        DrawClassicFrame(pcontext, prcCurrent);
+    }
+
+    if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle))
+        ThemeDrawMenuBar(pcontext, prcCurrent);
+    
+    if(pcontext->wi.dwStyle & WS_HSCROLL)
+        ThemeDrawScrollBar(pcontext, OBJID_VSCROLL);
+
+    if(pcontext->wi.dwStyle & WS_VSCROLL)
+        ThemeDrawScrollBar(pcontext, OBJID_HSCROLL);
 }
 
 /*
     Message handlers
  */
-
-static void 
-ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
-{
-    UNIMPLEMENTED;
-}
 
 static LRESULT 
 ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)


Reply via email to