[uxtheme]

- Merge from the themes branch

svn path=/trunk/; revision=53748
This commit is contained in:
Giannis Adamopoulos 2011-09-19 12:51:42 +00:00
commit 84ffa0b5f9
11 changed files with 2483 additions and 107 deletions

View file

@ -11,9 +11,12 @@ list(APPEND SOURCE
main.c
metric.c
msstyles.c
ncscrollbar.c
nonclient.c
property.c
stylemap.c
system.c
themehooks.c
uxini.c
version.rc
${CMAKE_CURRENT_BINARY_DIR}/uxtheme_stubs.c

View file

@ -1731,6 +1731,166 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId,
return S_OK;
}
static HBITMAP UXTHEME_DrawThemePartToDib(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCRECT pRect)
{
HDC hdcMem;
BITMAPINFO bmi = {0};
HBITMAP hbmp, hbmpOld;
HBRUSH hbrBack;
hdcMem = CreateCompatibleDC(0);
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = pRect->right;
bmi.bmiHeader.biHeight = -pRect->bottom;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
hbmp = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS , NULL, 0, 0);
hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmp);
/* FIXME: use an internal function that doesn't do transparent blt */
hbrBack = CreateSolidBrush(RGB(255,0,255));
FillRect(hdcMem, pRect, hbrBack);
DrawThemeBackground(hTheme, hdcMem, iPartId, iStateId, pRect, NULL);
DeleteObject(hbrBack);
SelectObject(hdcMem, hbmpOld);
DeleteObject(hdcMem);
return hbmp;
}
#define PT_IN_RECT(lprc,x,y) ( x >= lprc->left && x < lprc->right && \
y >= lprc->top && y < lprc->bottom)
static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent, LPCRECT pRect)
{
int x, y, xstart;
int cMaxRgnRects, cRgnDataSize, cRgnRects;
#ifdef EXTCREATEREGION_WORKS
RECT* prcCurrent;
PRGNDATA prgnData;
#else
HRGN hrgnTemp;
#endif
ULONG clrTransparent, *pclrCurrent;
HRGN hrgnRet;
pclrCurrent = (PULONG)pBuffer;
clrTransparent = *(PULONG)pclrTransparent;
/* Create a region and pre-allocate memory enough for 3 spaces in one row*/
cRgnRects = 0;
cMaxRgnRects = 4* (pRect->bottom-pRect->top);
cRgnDataSize = sizeof(RGNDATA) + cMaxRgnRects * sizeof(RECT);
#ifdef EXTCREATEREGION_WORKS
/* Allocate the region data */
prgnData = (PRGNDATA)HeapAlloc(GetProcessHeap(), 0, cRgnDataSize);
prcCurrent = (PRECT)prgnData->Buffer;
#else
hrgnRet = CreateRectRgn(0,0,0,0);
#endif
/* Calculate the region rects */
y=0;
/* Scan each line of the bitmap */
while(y<pRect->bottom)
{
x=0;
/* Scan each pixel */
while (x<pRect->right)
{
/* Check if the pixel is not transparent and it is in the requested rect */
if(*pclrCurrent != clrTransparent && PT_IN_RECT(pRect,x,y))
{
xstart = x;
/* Find the end of the opaque row of pixels */
while (x<pRect->right)
{
if(*pclrCurrent == clrTransparent || !PT_IN_RECT(pRect,x,y))
break;
x++;
pclrCurrent++;
}
#ifdef EXTCREATEREGION_WORKS
/* Add the scaned line to the region */
SetRect(prcCurrent, xstart, y,x,y+1);
prcCurrent++;
cRgnRects++;
/* Increase the size of the buffer if it is full */
if(cRgnRects == cMaxRgnRects)
{
cMaxRgnRects *=2;
cRgnDataSize = sizeof(RGNDATA) + cMaxRgnRects * sizeof(RECT);
prgnData = (PRGNDATA)HeapReAlloc(GetProcessHeap(),
0,
prgnData,
cRgnDataSize);
prcCurrent = (RECT*)prgnData->Buffer + cRgnRects;
}
#else
hrgnTemp = CreateRectRgn(xstart, y,x,y+1);
CombineRgn(hrgnRet, hrgnRet, hrgnTemp, RGN_OR );
DeleteObject(hrgnTemp);
#endif
}
else
{
x++;
pclrCurrent++;
}
}
y++;
}
#ifdef EXTCREATEREGION_WORKS
/* Fill the region data header */
prgnData->rdh.dwSize = sizeof(prgnData->rdh);
prgnData->rdh.iType = RDH_RECTANGLES;
prgnData->rdh.nCount = cRgnRects;
prgnData->rdh.nRgnSize = cRgnDataSize;
prgnData->rdh.rcBound = *pRect;
/* Create the region*/
hrgnRet = ExtCreateRegion (NULL, cRgnDataSize, prgnData);
/* Free the region data*/
HeapFree(GetProcessHeap(),0,prgnData);
#endif
/* return the region*/
return hrgnRet;
}
HRESULT UXTHEME_GetImageBackBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCRECT pRect, HRGN *pRegion)
{
HBITMAP hbmp;
DIBSECTION dib;
RGBQUAD clrTransparent = {0xFF,0x0, 0xFF,0x0};
/* Draw the theme part to a dib */
hbmp = UXTHEME_DrawThemePartToDib(hTheme, hdc, iPartId, iStateId, pRect);
/* Retrieve the info of the dib section */
GetObject(hbmp, sizeof (DIBSECTION), &dib);
/* Convert the bits of the dib section to a region */
*pRegion = UXTHEME_RegionFromDibBits((RGBQUAD*)dib.dsBm.bmBits, &clrTransparent, pRect);
/* Free the temp bitmap */
DeleteObject(hbmp);
return S_OK;
}
/***********************************************************************
* GetThemeBackgroundRegion (UXTHEME.@)
*
@ -1752,8 +1912,7 @@ HRESULT WINAPI GetThemeBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId,
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
if(bgtype == BT_IMAGEFILE) {
FIXME("Images not handled yet\n");
hr = ERROR_CALL_NOT_IMPLEMENTED;
hr = UXTHEME_GetImageBackBackgroundRegion(hTheme, hdc, iPartId, iStateId, pRect, pRegion);
}
else if(bgtype == BT_BORDERFILL) {
*pRegion = CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);

View file

@ -1257,6 +1257,13 @@ static HRESULT MSSTYLES_GetFont (LPCWSTR lpCur, LPCWSTR lpEnd,
*lpValEnd = lpCur;
return E_PROP_ID_UNSUPPORTED;
}
if(pointSize > 0)
{
HDC hdc = GetDC(0);
pointSize = -MulDiv(pointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(0, hdc);
}
pFont->lfHeight = pointSize;
pFont->lfWeight = FW_REGULAR;
pFont->lfCharSet = DEFAULT_CHARSET;
@ -1278,8 +1285,6 @@ HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont)
ZeroMemory(pFont, sizeof(LOGFONTW));
hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont);
if (SUCCEEDED (hr))
pFont->lfHeight = -MulDiv(pFont->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
return hr;
}

View file

@ -0,0 +1,676 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS uxtheme.dll
* FILE: dll/win32/uxtheme/ncscrollbar.c
* PURPOSE: uxtheme scrollbar support
* PROGRAMMER: Giannis Adamopoulos
* This file is heavily based on code from the wine project:
* Copyright 1993 Martin Ayotte
* Copyright 1994, 1996 Alexandre Julliard
*/
#include <windows.h>
#include "undocuser.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
#include <tmschema.h>
#include <Windowsx.h>
#include "ncthm.h"
#include <assert.h>
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
static BOOL SCROLL_trackVertical;
static enum SCROLL_HITTEST SCROLL_trackHitTest;
/* Is the moving thumb being displayed? */
static BOOL SCROLL_MovingThumb = FALSE;
static HWND SCROLL_TrackingWin = 0;
static INT SCROLL_TrackingBar = 0;
static INT SCROLL_TrackingPos = 0;
static INT SCROLL_TrackingVal = 0;
void static ScreenToWindow( HWND hWnd, POINT* pt)
{
RECT rcWnd;
GetWindowRect(hWnd, &rcWnd);
pt->x -= rcWnd.left;
pt->y -= rcWnd.top;
}
static BOOL SCROLL_IsVertical(HWND hwnd, INT nBar)
{
switch(nBar)
{
case SB_HORZ:
return FALSE;
case SB_VERT:
return TRUE;
default:
assert(FALSE);
return FALSE;
}
}
static LONG SCROLL_getObjectId(INT nBar)
{
switch(nBar)
{
case SB_HORZ:
return OBJID_HSCROLL;
case SB_VERT:
return OBJID_VSCROLL;
default:
assert(FALSE);
return 0;
}
}
/***********************************************************************
* SCROLL_PtInRectEx
*/
static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
{
RECT rect = *lpRect;
int scrollbarWidth;
/* Pad hit rect to allow mouse to be dragged outside of scrollbar and
* still be considered in the scrollbar. */
if (vertical)
{
scrollbarWidth = lpRect->right - lpRect->left;
rect.left -= scrollbarWidth*8;
rect.right += scrollbarWidth*8;
rect.top -= scrollbarWidth*2;
rect.bottom += scrollbarWidth*2;
}
else
{
scrollbarWidth = lpRect->bottom - lpRect->top;
rect.left -= scrollbarWidth*2;
rect.right += scrollbarWidth*2;
rect.top -= scrollbarWidth*8;
rect.bottom += scrollbarWidth*8;
}
return PtInRect( &rect, pt );
}
/***********************************************************************
* SCROLL_HitTest
*
* Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
*/
static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, SCROLLBARINFO* psbi, BOOL vertical,
POINT pt, BOOL bDragging )
{
if ( (bDragging && !SCROLL_PtInRectEx( &psbi->rcScrollBar, pt, vertical )) ||
(!PtInRect( &psbi->rcScrollBar, pt )) )
{
return SCROLL_NOWHERE;
}
if (vertical)
{
if (pt.y < psbi->rcScrollBar.top + psbi->dxyLineButton)
return SCROLL_TOP_ARROW;
if (pt.y >= psbi->rcScrollBar.bottom - psbi->dxyLineButton)
return SCROLL_BOTTOM_ARROW;
if (!psbi->xyThumbTop)
return SCROLL_TOP_RECT;
pt.y -= psbi->rcScrollBar.top;
if (pt.y < psbi->xyThumbTop)
return SCROLL_TOP_RECT;
if (pt.y >= psbi->xyThumbTop + psbi->dxyLineButton)
return SCROLL_BOTTOM_RECT;
}
else /* horizontal */
{
if (pt.x < psbi->rcScrollBar.left + psbi->dxyLineButton)
return SCROLL_TOP_ARROW;
if (pt.x >= psbi->rcScrollBar.right - psbi->dxyLineButton)
return SCROLL_BOTTOM_ARROW;
if (!psbi->xyThumbTop)
return SCROLL_TOP_RECT;
pt.x -= psbi->rcScrollBar.left;
if (pt.x < psbi->xyThumbTop)
return SCROLL_TOP_RECT;
if (pt.x >= psbi->xyThumbTop + psbi->dxyLineButton)
return SCROLL_BOTTOM_RECT;
}
return SCROLL_THUMB;
}
static void SCROLL_ThemeDrawPart(PDRAW_CONTEXT pcontext, int iPartId,int iStateId, SCROLLBARINFO* psbi, int htCurrent, int htDown, int htHot, RECT* r)
{
if(psbi->rgstate[htCurrent] & STATE_SYSTEM_UNAVAILABLE)
iStateId += BUTTON_DISABLED - BUTTON_NORMAL;
else if (htHot == htCurrent)
iStateId += BUTTON_HOT - BUTTON_NORMAL;
else if (htDown == htCurrent)
iStateId += BUTTON_PRESSED - BUTTON_NORMAL;
DrawThemeBackground(pcontext->scrolltheme, pcontext->hDC, iPartId, iStateId, r, NULL);
}
/***********************************************************************
* SCROLL_DrawArrows
*
* Draw the scroll bar arrows.
*/
static void SCROLL_DrawArrows( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi,
BOOL vertical, int htDown, int htHot )
{
RECT r;
int iStateId;
r = psbi->rcScrollBar;
if( vertical )
{
r.bottom = r.top + psbi->dxyLineButton;
iStateId = ABS_UPNORMAL;
}
else
{
r.right = r.left + psbi->dxyLineButton;
iStateId = ABS_LEFTNORMAL;
}
SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_TOP_ARROW, htDown, htHot, &r);
r = psbi->rcScrollBar;
if( vertical )
{
r.top = r.bottom - psbi->dxyLineButton;
iStateId = ABS_DOWNNORMAL;
}
else
{
iStateId = ABS_RIGHTNORMAL;
r.left = r.right - psbi->dxyLineButton;
}
SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_BOTTOM_ARROW, htDown, htHot, &r);
}
static void SCROLL_DrawInterior( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi,
INT thumbPos, BOOL vertical,
int htDown, int htHot )
{
RECT r, rcPart;
r = psbi->rcScrollBar;
if (vertical)
{
r.top += psbi->dxyLineButton;
r.bottom -= (psbi->dxyLineButton);
}
else
{
r.left += psbi->dxyLineButton;
r.right -= psbi->dxyLineButton;
}
/* Draw the scroll rectangles and thumb */
if (!thumbPos) /* No thumb to draw */
{
rcPart = r;
SCROLL_ThemeDrawPart(pcontext, vertical ? SBP_UPPERTRACKVERT: SBP_UPPERTRACKHORZ , BUTTON_NORMAL, psbi, SCROLL_THUMB, 0, 0, &rcPart);
return;
}
if (vertical)
{
rcPart = r;
rcPart.bottom = rcPart.top + thumbPos - psbi->dxyLineButton;
SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart);
r.top = rcPart.bottom;
rcPart = r;
rcPart.top += psbi->dxyLineButton;
SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart);
r.bottom = rcPart.top;
SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
}
else /* horizontal */
{
rcPart = r;
rcPart.right = rcPart.left + thumbPos - psbi->dxyLineButton;
SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart);
r.left = rcPart.right;
rcPart = r;
rcPart.left += psbi->dxyLineButton;
SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart);
r.right = rcPart.left;
SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r);
}
}
static void SCROLL_DrawMovingThumb( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi, BOOL vertical)
{
INT pos = SCROLL_TrackingPos;
INT max_size;
if( vertical )
max_size = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
else
max_size = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
max_size -= (psbi->dxyLineButton -SCROLL_ARROW_THUMB_OVERLAP) + psbi->dxyLineButton;
if( pos < (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP) )
pos = (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP);
else if( pos > max_size )
pos = max_size;
SCROLL_DrawInterior(pcontext, psbi, pos, vertical, SCROLL_THUMB, 0);
SCROLL_MovingThumb = !SCROLL_MovingThumb;
}
void
ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT nBar, POINT* pt)
{
SCROLLINFO si;
SCROLLBARINFO sbi;
BOOL vertical;
enum SCROLL_HITTEST htHot = SCROLL_NOWHERE;
/* Retrieve scrollbar info */
sbi.cbSize = sizeof(sbi);
si.cbSize = sizeof(si);
si.fMask = SIF_ALL ;
GetScrollInfo(pcontext->hWnd, nBar, &si);
GetScrollBarInfo(pcontext->hWnd, SCROLL_getObjectId(nBar), &sbi);
vertical = SCROLL_IsVertical(pcontext->hWnd, nBar);
if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE &&
sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE )
{
sbi.xyThumbTop = 0;
}
#ifndef ROS_SUCKS
/* The scrollbar rect is in screen coordinates */
// OffsetRect(&sbi.rcScrollBar, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
#endif
if(pt)
{
ScreenToWindow(pcontext->hWnd, pt);
htHot = SCROLL_HitTest(pcontext->hWnd, &sbi, vertical, *pt, FALSE);
}
if (((nBar == SB_VERT) && !(pcontext->wi.dwStyle & WS_VSCROLL)) ||
((nBar == SB_HORZ) && !(pcontext->wi.dwStyle & WS_HSCROLL))) return;
/* do not draw if the scrollbar rectangle is empty */
if(IsRectEmpty(&sbi.rcScrollBar)) return;
/* Draw the scrollbar */
SCROLL_DrawArrows( pcontext, &sbi, vertical, 0, htHot );
SCROLL_DrawInterior( pcontext, &sbi, sbi.xyThumbTop, vertical, 0, htHot );
}
/***********************************************************************
* SCROLL_ClipPos
*/
static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
{
if( pt.x < lpRect->left )
pt.x = lpRect->left;
else
if( pt.x > lpRect->right )
pt.x = lpRect->right;
if( pt.y < lpRect->top )
pt.y = lpRect->top;
else
if( pt.y > lpRect->bottom )
pt.y = lpRect->bottom;
return pt;
}
/***********************************************************************
* SCROLL_GetThumbVal
*
* Compute the current scroll position based on the thumb position in pixels
* from the top of the scroll-bar.
*/
static UINT SCROLL_GetThumbVal( SCROLLINFO *psi, RECT *rect,
BOOL vertical, INT pos )
{
INT thumbSize;
INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
INT range;
if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
return psi->nMin;
if (psi->nPage)
{
thumbSize = MulDiv(pixels,psi->nPage,(psi->nMax-psi->nMin+1));
if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
}
else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
if ((pixels -= thumbSize) <= 0) return psi->nMin;
pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
if (pos > pixels) pos = pixels;
if (!psi->nPage)
range = psi->nMax - psi->nMin;
else
range = psi->nMax - psi->nMin - psi->nPage + 1;
return psi->nMin + MulDiv(pos, range, pixels);
}
static void
SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
{
/* Previous mouse position for timer events */
static POINT prevPt;
/* Thumb position when tracking started. */
static UINT trackThumbPos;
/* Position in the scroll-bar of the last button-down event. */
static INT lastClickPos;
/* Position in the scroll-bar of the last mouse event. */
static INT lastMousePos;
enum SCROLL_HITTEST hittest;
HWND hwndOwner, hwndCtl;
BOOL vertical;
SCROLLINFO si;
SCROLLBARINFO sbi;
DRAW_CONTEXT context;
si.cbSize = sizeof(si);
sbi.cbSize = sizeof(sbi);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, nBar, &si);
GetScrollBarInfo(hwnd, SCROLL_getObjectId(nBar), &sbi);
vertical = SCROLL_IsVertical(hwnd, nBar);
if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE &&
sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE )
{
return;
}
ThemeInitDrawContext(&context, hwnd, 0);
#ifndef ROS_SUCKS
/* The scrollbar rect is in screen coordinates */
// OffsetRect(&sbi.rcScrollBar, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
#endif
if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN))
return;
hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd;
hwndCtl = (nBar == SB_CTL) ? hwnd : 0;
switch(msg)
{
case WM_LBUTTONDOWN: /* Initialise mouse tracking */
HideCaret(hwnd); /* hide caret while holding down LBUTTON */
SCROLL_trackVertical = vertical;
SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE );
lastClickPos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left);
lastMousePos = lastClickPos;
trackThumbPos = sbi.xyThumbTop;
prevPt = pt;
SetCapture( hwnd );
break;
case WM_MOUSEMOVE:
hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, TRUE );
prevPt = pt;
break;
case WM_LBUTTONUP:
hittest = SCROLL_NOWHERE;
ReleaseCapture();
/* if scrollbar has focus, show back caret */
if (hwnd==GetFocus())
ShowCaret(hwnd);
break;
case WM_SYSTIMER:
pt = prevPt;
hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE );
break;
default:
return; /* Should never happen */
}
//TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
// hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest );
switch(SCROLL_trackHitTest)
{
case SCROLL_NOWHERE: /* No tracking in progress */
break;
case SCROLL_TOP_ARROW:
if (hittest == SCROLL_trackHitTest)
{
SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 );
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
{
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_LINEUP, (LPARAM)hwndCtl );
}
SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
}
else
{
SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 );
KillSystemTimer( hwnd, SCROLL_TIMER );
}
break;
case SCROLL_TOP_RECT:
SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0);
if (hittest == SCROLL_trackHitTest)
{
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
{
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_PAGEUP, (LPARAM)hwndCtl );
}
SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
}
else KillSystemTimer( hwnd, SCROLL_TIMER );
break;
case SCROLL_THUMB:
if (msg == WM_LBUTTONDOWN)
{
SCROLL_TrackingWin = hwnd;
SCROLL_TrackingBar = nBar;
SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar,
vertical, SCROLL_TrackingPos );
if (!SCROLL_MovingThumb)
SCROLL_DrawMovingThumb(&context, &sbi, vertical);
}
else if (msg == WM_LBUTTONUP)
{
if (SCROLL_MovingThumb)
SCROLL_DrawMovingThumb(&context, &sbi, vertical);
SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, SCROLL_trackHitTest );
}
else /* WM_MOUSEMOVE */
{
INT pos;
if (!SCROLL_PtInRectEx( &sbi.rcScrollBar, pt, vertical ))
pos = lastClickPos;
else
{
pt = SCROLL_ClipPos( &sbi.rcScrollBar, pt );
pos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left);
}
if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) )
{
if (SCROLL_MovingThumb)
SCROLL_DrawMovingThumb( &context, &sbi, vertical);
lastMousePos = pos;
SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar,
vertical,
SCROLL_TrackingPos );
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
(LPARAM)hwndCtl );
if (!SCROLL_MovingThumb)
SCROLL_DrawMovingThumb( &context, &sbi, vertical);
}
}
break;
case SCROLL_BOTTOM_RECT:
if (hittest == SCROLL_trackHitTest)
{
SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0 );
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
{
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_PAGEDOWN, (LPARAM)hwndCtl );
}
SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
}
else
{
SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, 0 );
KillSystemTimer( hwnd, SCROLL_TIMER );
}
break;
case SCROLL_BOTTOM_ARROW:
if (hittest == SCROLL_trackHitTest)
{
SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 );
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
{
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_LINEDOWN, (LPARAM)hwndCtl );
}
SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
}
else
{
SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 );
KillSystemTimer( hwnd, SCROLL_TIMER );
}
break;
}
if (msg == WM_LBUTTONDOWN)
{
if (hittest == SCROLL_THUMB)
{
UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical,
trackThumbPos + lastMousePos - lastClickPos );
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl );
}
}
if (msg == WM_LBUTTONUP)
{
hittest = SCROLL_trackHitTest;
SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
if (hittest == SCROLL_THUMB)
{
UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical,
trackThumbPos + lastMousePos - lastClickPos );
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl );
}
/* SB_ENDSCROLL doesn't report thumb position */
SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_ENDSCROLL, (LPARAM)hwndCtl );
/* Terminate tracking */
SCROLL_TrackingWin = 0;
}
ThemeCleanupDrawContext(&context);
}
static void
SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt )
{
MSG msg;
ScreenToWindow(hwnd, &pt);
SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
do
{
if (!GetMessageW( &msg, 0, 0, 0 )) break;
if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue;
if (msg.message == WM_LBUTTONUP ||
msg.message == WM_MOUSEMOVE ||
(msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER))
{
pt.x = GET_X_LPARAM(msg.lParam);
pt.y = GET_Y_LPARAM(msg.lParam);
ClientToScreen(hwnd, &pt);
ScreenToWindow(hwnd, &pt);
SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
}
else
{
TranslateMessage( &msg );
DispatchMessageW( &msg );
}
if (!IsWindow( hwnd ))
{
ReleaseCapture();
break;
}
} while (msg.message != WM_LBUTTONUP && GetCapture() == hwnd);
}
void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
{
INT scrollbar;
if ((wParam & 0xfff0) == SC_HSCROLL)
{
if ((wParam & 0x0f) != HTHSCROLL) return;
scrollbar = SB_HORZ;
}
else /* SC_VSCROLL */
{
if ((wParam & 0x0f) != HTVSCROLL) return;
scrollbar = SB_VERT;
}
SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
}

