- DrawCaption

- Patch by Saveliy Tretiakov, new NtUserDrawCaption implementation.
    See URL for more details, http://www.reactos.org/archives/public/ros-dev/2006-July/008575.html


svn path=/trunk/; revision=23525
This commit is contained in:
James Tabor 2006-08-08 20:00:53 +00:00
parent 0468c25a60
commit 43bcb034b6
7 changed files with 627 additions and 411 deletions

View file

@ -1097,231 +1097,9 @@ AdjustWindowRect(LPRECT lpRect,
BOOL WINAPI
DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
{
NONCLIENTMETRICSW nclm;
BOOL result = FALSE;
RECT r = *lprc;
UINT VCenter = 0, Padding = 0, Height;
ULONG Style;
WCHAR buffer[256];
HFONT hFont = NULL;
HFONT hOldFont = NULL;
HBRUSH OldBrush = NULL;
HDC MemDC = NULL;
int ButtonWidth;
COLORREF OldTextColor;
#ifdef DOUBLE_BUFFER_CAPTION
HBITMAP MemBMP = NULL, OldBMP = NULL;
MemDC = CreateCompatibleDC(hDC);
if (! MemDC) goto cleanup;
MemBMP = CreateCompatibleBitmap(hDC, lprc->right - lprc->left, lprc->bottom - lprc->top);
if (! MemBMP) goto cleanup;
OldBMP = SelectObject(MemDC, MemBMP);
if (! OldBMP) goto cleanup;
#else
MemDC = hDC;
OffsetViewportOrgEx(MemDC, lprc->left, lprc->top, NULL);
#endif
Style = GetWindowLongW(hWnd, GWL_STYLE);
/* Windows behaves like this */
Height = GetSystemMetrics(SM_CYCAPTION) - 1;
VCenter = (lprc->bottom - lprc->top) / 2;
Padding = VCenter - (Height / 2);
r.left = Padding;
r.right = r.left + (lprc->right - lprc->left);
r.top = Padding;
r.bottom = r.top + (Height / 2);
// Draw the caption background
if (uFlags & DC_INBUTTON)
{
OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_BTNFACE : COLOR_BTNSHADOW) );
if (! OldBrush) goto cleanup;
if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
}
else
{
if (uFlags & DC_GRADIENT)
{
static GRADIENT_RECT gcap = {0, 1};
TRIVERTEX vert[2];
COLORREF Colors[2];
LONG xx;
r.right = (lprc->right - lprc->left);
if (uFlags & DC_SMALLCAP)
ButtonWidth = GetSystemMetrics(SM_CXSMSIZE) - 2;
else
ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
//if (Style & WS_SYSMENU)
//{
// r.right -= 3 + ButtonWidth;
// if (! (uFlags & DC_SMALLCAP))
// {
// if(Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
// r.right -= 2 + 2 * ButtonWidth;
// else
// r.right -= 2;
// r.right -= 2;
// }
//}
Colors[0] = GetSysColor((uFlags & DC_ACTIVE) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
Colors[1] = GetSysColor((uFlags & DC_ACTIVE) ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION);
vert[0].x = r.left;
vert[0].y = 0;
vert[0].Red = GetRValue(Colors[0]) << 8;
vert[0].Green = GetGValue(Colors[0]) << 8;
vert[0].Blue = GetBValue(Colors[0]) << 8;
vert[0].Alpha = 0;
vert[1].x = r.right;
vert[1].y = lprc->bottom - lprc->top;
vert[1].Red = GetRValue(Colors[1]) << 8;
vert[1].Green = GetGValue(Colors[1]) << 8;
vert[1].Blue = GetBValue(Colors[1]) << 8;
vert[1].Alpha = 0;
GdiGradientFill(MemDC, vert, 2, &gcap, 1, GRADIENT_FILL_RECT_V);
if ((uFlags & DC_ICON) && (Style & WS_SYSMENU) && !(uFlags & DC_SMALLCAP))
{
r.top --;
SetBkMode( MemDC, TRANSPARENT );
xx = GetSystemMetrics(SM_CXSIZE) + Padding;
if (UserDrawSysMenuButton(hWnd, MemDC, &r, FALSE))
r.left += xx;
r.top ++;
}
if(OldBrush)
{
SelectObject(MemDC, OldBrush);
OldBrush = NULL;
}
//xx = lprc->right - lprc->left - r.right;
//if(xx > 0)
//{
// OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION));
// if (!OldBrush) goto cleanup;
// PatBlt(MemDC, r.right, 0, xx, lprc->bottom - lprc->top, PATCOPY);
//}
}
else
{
OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
if (! OldBrush) goto cleanup;
if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
}
}
if ((uFlags & DC_ICON) && !(uFlags & DC_GRADIENT) && (Style & WS_SYSMENU) && !(uFlags & DC_SMALLCAP))
{
/* For some reason the icon isn't centered correctly... */
r.top --;
if (UserDrawSysMenuButton(hWnd, MemDC, &r, FALSE))
r.left += GetSystemMetrics(SM_CXSIZE) + Padding;
r.top ++;
}
r.top ++;
r.left += 2;
r.bottom = r.top + Height;
if ((uFlags & DC_TEXT) && (NtUserInternalGetWindowText( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) )))
{
if(!(uFlags & DC_GRADIENT))
{
r.right = (lprc->right - lprc->left);
if (uFlags & DC_SMALLCAP)
ButtonWidth = GetSystemMetrics(SM_CXSMSIZE) - 2;
else
ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
if (Style & WS_SYSMENU)
{
r.right -= 3 + ButtonWidth;
if (! (uFlags & DC_SMALLCAP))
{
if(Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
r.right -= 2 + 2 * ButtonWidth;
else
r.right -= 2;
r.right -= 2;
}
}
}
nclm.cbSize = sizeof(nclm);
if (! SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &nclm, 0)) goto cleanup;
SetBkMode( MemDC, TRANSPARENT );
if (uFlags & DC_SMALLCAP)
hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
else
hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
if (! hFont) goto cleanup;
hOldFont = SelectObject(MemDC, hFont);
if (! hOldFont) goto cleanup;
if (uFlags & DC_INBUTTON)
OldTextColor = SetTextColor(MemDC, GetSysColor(uFlags & DC_ACTIVE ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
else
OldTextColor = SetTextColor(MemDC, GetSysColor(uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
DrawTextW(MemDC, buffer, wcslen(buffer), &r, DT_VCENTER | DT_END_ELLIPSIS);
SetTextColor(MemDC, OldTextColor);
}
#if 0
if (uFlags & DC_BUTTONS)
{
// Windows XP draws the caption buttons with DC_BUTTONS
// r.left += GetSystemMetrics(SM_CXSIZE) + 1;
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
// r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
}
#endif
#ifdef DOUBLE_BUFFER_CAPTION
if (! BitBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
MemDC, 0, 0, SRCCOPY)) goto cleanup;
#endif
result = TRUE;
cleanup :
if (MemDC)
{
if (OldBrush) SelectObject(MemDC, OldBrush);
if (hOldFont) SelectObject(MemDC, hOldFont);
if (hFont) DeleteObject(hFont);
#ifdef DOUBLE_BUFFER_CAPTION
if (OldBMP) SelectObject(MemDC, OldBMP);
if (MemBMP) DeleteObject(MemBMP);
DeleteDC(MemDC);
#else
OffsetViewportOrgEx(MemDC, -lprc->left, -lprc->top, NULL);
#endif
}
return result;
return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
}
/*
* @unimplemented
*/

View file

@ -689,12 +689,11 @@ NtUserDragDetect(
DWORD
NTAPI
NtUserDragObject(
HWND hwnd1,
HWND hwnd2,
UINT u1,
DWORD dw1,
HCURSOR hc1
);
HWND hwnd1,
HWND hwnd2,
UINT u1,
DWORD dw1,
HCURSOR hc1);
DWORD
NTAPI
@ -704,24 +703,24 @@ NtUserDrawAnimatedRects(
DWORD Unknown2,
DWORD Unknown3);
DWORD
BOOL
NTAPI
NtUserDrawCaption(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3);
HWND hWnd,
HDC hDc,
LPCRECT lpRc,
UINT uFlags);
DWORD
NTAPI
STDCALL
NtUserDrawCaptionTemp(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6);
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6);
BOOL
NTAPI

