- 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 BOOL WINAPI
DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags) DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
{ {
NONCLIENTMETRICSW nclm; return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
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;
} }
/* /*
* @unimplemented * @unimplemented
*/ */

View file

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

View file

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

View file

@ -72,7 +72,6 @@ IntGetCursorLocation(PWINSTATION_OBJECT WinSta, POINT *loc)
} }
static
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon) PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
@ -1346,6 +1345,191 @@ DoStretchBlt(HDC DcDest, int XDest, int YDest, int WidthDest, int HeightDest,
(Rop3), 0) (Rop3), 0)
#endif /* STRETCH_CAN_SRCCOPY_ONLY */ #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 * @implemented
*/ */
@ -1364,167 +1548,29 @@ NtUserDrawIconEx(
DWORD Unknown0, DWORD Unknown0,
DWORD Unknown1) DWORD Unknown1)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT pIcon;
PWINSTATION_OBJECT WinSta; BOOL Ret;
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);
DPRINT("Enter NtUserDrawIconEx\n"); DPRINT("Enter NtUserDrawIconEx\n");
UserEnterExclusive(); UserEnterExclusive();
WinSta = IntGetWinStaObj(); if(!(pIcon = UserGetCurIconObject(hIcon)))
if(WinSta == NULL)
{ {
RETURN( FALSE); DPRINT1("UserGetCurIconObject() failed!\n");
UserLeave();
return FALSE;
} }
if (!(CurIcon = UserGetCurIconObject(hIcon))) Ret = UserDrawIconEx(hdc,
{ xLeft,
ObDereferenceObject(WinSta); yTop,
RETURN(FALSE); pIcon,
} cxWidth,
cyHeight,
istepIfAniCur,
hbrFlickerFreeDraw,
diFlags);
hbmMask = CurIcon->IconInfo.hbmMask;
hbmColor = CurIcon->IconInfo.hbmColor;
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(); UserLeave();
END_CLEANUP; return Ret;
} }

View file

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

View file

@ -1372,4 +1372,392 @@ CLEANUP:
END_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 */ /* EOF */

View file

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