View file

@ -0,0 +1,106 @@
typedef struct _WND_CONTEXT
{
BOOL HasAppDefinedRgn;
BOOL HasThemeRgn;
BOOL UpdatingRgn;
} WND_CONTEXT, *PWND_CONTEXT;
typedef struct _DRAW_CONTEXT
{
HWND hWnd;
HDC hDC;
HTHEME theme;
HTHEME scrolltheme;
HTHEME hPrevTheme;
WINDOWINFO wi;
BOOL Active; /* wi.dwWindowStatus isn't correct for mdi child windows */
HRGN hRgn;
int CaptionHeight;
/* for double buffering */
HDC hDCScreen;
HBITMAP hbmpOld;
} 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;
/* Scroll-bar hit testing */
enum SCROLL_HITTEST
{
SCROLL_NOWHERE, /* Outside the scroll bar */
SCROLL_TOP_ARROW, /* Top or left arrow */
SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
SCROLL_THUMB, /* Thumb rectangle */
SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
};
#define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
(WindowRect.right - WindowRect.left == ParentClientRect.right) && \
(WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
#define HAS_MENU(hwnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
#define BUTTON_GAP_SIZE 2
#define MENU_BAR_ITEMS_SPACE (12)
#define SCROLL_TIMER 0 /* Scroll timer id */
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 0
/* Delay (in ms) before first repetition when holding the button down */
#define SCROLL_FIRST_DELAY 200
/* Delay (in ms) between scroll repetitions */
#define SCROLL_REPEAT_DELAY 50
/* Minimum size of the thumb in pixels */
#define SCROLL_MIN_THUMB 6
/* Minimum size of the rectangle between the arrows */
#define SCROLL_MIN_RECT 4
void
ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT Bar, POINT* pt);
VOID
NC_TrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt);
void
ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
HWND hWnd,
HRGN hRgn);
void
ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext);
PWND_CONTEXT
ThemeGetWndContext(HWND hWnd);
extern ATOM atWindowTheme;
extern ATOM atWndContrext;

File diff suppressed because it is too large Load diff

View file

@ -31,9 +31,11 @@
#include "vfwmsgs.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "uxundoc.h"
#include "uxthemedll.h"
#include "msstyles.h"
#include "ncthm.h"
#include "wine/debug.h"
@ -61,9 +63,10 @@ HINSTANCE hDllInst;
ATOM atDialogThemeEnabled;
static DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
static ATOM atWindowTheme;
ATOM atWindowTheme;
static ATOM atSubAppName;
static ATOM atSubIdList;
ATOM atWndContrext;
static BOOL bThemeActive = FALSE;
static WCHAR szCurrentTheme[MAX_PATH];
@ -79,7 +82,7 @@ static BOOL CALLBACK UXTHEME_broadcast_msg_enumchild (HWND hWnd, LPARAM msg)
}
/* Broadcast a message to *all* windows, including children */
static BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
{
if (hWnd == NULL)
{
@ -140,7 +143,6 @@ static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue,
}
}
RegCloseKey(hKey);
return dwRet;
}
@ -149,7 +151,7 @@ static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue,
*
* Set the current active theme from the registry
*/
static void UXTHEME_LoadTheme(void)
void UXTHEME_LoadTheme(BOOL bLoad)
{
HKEY hKey;
DWORD buffsize;
@ -157,29 +159,36 @@ static void UXTHEME_LoadTheme(void)
WCHAR tmp[10];
PTHEME_FILE pt;
/* Get current theme configuration */
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
TRACE("Loading theme config\n");
buffsize = sizeof(tmp)/sizeof(tmp[0]);
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
bThemeActive = (tmp[0] != '0');
if(bLoad == TRUE)
{
/* Get current theme configuration */
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
TRACE("Loading theme config\n");
buffsize = sizeof(tmp)/sizeof(tmp[0]);
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
bThemeActive = (tmp[0] != '0');
}
else {
bThemeActive = FALSE;
TRACE("Failed to get ThemeActive: %d\n", GetLastError());
}
buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
szCurrentColor[0] = '\0';
buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
szCurrentSize[0] = '\0';
if (query_reg_path (hKey, szDllName, szCurrentTheme))
szCurrentTheme[0] = '\0';
RegCloseKey(hKey);
}
else {
bThemeActive = FALSE;
TRACE("Failed to get ThemeActive: %d\n", GetLastError());
}
buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
szCurrentColor[0] = '\0';
buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
szCurrentSize[0] = '\0';
if (query_reg_path (hKey, szDllName, szCurrentTheme))
szCurrentTheme[0] = '\0';
RegCloseKey(hKey);
else
TRACE("Failed to open theme registry key\n");
}
else
TRACE("Failed to open theme registry key\n");
{
bThemeActive = FALSE;
}
if(bThemeActive) {
/* Make sure the theme requested is actually valid */
@ -543,8 +552,7 @@ void UXTHEME_InitSystem(HINSTANCE hInst)
atSubAppName = GlobalAddAtomW(szSubAppName);
atSubIdList = GlobalAddAtomW(szSubIdList);
atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
UXTHEME_LoadTheme();
atWndContrext = GlobalAddAtomW(L"ux_WndContext");
}
/***********************************************************************
@ -973,7 +981,7 @@ HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
* Success: S_OK
* Failure: HRESULT error-code
*/
HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, ENUMTHEMEPROC callback,
LPVOID lpData)
{
WCHAR szDir[MAX_PATH];
@ -1171,7 +1179,7 @@ HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
* any other purpose
*/
HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
ParseThemeIniFileProc callback, LPVOID lpData)
PARSETHEMEINIFILEPROC callback, LPVOID lpData)
{
FIXME("%s %s: stub\n", debugstr_w(pszIniFileName), debugstr_w(pszUnknown));
return ERROR_CALL_NOT_IMPLEMENTED;

View file

@ -0,0 +1,398 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS uxtheme.dll
* FILE: dll/win32/uxtheme/themehooks.c
* PURPOSE: uxtheme user api hook functions
* PROGRAMMER: Giannis Adamopoulos
*/
#include <windows.h>
#include <undocuser.h>
#include "vfwmsgs.h"
#include "uxtheme.h"
#include "uxthemedll.h"
#include "ncthm.h"
#include "tmschema.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
extern HINSTANCE hDllInst;
LRESULT CALLBACK ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc);
USERAPIHOOK user32ApiHook;
BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
PWND_CONTEXT ThemeGetWndContext(HWND hWnd)
{
PWND_CONTEXT pcontext;
pcontext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
if(pcontext == NULL)
{
pcontext = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(WND_CONTEXT));
if(pcontext == NULL)
{
return NULL;
}
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), pcontext);
}
return pcontext;
}
void ThemeDetroyWndContext(HWND hWnd)
{
PWND_CONTEXT pContext;
DWORD ProcessId;
/*Do not destroy WND_CONTEXT of a window that belong to another process */
GetWindowThreadProcessId(hWnd, &ProcessId);
if(ProcessId != GetCurrentProcessId())
{
return;
}
pContext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
if(pContext == NULL)
{
return;
}
if(pContext->HasThemeRgn)
{
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
HeapFree(GetProcessHeap(), 0, pContext);
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), NULL);
}
static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
{
ThemeDetroyWndContext(hWnd);
return TRUE;
}
static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
{
if (hWnd == NULL)
{
EnumWindows (ThemeCleanupWndContext, 0);
}
else
{
ThemeDetroyWndContext(hWnd);
EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
}
return TRUE;
}
void SetThemeRegion(HWND hWnd, PWND_CONTEXT pcontext)
{
HTHEME hTheme;
RECT rcWindow;
HRGN hrgn, hrgn1;
int CaptionHeight, iPart;
WINDOWINFO wi;
if(!IsAppThemed())
{
if(pcontext->HasThemeRgn)
{
pcontext->HasThemeRgn = FALSE;
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
return;
}
wi.cbSize = sizeof(wi);
GetWindowInfo(hWnd, &wi);
if((wi.dwStyle & WS_CAPTION)!=WS_CAPTION)
{
return;
}
/* Get the caption part id */
if (wi.dwExStyle & WS_EX_TOOLWINDOW)
iPart = WP_SMALLCAPTION;
else if (wi.dwStyle & WS_MAXIMIZE)
iPart = WP_MAXCAPTION;
else
iPart = WP_CAPTION;
pcontext->HasThemeRgn = TRUE;
CaptionHeight = wi.cyWindowBorders;
CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
GetWindowRect(hWnd, &rcWindow);
rcWindow.right -= rcWindow.left;
rcWindow.bottom = CaptionHeight;
rcWindow.top = 0;
rcWindow.left = 0;
hTheme = OpenThemeData (hWnd, L"WINDOW");
GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
CloseThemeData(hTheme);
GetWindowRect(hWnd, &rcWindow);
rcWindow.right -= rcWindow.left;
rcWindow.bottom -= rcWindow.top;
rcWindow.top = CaptionHeight;
rcWindow.left = 0;
hrgn1 = CreateRectRgnIndirect(&rcWindow);
CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
DeleteObject(hrgn1);
user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
}
int OnPostWinPosChanged(HWND hWnd)
{
PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
if(pcontext &&
pcontext->HasAppDefinedRgn == FALSE &&
pcontext->UpdatingRgn == FALSE)
{
pcontext->UpdatingRgn = TRUE;
SetThemeRegion(hWnd, pcontext);
pcontext = ThemeGetWndContext(hWnd);
pcontext->UpdatingRgn = FALSE;
}
return 0;
}
/**********************************************************************
* Hook Functions
*/
static LRESULT CALLBACK
ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(!IsThemeActive())
{
return user32ApiHook.DefWindowProcW(hWnd,
Msg,
wParam,
lParam);
}
return ThemeWndProc(hWnd,
Msg,
wParam,
lParam,
user32ApiHook.DefWindowProcW);
}
static LRESULT CALLBACK
ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(!IsThemeActive())
{
return user32ApiHook.DefWindowProcA(hWnd,
Msg,
wParam,
lParam);
}
return ThemeWndProc(hWnd,
Msg,
wParam,
lParam,
user32ApiHook.DefWindowProcA);
}
static LRESULT CALLBACK
ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
switch(Msg)
{
case WM_THEMECHANGED:
UXTHEME_LoadTheme(TRUE);
return 0;
}
return 0;
}
static LRESULT CALLBACK
ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
switch(Msg)
{
case WM_WINDOWPOSCHANGED:
{
return OnPostWinPosChanged(hWnd);
}
case WM_DESTROY:
{
ThemeDetroyWndContext(hWnd);
return 0;
}
}
return 0;
}
int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
{
PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
if(pcontext)
{
pcontext->HasAppDefinedRgn = TRUE;
pcontext->HasThemeRgn = FALSE;
}
return user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
}
/**********************************************************************
* Exports
*/
BOOL CALLBACK
ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
{
/* Sanity checks for the caller */
if (!puah || State != uahLoadInit)
{
UXTHEME_LoadTheme(FALSE);
ThemeCleanupWndContext(NULL, 0);
return TRUE;
}
/* Store the original functions from user32 */
user32ApiHook = *puah;
puah->DefWindowProcA = ThemeDefWindowProcA;
puah->DefWindowProcW = ThemeDefWindowProcW;
puah->PreWndProc = ThemePreWindowProc;
puah->PostWndProc = ThemePostWindowProc;
puah->PreDefDlgProc = ThemePreWindowProc;
puah->PostDefDlgProc = ThemePostWindowProc;
puah->DefWndProcArray.MsgBitArray = gabDWPmessages;
puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
puah->WndProcArray.MsgBitArray = gabMSGPmessages;
puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
puah->DlgProcArray.MsgBitArray = gabMSGPmessages;
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
puah->SetWindowRgn = ThemeSetWindowRgn;
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
UXTHEME_LoadTheme(TRUE);
return TRUE;
}
typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
BOOL WINAPI
ThemeHooksInstall()
{
PVOID lpFunc;
OSVERSIONINFO osvi;
BOOL ret;
lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
ret = lpfuncxp(hDllInst, ThemeInitApiHook);
}
else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
USERAPIHOOKINFO uah;
uah.m_size = sizeof(uah);
uah.m_dllname1 = L"uxtheme.dll";
uah.m_funname1 = L"ThemeInitApiHook";
uah.m_dllname2 = NULL;
uah.m_funname2 = NULL;
ret = lpfunc2003(&uah);
}
else
{
UNIMPLEMENTED;
ret = FALSE;
}
UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
return ret;
}
BOOL WINAPI
ThemeHooksRemove()
{
BOOL ret;
ret = UnregisterUserApiHook();
UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
return ret;
}

View file

@ -11,9 +11,12 @@
<file>main.c</file>
<file>metric.c</file>
<file>msstyles.c</file>
<file>ncscrollbar.c</file>
<file>nonclient.c</file>
<file>property.c</file>
<file>stylemap.c</file>
<file>system.c</file>
<file>themehooks.c</file>
<file>uxini.c</file>
<file>version.rc</file>
<library>wine</library>

View file

@ -29,8 +29,8 @@
31 stub -noname InitUserTheme
32 stub -noname InitUserRegistry
33 stub -noname ReestablishServerConnection
34 stub -noname ThemeHooksInstall
35 stub -noname ThemeHooksRemove
34 stdcall -noname ThemeHooksInstall()
35 stdcall -noname ThemeHooksRemove()
36 stub -noname RefreshThemeForTS
43 stub -noname ClassicGetSystemMetrics
44 stub -noname ClassicSystemParametersInfoA
@ -95,3 +95,4 @@
@ stdcall OpenThemeData(ptr wstr)
@ stdcall SetThemeAppProperties(long)
@ stdcall SetWindowTheme(ptr wstr wstr)
@ stdcall ThemeInitApiHook(long ptr)

View file

@ -21,80 +21,9 @@
#ifndef __WINE_UXTHEMEDLL_H
#define __WINE_UXTHEMEDLL_H
typedef HANDLE HTHEMEFILE;
/**********************************************************************
* EnumThemeProc
*
* Callback function for EnumThemes.
*
* RETURNS
* TRUE to continue enumeration, FALSE to stop
*
* PARAMS
* lpReserved Always 0
* pszThemeFileName Full path to theme msstyles file
* pszThemeName Display name for theme
* pszToolTip Tooltip name for theme
* lpReserved2 Always 0
* lpData Value passed through lpData from EnumThemes
*/
typedef BOOL (CALLBACK *EnumThemeProc)(LPVOID lpReserved, LPCWSTR pszThemeFileName,
LPCWSTR pszThemeName, LPCWSTR pszToolTip, LPVOID lpReserved2,
LPVOID lpData);
/**********************************************************************
* ParseThemeIniFileProc
*
* Callback function for ParseThemeIniFile.
*
* RETURNS
* TRUE to continue enumeration, FALSE to stop
*
* PARAMS
* dwType Entry type
* pszParam1 Use defined by entry type
* pszParam2 Use defined by entry type
* pszParam3 Use defined by entry type
* dwParam Use defined by entry type
* lpData Value passed through lpData from ParseThemeIniFile
*
* NOTES
* I don't know what the valid entry types are
*/
typedef BOOL (CALLBACK*ParseThemeIniFileProc)(DWORD dwType, LPWSTR pszParam1,
LPWSTR pszParam2, LPWSTR pszParam3,
DWORD dwParam, LPVOID lpData);
/* Structure filled in by EnumThemeColors() and EnumeThemeSizes() with the
* various strings for a theme color or size. */
typedef struct tagTHEMENAMES
{
WCHAR szName[MAX_PATH+1];
WCHAR szDisplayName[MAX_PATH+1];
WCHAR szTooltip[MAX_PATH+1];
} THEMENAMES, *PTHEMENAMES;
/* Declarations for undocumented functions for use internally */
DWORD WINAPI QueryThemeServices(void);
HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile,
DWORD unknown);
HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile);
HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd);
HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
DWORD dwColorNameLen, LPWSTR pszSizeName,
DWORD dwSizeNameLen);
HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
LPVOID lpData);
HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
DWORD dwColorNum, PTHEMENAMES pszColorNames);
HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
DWORD dwSizeNum, PTHEMENAMES pszColorNames);
HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
ParseThemeIniFileProc callback, LPVOID lpData);
extern void UXTHEME_InitSystem(HINSTANCE hInst);
extern void UXTHEME_LoadTheme(BOOL bLoad);
extern BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg);
/* No alpha blending */
#define ALPHABLEND_NONE 0