View file

@ -188,12 +188,18 @@ IntSetSysColors(UINT nColors, INT *Elements, COLORREF *Colors);
BOOL FASTCALL
IntGetSysColorBrushes(HBRUSH *Brushes, UINT nBrushes);
HGDIOBJ FASTCALL
IntGetSysColorBrush(INT Object);
BOOL FASTCALL
IntGetSysColorPens(HPEN *Pens, UINT nPens);
BOOL FASTCALL
IntGetSysColors(COLORREF *Colors, UINT nColors);
DWORD FASTCALL
IntGetSysColor(INT nIndex);
/* Other Stuff */
INT FASTCALL

View file

@ -72,7 +72,6 @@ IntGetCursorLocation(PWINSTATION_OBJECT WinSta, POINT *loc)
}
static
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
{
PCURICON_OBJECT CurIcon;
@ -1346,6 +1345,191 @@ DoStretchBlt(HDC DcDest, int XDest, int YDest, int WidthDest, int HeightDest,
(Rop3), 0)
#endif /* STRETCH_CAN_SRCCOPY_ONLY */
BOOL
UserDrawIconEx(
HDC hDc,
INT xLeft,
INT yTop,
PCURICON_OBJECT pIcon,
INT cxWidth,
INT cyHeight,
UINT istepIfAniCur,
HBRUSH hbrFlickerFreeDraw,
UINT diFlags)
{
BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor;
BITMAP bmpMask, bmpColor;
COLORREF oldFg, oldBg;
BOOL DoFlickerFree;
INT nStretchMode;
SIZE IconSize;
HDC hdcOff;
HGDIOBJ hOldOffBrush = 0;
HGDIOBJ hOldOffBmp = 0;
HBITMAP hbmOff = 0;
HDC hdcMem = 0;
HGDIOBJ hOldMem;
hbmMask = pIcon->IconInfo.hbmMask;
hbmColor = pIcon->IconInfo.hbmColor;
if(istepIfAniCur)
DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
if(!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), &bmpMask))
{
return FALSE;
}
if(hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), &bmpColor))
{
return FALSE;
}
if(hbmColor)
{
IconSize.cx = bmpColor.bmWidth;
IconSize.cy = bmpColor.bmHeight;
}
else
{
IconSize.cx = bmpMask.bmWidth;
IconSize.cy = bmpMask.bmHeight / 2;
}
if(!diFlags)
diFlags = DI_NORMAL;
if(!cxWidth)
cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
if(!cyHeight)
cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CYICON) : IconSize.cy);
DoFlickerFree = (hbrFlickerFreeDraw &&
(NtGdiGetObjectType(hbrFlickerFreeDraw) == OBJ_BRUSH));
if(DoFlickerFree)
{
RECT r;
r.right = cxWidth;
r.bottom = cyHeight;
hdcOff = NtGdiCreateCompatibleDC(hDc);
if(!hdcOff)
{
DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
return FALSE;
}
hbmOff = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
if(!hbmOff)
{
DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
goto cleanup;
}
hOldOffBrush = NtGdiSelectObject(hdcOff, hbrFlickerFreeDraw);
if(!hOldOffBrush)
{
DPRINT1("NtGdiSelectObject() failed!\n");
goto cleanup;
}
hOldOffBmp = NtGdiSelectObject(hdcOff, hbmOff);
if(!hOldOffBmp)
{
DPRINT1("NtGdiSelectObject() failed!\n");
goto cleanup;
}
NtGdiPatBlt(hdcOff, 0, 0, r.right, r.bottom, PATCOPY);
}
else hdcOff = hDc;
hdcMem = NtGdiCreateCompatibleDC(hDc);
if(!hdcMem)
{
DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
goto cleanup;
}
nStretchMode = NtGdiSetStretchBltMode(hdcOff, STRETCH_DELETESCANS);
oldFg = NtGdiSetTextColor(hdcOff, RGB(0, 0, 0));
oldBg = NtGdiSetBkColor(hdcOff, RGB(255, 255, 255));
if(diFlags & DI_MASK)
{
hOldMem = NtGdiSelectObject(hdcMem, hbmMask);
if(!hOldMem)
{
DPRINT("NtGdiSelectObject() failed!\n");
goto cleanup;
}
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, 0, IconSize.cx, IconSize.cy,
((diFlags & DI_IMAGE) ? SRCAND : SRCCOPY), FALSE);
if(!hbmColor && (bmpMask.bmHeight == 2 * bmpMask.bmWidth)
&& (diFlags & DI_IMAGE))
{
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, IconSize.cy, IconSize.cx, IconSize.cy, SRCINVERT,
FALSE);
diFlags &= ~DI_IMAGE;
}
NtGdiSelectObject(hdcMem, hOldMem);
}
if(diFlags & DI_IMAGE)
{
hOldMem = NtGdiSelectObject(hdcMem, (hbmColor ? hbmColor : hbmMask));
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, (hbmColor ? 0 : IconSize.cy), IconSize.cx, IconSize.cy,
((diFlags & DI_MASK) ? SRCINVERT : SRCCOPY),
NULL != hbmColor);
NtGdiSelectObject(hdcMem, hOldMem);
}
if(DoFlickerFree)
{
NtGdiBitBlt(hDc, xLeft, yTop, cxWidth,
cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0);
}
NtGdiSetTextColor(hdcOff, oldFg);
NtGdiSetBkColor(hdcOff, oldBg);
NtGdiSetStretchBltMode(hdcOff, nStretchMode);
Ret = TRUE;
cleanup:
if(DoFlickerFree)
{
if(hOldOffBmp) NtGdiSelectObject(hdcOff, hOldOffBmp);
if(hOldOffBrush) NtGdiSelectObject(hdcOff, hOldOffBrush);
if(hbmOff) NtGdiDeleteObject(hbmOff);
if(hdcOff) NtGdiDeleteObjectApp(hdcOff);
}
if(hdcMem) NtGdiDeleteObjectApp(hdcMem);
return Ret;
}
/*
* @implemented
*/
@ -1364,167 +1548,29 @@ NtUserDrawIconEx(
DWORD Unknown0,
DWORD Unknown1)
{
PCURICON_OBJECT CurIcon;
PWINSTATION_OBJECT WinSta;
HBITMAP hbmMask, hbmColor;
BITMAP bmpMask, bmpColor;
BOOL DoFlickerFree;
SIZE IconSize;
COLORREF oldFg, oldBg;
HDC hdcMem, hdcOff = (HDC)0;
HBITMAP hbmOff = (HBITMAP)0;
HGDIOBJ hOldOffBrush = 0, hOldOffBmp = 0, hOldMem;
BOOL Ret = FALSE;
INT nStretchMode;
DECLARE_RETURN(BOOL);
PCURICON_OBJECT pIcon;
BOOL Ret;
DPRINT("Enter NtUserDrawIconEx\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if(WinSta == NULL)
if(!(pIcon = UserGetCurIconObject(hIcon)))
{
RETURN( FALSE);
}
if (!(CurIcon = UserGetCurIconObject(hIcon)))
{
ObDereferenceObject(WinSta);
RETURN(FALSE);
DPRINT1("UserGetCurIconObject() failed!\n");
UserLeave();
return FALSE;
}
hbmMask = CurIcon->IconInfo.hbmMask;
hbmColor = CurIcon->IconInfo.hbmColor;
Ret = UserDrawIconEx(hdc,
xLeft,
yTop,
pIcon,
cxWidth,
cyHeight,
istepIfAniCur,
hbrFlickerFreeDraw,
diFlags);
if(istepIfAniCur)
DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
if(!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), &bmpMask))
goto done;
if(hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), &bmpColor))
goto done;
if(hbmColor)
{
IconSize.cx = bmpColor.bmWidth;
IconSize.cy = bmpColor.bmHeight;
}
else
{
IconSize.cx = bmpMask.bmWidth;
IconSize.cy = bmpMask.bmHeight / 2;
}
if(!diFlags)
diFlags = DI_NORMAL;
if(!cxWidth)
cxWidth = ((diFlags & DI_DEFAULTSIZE) ? UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
if(!cyHeight)
cyHeight = ((diFlags & DI_DEFAULTSIZE) ? UserGetSystemMetrics(SM_CYICON) : IconSize.cy);
DoFlickerFree = (hbrFlickerFreeDraw && (NtGdiGetObjectType(hbrFlickerFreeDraw) == OBJ_BRUSH));
if(DoFlickerFree)
{
RECT r;
r.right = cxWidth;
r.bottom = cyHeight;
hdcOff = NtGdiCreateCompatibleDC(hdc);
if(!hdcOff)
goto done;
hbmOff = NtGdiCreateCompatibleBitmap(hdc, cxWidth, cyHeight);
if(!hbmOff)
{
NtGdiDeleteObjectApp(hdcOff);
goto done;
}
hOldOffBrush = NtGdiSelectObject(hdcOff, hbrFlickerFreeDraw);
hOldOffBmp = NtGdiSelectObject(hdcOff, hbmOff);
NtGdiPatBlt(hdcOff, 0, 0, r.right, r.bottom, PATCOPY);
NtGdiSelectObject(hdcOff, hbmOff);
}
hdcMem = NtGdiCreateCompatibleDC(hdc);
if(!hdcMem)
goto cleanup;
if(!DoFlickerFree)
hdcOff = hdc;
nStretchMode = NtGdiSetStretchBltMode(hdcOff, STRETCH_DELETESCANS);
oldFg = NtGdiSetTextColor(hdcOff, RGB(0, 0, 0));
oldBg = NtGdiSetBkColor(hdcOff, RGB(255, 255, 255));
if(diFlags & DI_MASK)
{
hOldMem = NtGdiSelectObject(hdcMem, hbmMask);
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, 0, IconSize.cx, IconSize.cy,
((diFlags & DI_IMAGE) ? SRCAND : SRCCOPY), FALSE);
if(!hbmColor && (bmpMask.bmHeight == 2 * bmpMask.bmWidth) && (diFlags & DI_IMAGE))
{
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, IconSize.cy, IconSize.cx, IconSize.cy, SRCINVERT,
FALSE);
diFlags &= ~DI_IMAGE;
}
NtGdiSelectObject(hdcMem, hOldMem);
}
if(diFlags & DI_IMAGE)
{
hOldMem = NtGdiSelectObject(hdcMem, (hbmColor ? hbmColor : hbmMask));
DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
(DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
0, (hbmColor ? 0 : IconSize.cy), IconSize.cx, IconSize.cy,
((diFlags & DI_MASK) ? SRCINVERT : SRCCOPY),
NULL != hbmColor);
NtGdiSelectObject(hdcMem, hOldMem);
}
if(DoFlickerFree)
NtGdiBitBlt(hdc, xLeft, yTop, cxWidth, cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0);
NtGdiSetTextColor(hdcOff, oldFg);
NtGdiSetBkColor(hdcOff, oldBg);
NtGdiSetStretchBltMode(hdcOff, nStretchMode);
Ret = TRUE;
cleanup:
if(DoFlickerFree)
{
NtGdiSelectObject(hdcOff, hOldOffBmp);
NtGdiSelectObject(hdcOff, hOldOffBrush);
NtGdiDeleteObject(hbmOff);
NtGdiDeleteObjectApp(hdcOff);
}
if(hdcMem)
NtGdiDeleteObjectApp(hdcMem);
done:
ObDereferenceObject(WinSta);
RETURN( Ret);
CLEANUP:
DPRINT("Leave NtUserDrawIconEx, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
return Ret;
}

View file

@ -191,19 +191,6 @@ NtUserDrawAnimatedRects(
return 0;
}
DWORD
STDCALL
NtUserDrawCaption(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3)
{
UNIMPLEMENTED
return 0;
}
DWORD
STDCALL
NtUserDrawCaptionTemp(

View file

@ -1372,4 +1372,392 @@ CLEANUP:
END_CLEANUP;
}
/* Don't know where to put this */
BOOL FASTCALL IntGdiGradientFill(DC *dc, PTRIVERTEX pVertex, ULONG uVertex, PVOID pMesh, ULONG uMesh, ULONG ulMode);
ULONG FASTCALL IntSystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth,
INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags);
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon);
BOOL
IntDrawSysMenuButton(
PWINDOW_OBJECT pWnd,
HDC hDc,
LPRECT lpRc,
BOOL Down)
{
HICON hIcon;
PCURICON_OBJECT pIcon;
ASSERT(pWnd && lpRc);
/* Get the icon to draw. We don't care about WM_GETICON here. */
hIcon = pWnd->Class->hIconSm;
if(!hIcon)
{
DPRINT("Wnd class has no small icon.\n");
hIcon = pWnd->Class->hIcon;
}
if(!hIcon)
{
DPRINT("Wnd class hasn't any icon.\n");
//FIXME: Draw "winlogo" icon.
return FALSE;
}
if(!(pIcon = UserGetCurIconObject(hIcon)))
{
DPRINT1("UserGetCurIconObject() failed!\n");
return FALSE;
}
return UserDrawIconEx(hDc, lpRc->left, lpRc->top, pIcon,
UserGetSystemMetrics(SM_CXSMICON),
UserGetSystemMetrics(SM_CYSMICON),
0, NULL, DI_NORMAL);
}
BOOL
IntDrawCaptionText(HDC hDc,
const PUNICODE_STRING Text,
const LPRECT lpRc,
UINT uFlags)
{
HFONT hOldFont = NULL, hFont = NULL;
COLORREF OldTextColor;
NONCLIENTMETRICS nclm;
NTSTATUS Status;
INT i;
#ifndef NDEBUG
DPRINT("%s:", __FUNCTION__);
for(i = 0; i < Text->Length/sizeof(WCHAR); i++)
DbgPrint("%C", Text->Buffer[i]);
DbgPrint(", %d\n", Text->Length/sizeof(WCHAR));
#endif
nclm.cbSize = sizeof(nclm);
if(!IntSystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS), &nclm, 0))
{
DPRINT1("%s: IntSystemParametersInfo() failed!\n", __FUNCTION__);
return FALSE;
}
NtGdiSetBkMode(hDc, TRANSPARENT);
if(uFlags & DC_SMALLCAP)
Status = TextIntCreateFontIndirect(&nclm.lfSmCaptionFont, &hFont);
else Status = TextIntCreateFontIndirect(&nclm.lfCaptionFont, &hFont);
if(!NT_SUCCESS(Status))
{
DPRINT1("%s: TextIntCreateFontIndirect() failed! Status: 0x%x\n",
__FUNCTION__, Status);
return FALSE;
}
hOldFont = NtGdiSelectObject(hDc, hFont);
if(!hOldFont)
{
DPRINT1("%s: SelectObject() failed!\n", __FUNCTION__);
NtGdiDeleteObject(hFont);
return FALSE;
}
if(uFlags & DC_INBUTTON)
OldTextColor = NtGdiSetTextColor(hDc, IntGetSysColor(COLOR_BTNTEXT));
else OldTextColor = NtGdiSetTextColor(hDc, IntGetSysColor(uFlags & DC_ACTIVE
? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
//FIXME: If string doesn't fit to rc, truncate it and add ellipsis.
NtGdiTextOut(hDc, lpRc->left,
lpRc->top, Text->Buffer,
Text->Length/sizeof(WCHAR));
NtGdiSetTextColor(hDc, OldTextColor);
NtGdiSelectObject(hDc, hOldFont);
NtGdiDeleteObject(hFont);
return TRUE;
}
BOOL UserDrawCaption(
PWINDOW_OBJECT pWnd,
HDC hDc,
LPCRECT lpRc,
UINT uFlags)
{
BOOL Ret = FALSE;
HBITMAP hMemBmp = NULL, hOldBmp = NULL;
HBRUSH hOldBrush = NULL;
HDC hMemDc = NULL;
ULONG Height;
UINT VCenter = 0, Padding = 0;
RECT r = *lpRc;
LONG ButtonWidth, IconWidth;
BOOL HasIcon;
ASSERT(pWnd != NULL);
hMemBmp = NtGdiCreateCompatibleBitmap(hDc,
lpRc->right - lpRc->left,
lpRc->bottom - lpRc->top);
if(!hMemBmp)
{
DPRINT1("%s: NtGdiCreateCompatibleBitmap() failed!\n", __FUNCTION__);
return FALSE;
}
hMemDc = NtGdiCreateCompatibleDC(hDc);
if(!hMemDc)
{
DPRINT1("%s: NtGdiCreateCompatibleDC() failed!\n", __FUNCTION__);
goto cleanup;
}
hOldBmp = NtGdiSelectObject(hMemDc, hMemBmp);
if(!hOldBmp)
{
DPRINT1("%s: NtGdiSelectObject() failed!\n", __FUNCTION__);
goto cleanup;
}
Height = UserGetSystemMetrics(SM_CYCAPTION) - 1;
VCenter = (lpRc->bottom - lpRc->top) / 2;
Padding = VCenter - (Height / 2);
HasIcon = (uFlags & DC_ICON) && (pWnd->Style & WS_SYSMENU)
&& !(uFlags & DC_SMALLCAP);
IconWidth = UserGetSystemMetrics(SM_CXSIZE) + Padding;
r.left = Padding;
r.right = r.left + (lpRc->right - lpRc->left);
r.top = Padding;
r.bottom = r.top + (Height / 2);
// Draw the caption background
if(uFlags & DC_INBUTTON)
{
hOldBrush = NtGdiSelectObject(hMemDc,
IntGetSysColorBrush(uFlags & DC_ACTIVE ?
COLOR_BTNFACE : COLOR_BTNSHADOW));
if(!hOldBrush)
{
DPRINT1("%s: NtGdiSelectObject() failed!\n", __FUNCTION__);
goto cleanup;
}
if(!NtGdiPatBlt(hMemDc, 0, 0,
lpRc->right - lpRc->left,
lpRc->bottom - lpRc->top,
PATCOPY))
{
DPRINT1("%s: NtGdiPatBlt() failed!\n", __FUNCTION__);
goto cleanup;
}
if(HasIcon) r.left+=IconWidth;
}
else
{
r.right = (lpRc->right - lpRc->left);
if(uFlags & DC_SMALLCAP)
ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
hOldBrush = NtGdiSelectObject(hMemDc,
IntGetSysColorBrush(uFlags & DC_ACTIVE ?
COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
if(!hOldBrush)
{
DPRINT1("%s: NtGdiSelectObject() failed!\n", __FUNCTION__);
goto cleanup;
}
if(HasIcon && (uFlags & DC_GRADIENT))
{
NtGdiPatBlt(hMemDc, 0, 0,
IconWidth+1,
lpRc->bottom - lpRc->top,
PATCOPY);
r.left+=IconWidth;
}
else
{
NtGdiPatBlt(hMemDc, 0, 0,
lpRc->right - lpRc->left,
lpRc->bottom - lpRc->top,
PATCOPY);
}
if(uFlags & DC_GRADIENT)
{
static GRADIENT_RECT gcap = {0, 1};
TRIVERTEX vert[2];
COLORREF Colors[2];
PDC pMemDc;
if(pWnd->Style & WS_SYSMENU)
{
r.right -= 3 + ButtonWidth;
if(!(uFlags & DC_SMALLCAP))
{
if(pWnd->Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
r.right -= 2 + 2 * ButtonWidth;
else r.right -= 2;
r.right -= 2;
}
//Draw buttons background
if(!NtGdiSelectObject(hMemDc,
IntGetSysColorBrush(uFlags & DC_ACTIVE ?
COLOR_GRADIENTACTIVECAPTION:COLOR_GRADIENTINACTIVECAPTION)))
{
DPRINT1("%s: NtGdiSelectObject() failed!\n", __FUNCTION__);
goto cleanup;
}
NtGdiPatBlt(hMemDc,
r.right,
0,
lpRc->right - lpRc->left - r.right,
lpRc->bottom - lpRc->top,
PATCOPY);
}
Colors[0] = IntGetSysColor((uFlags & DC_ACTIVE) ?
COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
Colors[1] = IntGetSysColor((uFlags & DC_ACTIVE) ?
COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION);
vert[0].x = r.left;
vert[0].y = 0;
vert[0].Red = (WORD)Colors[0]<<8;
vert[0].Green = (WORD)Colors[0] & 0xFF00;
vert[0].Blue = (WORD)(Colors[0]>>8) & 0xFF00;
vert[0].Alpha = 0;
vert[1].x = r.right;
vert[1].y = lpRc->bottom - lpRc->top;
vert[1].Red = (WORD)Colors[1]<<8;
vert[1].Green = (WORD)Colors[1] & 0xFF00;
vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00;
vert[1].Alpha = 0;
pMemDc = DC_LockDc(hMemDc);
if(!pMemDc)
{
DPRINT1("%s: Can't lock dc!\n", __FUNCTION__);
goto cleanup;
}
if(!IntGdiGradientFill(pMemDc, vert, 2, &gcap,
1, GRADIENT_FILL_RECT_H))
{
DPRINT1("%s: IntGdiGradientFill() failed!\n", __FUNCTION__);
}
DC_UnlockDc(pMemDc);
} //if(uFlags & DC_GRADIENT)
}
if(HasIcon)
{
r.top ++;
r.left -= --IconWidth;
IntDrawSysMenuButton(pWnd, hMemDc, &r, FALSE);
r.left += IconWidth;
r.top --;
}
r.top ++;
r.left += 2;
r.bottom = r.top + Height;
if((uFlags & DC_TEXT) && pWnd->WindowName.Length)
{
if(!(uFlags & DC_GRADIENT))
{
r.right = (lpRc->right - lpRc->left);
if(uFlags & DC_SMALLCAP)
ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
if(pWnd->Style & WS_SYSMENU)
{
r.right -= 3 + ButtonWidth;
if(! (uFlags & DC_SMALLCAP))
{
if(pWnd->Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
r.right -= 2 + 2 * ButtonWidth;
else r.right -= 2;
r.right -= 2;
}
}
}
IntDrawCaptionText(hMemDc, &pWnd->WindowName, &r, uFlags);
}
if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top,
lpRc->right - lpRc->left, lpRc->bottom - lpRc->top,
hMemDc, 0, 0, SRCCOPY, 0, 0))
{
DPRINT1("%s: NtGdiBitBlt() failed!\n", __FUNCTION__);
goto cleanup;
}
Ret = TRUE;
cleanup:
if (hOldBrush) NtGdiSelectObject(hMemDc, hOldBrush);
if (hOldBmp) NtGdiSelectObject(hMemDc, hOldBmp);
if (hMemBmp) NtGdiDeleteObject(hMemBmp);
if (hMemDc) NtGdiDeleteObjectApp(hMemDc);
return Ret;
}
BOOL
STDCALL
NtUserDrawCaption(HWND hWnd,
HDC hDc,
LPCRECT lpRc,
UINT uFlags)
{
PWINDOW_OBJECT pWnd;
RECT SafeRect;
BOOL Ret;
if(!NT_SUCCESS(MmCopyFromCaller(&SafeRect, lpRc, sizeof(RECT))))
{
DPRINT1("%s: MmCopyFromCaller failed!", __FUNCTION__);
return FALSE;
}
UserEnterExclusive();
if(!(pWnd = UserGetWindowObject(hWnd)))
{
UserLeave();
return FALSE;
}
Ret = UserDrawCaption(pWnd, hDc, &SafeRect, uFlags);
UserLeave();
return Ret;
}
/* EOF */

View file

@ -210,6 +210,12 @@ IntGetSysColorBrushes(HBRUSH *Brushes, UINT nBrushes)
return nBrushes > 0;
}
HGDIOBJ FASTCALL
IntGetSysColorBrush(INT Object)
{
return ((Object < 0) || (NUM_SYSCOLORS <= Object)) ? NULL : SysColorBrushes[Object];
}
BOOL FASTCALL
IntGetSysColorPens(HPEN *Pens, UINT nPens)
{
@ -254,6 +260,12 @@ IntGetSysColors(COLORREF *Colors, UINT nColors)
return nColors > 0;
}
DWORD FASTCALL
IntGetSysColor(INT nIndex)
{
return ((nIndex < 0) || (NUM_SYSCOLORS <= nIndex)) ? 0 : SysColors[nIndex];
}
VOID FASTCALL
CreateSysColorObjects(VOID)
{