mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[uxtheme]
- Implement drawing windows caption and borders with themes svn path=/branches/GSoC_2011/ThemesSupport/; revision=51804
This commit is contained in:
parent
125af16c9b
commit
ceca3abd9d
1 changed files with 320 additions and 4 deletions
|
@ -10,6 +10,7 @@
|
|||
#include "undocuser.h"
|
||||
#include "vfwmsgs.h"
|
||||
#include "uxtheme.h"
|
||||
#include <tmschema.h>
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -21,9 +22,137 @@ typedef struct _DRAW_CONTEXT
|
|||
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,
|
||||
HWND hWnd,
|
||||
|
@ -31,8 +160,12 @@ ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
|
|||
{
|
||||
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)
|
||||
{
|
||||
hRgn = CreateRectRgnIndirect(&pcontext->wi.rcWindow);
|
||||
|
@ -59,16 +192,199 @@ ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Message handlers
|
||||
*/
|
||||
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)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
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 LRESULT
|
||||
ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue