Commit 6117fc41 authored by Serge Ivanov's avatar Serge Ivanov Committed by Alexandre Julliard

(Merged by Marcus Meissner <marcus@jet.franken.de>)

Fixed problem with origin for DST_COMPLEX style. Fixed handling of DSS_DISABLED and DSS_DEFAULT styles. Added handling of BS_MULTILINE style, label alignment styles (BS_RIGHT, etc.) and some exotic styles BS_FLAT (only pushbuttons for now), and BS_PUSHLIKE. Modified label drawing procedure: now all kinds of buttons use common BUTTON_DrawLabel function. Actual label drawing is performed by DrawStateW function. GroupBox must use WM_CTLCOLORSTATIC instead of WM_CTLCOLORBTN message.
parent 48455b36
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include <string.h> #include <string.h>
#include <stdlib.h> /* for abs() */
#include "win.h" #include "win.h"
#include "button.h" #include "button.h"
#include "winbase.h" #include "winbase.h"
...@@ -14,9 +15,6 @@ ...@@ -14,9 +15,6 @@
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "tweak.h" #include "tweak.h"
static void PaintGrayOnGray( HDC hDC,HFONT hFont,RECT *rc,
LPCWSTR text, UINT format );
static void PB_Paint( WND *wndPtr, HDC hDC, WORD action ); static void PB_Paint( WND *wndPtr, HDC hDC, WORD action );
static void CB_Paint( WND *wndPtr, HDC hDC, WORD action ); static void CB_Paint( WND *wndPtr, HDC hDC, WORD action );
static void GB_Paint( WND *wndPtr, HDC hDC, WORD action ); static void GB_Paint( WND *wndPtr, HDC hDC, WORD action );
...@@ -280,21 +278,37 @@ static inline LRESULT WINAPI ButtonWndProc_locked(WND* wndPtr, UINT uMsg, ...@@ -280,21 +278,37 @@ static inline LRESULT WINAPI ButtonWndProc_locked(WND* wndPtr, UINT uMsg,
break; break;
case BM_SETIMAGE: case BM_SETIMAGE:
oldHbitmap = infoPtr->hImage; /* Check that image format confirm button style */
if ((wndPtr->dwStyle & BS_BITMAP) || (wndPtr->dwStyle & BS_ICON)) if ((wndPtr->dwStyle & (BS_BITMAP|BS_ICON)) == BS_BITMAP)
{ {
infoPtr->hImage = (HANDLE) lParam; if (wParam != (WPARAM) IMAGE_BITMAP)
InvalidateRect( hWnd, NULL, FALSE ); return (HICON)0;
} }
else if ((wndPtr->dwStyle & (BS_BITMAP|BS_ICON)) == BS_ICON)
{
if (wParam != (WPARAM) IMAGE_ICON)
return (HICON)0;
} else
return (HICON)0;
oldHbitmap = infoPtr->hImage;
infoPtr->hImage = (HANDLE) lParam;
InvalidateRect( hWnd, NULL, FALSE );
return oldHbitmap; return oldHbitmap;
case BM_GETIMAGE: case BM_GETIMAGE:
if (wParam == IMAGE_BITMAP) if ((wndPtr->dwStyle & (BS_BITMAP|BS_ICON)) == BS_BITMAP)
return (HBITMAP)infoPtr->hImage; {
else if (wParam == IMAGE_ICON) if (wParam != (WPARAM) IMAGE_BITMAP)
return (HICON)infoPtr->hImage; return (HICON)0;
else }
else if ((wndPtr->dwStyle & (BS_BITMAP|BS_ICON)) == BS_ICON)
{
if (wParam != (WPARAM) IMAGE_ICON)
return (HICON)0;
} else
return (HICON)0; return (HICON)0;
return infoPtr->hImage;
case BM_GETCHECK16: case BM_GETCHECK16:
case BM_GETCHECK: case BM_GETCHECK:
...@@ -381,6 +395,213 @@ static void PB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -381,6 +395,213 @@ static void PB_Paint( WND *wndPtr, HDC hDC, WORD action )
} }
/********************************************************************** /**********************************************************************
* Convert button styles to flags used by DrawText.
* TODO: handle WS_EX_RIGHT extended style.
*/
static UINT BUTTON_BStoDT(DWORD style)
{
UINT dtStyle = DT_NOCLIP; /* We use SelectClipRgn to limit output */
/* "Convert" pushlike buttons to pushbuttons */
if (style & BS_PUSHLIKE)
style &= ~0x0F;
if (!(style & BS_MULTILINE))
dtStyle |= DT_SINGLELINE;
else
dtStyle |= DT_WORDBREAK;
switch (style & BS_CENTER)
{
case BS_LEFT: /* DT_LEFT is 0 */ break;
case BS_RIGHT: dtStyle |= DT_RIGHT; break;
case BS_CENTER: dtStyle |= DT_CENTER; break;
default:
/* Pushbutton's text is centered by default */
if ((style & 0x0F) <= BS_DEFPUSHBUTTON)
dtStyle |= DT_CENTER;
/* all other flavours have left aligned text */
}
/* DrawText ignores vertical alignment for multiline text,
* but we use these flags to align label manualy.
*/
if ((style & 0x0F) != BS_GROUPBOX)
{
switch (style & BS_VCENTER)
{
case BS_TOP: /* DT_TOP is 0 */ break;
case BS_BOTTOM: dtStyle |= DT_BOTTOM; break;
case BS_VCENTER: /* fall through */
default: dtStyle |= DT_VCENTER; break;
}
}
else
/* GroupBox's text is always single line and is top aligned. */
dtStyle |= DT_SINGLELINE;
return dtStyle;
}
/**********************************************************************
* BUTTON_CalcLabelRect
*
* Calculates label's rectangle depending on button style.
*
* Returns flags to be passed to DrawText.
* Calculated rectangle doesn't take into account button state
* (pushed, etc.). If there is nothing to draw (no text/image) output
* rectangle is empty, and return value is (UINT)-1.
*/
static UINT BUTTON_CalcLabelRect(WND *wndPtr, HDC hdc, RECT *rc)
{
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
ICONINFO iconInfo;
BITMAP bm;
UINT dtStyle = BUTTON_BStoDT(wndPtr->dwStyle);
RECT r = *rc;
INT n;
/* Calculate label rectangle according to label type */
switch (wndPtr->dwStyle & (BS_ICON|BS_BITMAP))
{
case BS_TEXT:
if (wndPtr->text && wndPtr->text[0])
DrawTextW(hdc, wndPtr->text, -1, &r, dtStyle | DT_CALCRECT);
else
goto empty_rect;
break;
case BS_ICON:
if (!GetIconInfo((HICON)infoPtr->hImage, &iconInfo))
goto empty_rect;
GetObjectA (iconInfo.hbmColor, sizeof(BITMAP), &bm);
r.right = r.left + bm.bmWidth;
r.bottom = r.top + bm.bmHeight;
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
break;
case BS_BITMAP:
if (!GetObjectA (infoPtr->hImage, sizeof(BITMAP), &bm))
goto empty_rect;
r.right = r.left + bm.bmWidth;
r.bottom = r.top + bm.bmHeight;
break;
default:
empty_rect:
r.right = r.left;
r.bottom = r.top;
return (UINT)(LONG)-1;
}
/* Position label inside bounding rectangle according to
* alignment flags. (calculated rect is always left-top aligned).
* If label is aligned to any side - shift label in opposite
* direction to leave extra space for focus rectangle.
*/
switch (dtStyle & (DT_CENTER|DT_RIGHT))
{
case DT_LEFT: r.left++; r.right++; break;
case DT_CENTER: n = r.right - r.left;
r.left = rc->left + ((rc->right - rc->left) - n) / 2;
r.right = r.left + n; break;
case DT_RIGHT: n = r.right - r.left;
r.right = rc->right - 1;
r.left = r.right - n;
break;
}
switch (dtStyle & (DT_VCENTER|DT_BOTTOM))
{
case DT_TOP: r.top++; r.bottom++; break;
case DT_VCENTER: n = r.bottom - r.top;
r.top = rc->top + ((rc->bottom - rc->top) - n) / 2;
r.bottom = r.top + n; break;
case DT_BOTTOM: n = r.bottom - r.top;
r.bottom = rc->bottom - 1;
r.top = r.bottom - n;
break;
}
*rc = r;
return dtStyle;
}
/**********************************************************************
* BUTTON_DrawTextCallback
*
* Callback function used be DrawStateA function.
*/
static BOOL CALLBACK BUTTON_DrawTextCallback(HDC hdc, LPARAM lp, WPARAM wp, int cx, int cy)
{
RECT rc = {0, 0, cx, cy};
DrawTextW(hdc, (LPCWSTR)lp, -1, &rc, (UINT)wp);
return TRUE;
}
/**********************************************************************
* BUTTON_DrawLabel
*
* Common function for drawing button label.
*/
static void BUTTON_DrawLabel(WND *wndPtr, HDC hdc, UINT dtFlags,
RECT *rc)
{
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
DRAWSTATEPROC lpOutputProc = NULL;
LPARAM lp;
WPARAM wp = 0;
HBRUSH hbr = 0;
UINT flags = IsWindowEnabled(wndPtr->hwndSelf) ? DSS_NORMAL : DSS_DISABLED;
/* Fixme: To draw disabled label in Win31 look-and-feel, we probably
* must use DSS_MONO flag and COLOR_GRAYTEXT brush (or maybe DSS_UNION).
* I don't have Win31 on hand to verify that, so I leave it as is.
*/
if ((wndPtr->dwStyle & BS_PUSHLIKE) && (infoPtr->state & BUTTON_3STATE))
{
hbr = GetSysColorBrush(COLOR_GRAYTEXT);
flags |= DSS_MONO;
}
switch (wndPtr->dwStyle & (BS_ICON|BS_BITMAP))
{
case BS_TEXT:
/* DST_COMPLEX -- is 0 */
lpOutputProc = BUTTON_DrawTextCallback;
lp = (LPARAM)wndPtr->text;
wp = (WPARAM)dtFlags;
break;
case BS_ICON:
flags |= DST_ICON;
lp = (LPARAM)infoPtr->hImage;
break;
case BS_BITMAP:
flags |= DST_BITMAP;
lp = (LPARAM)infoPtr->hImage;
break;
default:
return;
}
DrawStateW(hdc, hbr, lpOutputProc, lp, wp, rc->left, rc->top,
rc->right - rc->left, rc->bottom - rc->top, flags);
}
/**********************************************************************
* This method will actually do the drawing of the pushbutton * This method will actually do the drawing of the pushbutton
* depending on it's state and the pushedState parameter. * depending on it's state and the pushedState parameter.
*/ */
...@@ -390,30 +611,33 @@ static void BUTTON_DrawPushButton( ...@@ -390,30 +611,33 @@ static void BUTTON_DrawPushButton(
WORD action, WORD action,
BOOL pushedState ) BOOL pushedState )
{ {
RECT rc, focus_rect;
HPEN hOldPen;
HBRUSH hOldBrush;
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra; BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
int xBorderOffset, yBorderOffset; RECT rc, focus_rect, r;
xBorderOffset = yBorderOffset = 0; UINT dtFlags;
HRGN hRgn;
HPEN hOldPen;
HBRUSH hOldBrush;
INT oldBkMode;
COLORREF oldTxtColor;
GetClientRect( wndPtr->hwndSelf, &rc ); GetClientRect( wndPtr->hwndSelf, &rc );
/* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */ /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont ); if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
BUTTON_SEND_CTLCOLOR( wndPtr, hDC ); BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
hOldPen = (HPEN)SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME)); hOldPen = (HPEN)SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
hOldBrush =(HBRUSH)SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE)); hOldBrush =(HBRUSH)SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
SetBkMode(hDC, TRANSPARENT); oldBkMode = SetBkMode(hDC, TRANSPARENT);
if ( TWEAK_WineLook == WIN31_LOOK) if ( TWEAK_WineLook == WIN31_LOOK)
{ {
COLORREF clr_wnd = GetSysColor(COLOR_WINDOW);
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom); Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
SetPixel( hDC, rc.left, rc.top, GetSysColor(COLOR_WINDOW) ); SetPixel( hDC, rc.left, rc.top, clr_wnd);
SetPixel( hDC, rc.left, rc.bottom-1, GetSysColor(COLOR_WINDOW) ); SetPixel( hDC, rc.left, rc.bottom-1, clr_wnd);
SetPixel( hDC, rc.right-1, rc.top, GetSysColor(COLOR_WINDOW) ); SetPixel( hDC, rc.right-1, rc.top, clr_wnd);
SetPixel( hDC, rc.right-1, rc.bottom-1, GetSysColor(COLOR_WINDOW)); SetPixel( hDC, rc.right-1, rc.bottom-1, clr_wnd);
InflateRect( &rc, -1, -1 ); InflateRect( &rc, -1, -1 );
} }
...@@ -431,24 +655,19 @@ static void BUTTON_DrawPushButton( ...@@ -431,24 +655,19 @@ static void BUTTON_DrawPushButton(
SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW)); SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
PatBlt(hDC, rc.left, rc.top, 1, rc.bottom-rc.top, PATCOPY ); PatBlt(hDC, rc.left, rc.top, 1, rc.bottom-rc.top, PATCOPY );
PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, 1, PATCOPY ); PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, 1, PATCOPY );
rc.left += 2; /* To position the text down and right */
rc.top += 2;
} else { } else {
rc.right++, rc.bottom++; rc.right++, rc.bottom++;
DrawEdge( hDC, &rc, EDGE_RAISED, BF_RECT ); DrawEdge( hDC, &rc, EDGE_RAISED, BF_RECT );
/* To place the bitmap correctly */
xBorderOffset += GetSystemMetrics(SM_CXEDGE);
yBorderOffset += GetSystemMetrics(SM_CYEDGE);
rc.right--, rc.bottom--; rc.right--, rc.bottom--;
} }
} }
else else
{ {
UINT uState = DFCS_BUTTONPUSH; UINT uState = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
if (pushedState) if (wndPtr->dwStyle & BS_FLAT)
uState |= DFCS_MONO;
else if (pushedState)
{ {
if ( (wndPtr->dwStyle & 0x000f) == BS_DEFPUSHBUTTON ) if ( (wndPtr->dwStyle & 0x000f) == BS_DEFPUSHBUTTON )
uState |= DFCS_FLAT; uState |= DFCS_FLAT;
...@@ -456,211 +675,54 @@ static void BUTTON_DrawPushButton( ...@@ -456,211 +675,54 @@ static void BUTTON_DrawPushButton(
uState |= DFCS_PUSHED; uState |= DFCS_PUSHED;
} }
if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE))
uState |= DFCS_CHECKED;
DrawFrameControl( hDC, &rc, DFC_BUTTON, uState ); DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
InflateRect( &rc, -2, -2 );
focus_rect = rc; focus_rect = rc;
if (pushedState)
{
rc.left += 2; /* To position the text down and right */
rc.top += 2;
}
} }
/* draw button label, if any: /* draw button label */
* r = rc;
* In win9x we don't show text if there is a bitmap or icon. dtFlags = BUTTON_CalcLabelRect(wndPtr, hDC, &r);
* I don't know about win31 so I leave it as it was for win31.
* Dennis Bjrklund 12 Jul, 99
*/
if ( wndPtr->text && wndPtr->text[0]
&& (TWEAK_WineLook == WIN31_LOOK || !(wndPtr->dwStyle & (BS_ICON|BS_BITMAP))) )
{
LOGBRUSH lb;
GetObjectA( GetSysColorBrush(COLOR_BTNFACE), sizeof(lb), &lb );
if (wndPtr->dwStyle & WS_DISABLED &&
GetSysColor(COLOR_GRAYTEXT)==lb.lbColor)
/* don't write gray text on gray background */
PaintGrayOnGray( hDC,infoPtr->hFont,&rc,wndPtr->text,
DT_CENTER | DT_VCENTER );
else
{
SetTextColor( hDC, (wndPtr->dwStyle & WS_DISABLED) ?
GetSysColor(COLOR_GRAYTEXT) :
GetSysColor(COLOR_BTNTEXT) );
DrawTextW( hDC, wndPtr->text, -1, &rc,
DT_SINGLELINE | DT_CENTER | DT_VCENTER );
/* do we have the focus?
* Win9x draws focus last with a size prop. to the button
*/
if (TWEAK_WineLook == WIN31_LOOK
&& infoPtr->state & BUTTON_HASFOCUS)
{
RECT r = { 0, 0, 0, 0 };
INT xdelta, ydelta;
DrawTextW( hDC, wndPtr->text, -1, &r,
DT_SINGLELINE | DT_CALCRECT );
xdelta = ((rc.right - rc.left) - (r.right - r.left) - 1) / 2;
ydelta = ((rc.bottom - rc.top) - (r.bottom - r.top) - 1) / 2;
if (xdelta < 0) xdelta = 0;
if (ydelta < 0) ydelta = 0;
InflateRect( &rc, -xdelta, -ydelta );
DrawFocusRect( hDC, &rc );
}
}
}
if ( ((wndPtr->dwStyle & BS_ICON) || (wndPtr->dwStyle & BS_BITMAP) ) &&
(infoPtr->hImage != 0) )
{
int yOffset, xOffset;
int imageWidth, imageHeight;
/* if (dtFlags == (UINT)-1L)
* We extract the size of the image from the handle. goto cleanup;
*/
if (wndPtr->dwStyle & BS_ICON)
{
ICONINFO iconInfo;
BITMAP bm;
GetIconInfo((HICON)infoPtr->hImage, &iconInfo);
GetObjectA (iconInfo.hbmColor, sizeof(BITMAP), &bm);
imageWidth = bm.bmWidth;
imageHeight = bm.bmHeight;
DeleteObject(iconInfo.hbmColor); if (pushedState)
DeleteObject(iconInfo.hbmMask); OffsetRect(&r, 1, 1);
} if(TWEAK_WineLook == WIN31_LOOK)
else {
{ focus_rect = r;
BITMAP bm; InflateRect(&focus_rect, 2, 0);
}
GetObjectA (infoPtr->hImage, sizeof(BITMAP), &bm);
imageWidth = bm.bmWidth;
imageHeight = bm.bmHeight;
}
/* Center the bitmap */
xOffset = (((rc.right - rc.left) - 2*xBorderOffset) - imageWidth ) / 2;
yOffset = (((rc.bottom - rc.top) - 2*yBorderOffset) - imageHeight) / 2;
/* If the image is too big for the button then create a region */ hRgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
if(xOffset < 0 || yOffset < 0) SelectClipRgn(hDC, hRgn);
{
HRGN hBitmapRgn = 0;
hBitmapRgn = CreateRectRgn(
rc.left + xBorderOffset, rc.top +yBorderOffset,
rc.right - xBorderOffset, rc.bottom - yBorderOffset);
SelectClipRgn(hDC, hBitmapRgn);
DeleteObject(hBitmapRgn);
}
/* Let minimum 1 space from border */ oldTxtColor = SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
xOffset++, yOffset++;
/* BUTTON_DrawLabel(wndPtr, hDC, dtFlags, &r);
* Draw the image now.
*/
if (wndPtr->dwStyle & BS_ICON)
{
DrawIcon(hDC,
rc.left + xOffset, rc.top + yOffset,
(HICON)infoPtr->hImage);
}
else
{
HDC hdcMem;
hdcMem = CreateCompatibleDC (hDC);
SelectObject (hdcMem, (HBITMAP)infoPtr->hImage);
BitBlt(hDC,
rc.left + xOffset,
rc.top + yOffset,
imageWidth, imageHeight,
hdcMem, 0, 0, SRCCOPY);
DeleteDC (hdcMem);
}
if(xOffset < 0 || yOffset < 0) SetTextColor( hDC, oldTxtColor );
{ SelectClipRgn(hDC, 0);
SelectClipRgn(hDC, 0); DeleteObject(hRgn);
}
}
if (TWEAK_WineLook != WIN31_LOOK if (infoPtr->state & BUTTON_HASFOCUS)
&& infoPtr->state & BUTTON_HASFOCUS)
{ {
InflateRect( &focus_rect, -1, -1 ); InflateRect( &focus_rect, -1, -1 );
IntersectRect(&focus_rect, &focus_rect, &rc);
DrawFocusRect( hDC, &focus_rect ); DrawFocusRect( hDC, &focus_rect );
} }
cleanup:
SelectObject( hDC, hOldPen ); SelectObject( hDC, hOldPen );
SelectObject( hDC, hOldBrush ); SelectObject( hDC, hOldBrush );
SetBkMode(hDC, oldBkMode);
} }
/**********************************************************************
* PB_Paint & CB_Paint sub function [internal]
* Paint text using a raster brush to avoid gray text on gray
* background. 'format' can be a combination of DT_CENTER and
* DT_VCENTER to use this function in both PB_PAINT and
* CB_PAINT. - Dirk Thierbach
*
* FIXME: This and TEXT_GrayString should be eventually combined,
* so calling one common function from PB_Paint, CB_Paint and
* TEXT_GrayString will be enough. Also note that this
* function ignores the CACHE_GetPattern funcs.
*/
void PaintGrayOnGray(HDC hDC, HFONT hFont, RECT *rc, LPCWSTR text,
UINT format)
{
/* This is the standard gray on gray pattern:
static const WORD Pattern[] = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
*/
/* This pattern gives better readability with X Fonts.
FIXME: Maybe the user should be allowed to decide which he wants. */
static const WORD Pattern[] = {0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF};
HBITMAP hbm = CreateBitmap( 8, 8, 1, 1, Pattern );
HDC hdcMem = CreateCompatibleDC(hDC);
HBITMAP hbmMem;
HBRUSH hBr;
RECT rect,rc2;
rect=*rc;
DrawTextW( hDC, text, -1, &rect, DT_SINGLELINE | DT_CALCRECT);
/* now text width and height are in rect.right and rect.bottom */
rc2=rect;
rect.left = rect.top = 0; /* drawing pos in hdcMem */
if (format & DT_CENTER) rect.left=(rc->right-rect.right)/2;
if (format & DT_VCENTER) rect.top=(rc->bottom-rect.bottom)/2;
hbmMem = CreateCompatibleBitmap( hDC,rect.right,rect.bottom );
SelectObject( hdcMem, hbmMem);
PatBlt( hdcMem,0,0,rect.right,rect.bottom,WHITENESS);
/* will be overwritten by DrawText, but just in case */
if (hFont) SelectObject( hdcMem, hFont);
DrawTextW( hdcMem, text, -1, &rc2, DT_SINGLELINE);
/* After draw: foreground = 0 bits, background = 1 bits */
hBr = SelectObject( hdcMem, CreatePatternBrush(hbm) );
DeleteObject( hbm );
PatBlt( hdcMem,0,0,rect.right,rect.bottom,0xAF0229);
/* only keep the foreground bits where pattern is 1 */
DeleteObject( SelectObject( hdcMem,hBr) );
BitBlt(hDC,rect.left,rect.top,rect.right,rect.bottom,hdcMem,0,0,SRCAND);
/* keep the background of the dest */
DeleteDC( hdcMem);
DeleteObject( hbmMem );
}
/********************************************************************** /**********************************************************************
* Check Box & Radio Button Functions * Check Box & Radio Button Functions
*/ */
...@@ -669,17 +731,14 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -669,17 +731,14 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
{ {
RECT rbox, rtext, client; RECT rbox, rtext, client;
HBRUSH hBrush; HBRUSH hBrush;
int textlen, delta; int delta;
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra; BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
UINT dtFlags;
HRGN hRgn;
/* if (wndPtr->dwStyle & BS_PUSHLIKE)
* if the button has a bitmap/icon, draw a normal pushbutton
* instead of a radion button.
*/
if (infoPtr->hImage != 0)
{ {
BOOL bHighLighted = ((infoPtr->state & BUTTON_HIGHLIGHTED) || BOOL bHighLighted = (infoPtr->state & BUTTON_HIGHLIGHTED);
(infoPtr->state & BUTTON_CHECKED));
BUTTON_DrawPushButton(wndPtr, BUTTON_DrawPushButton(wndPtr,
hDC, hDC,
...@@ -688,18 +747,14 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -688,18 +747,14 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
return; return;
} }
textlen = 0;
GetClientRect(wndPtr->hwndSelf, &client); GetClientRect(wndPtr->hwndSelf, &client);
rbox = rtext = client; rbox = rtext = client;
if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont ); if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
/* Something is still not right, checkboxes (and edit controls) /* GetControlBrush16 sends WM_CTLCOLORBTN, plus it returns default brush
* in wsping32 have white backgrounds instead of dark grey. * if parent didn't return valid one. So we kill two hares at once
* BUTTON_SEND_CTLCOLOR() is even worse since it returns 0 in this
* particular case and the background is not painted at all.
*/ */
hBrush = GetControlBrush16( wndPtr->hwndSelf, hDC, CTLCOLOR_BTN ); hBrush = GetControlBrush16( wndPtr->hwndSelf, hDC, CTLCOLOR_BTN );
if (wndPtr->dwStyle & BS_LEFTTEXT) if (wndPtr->dwStyle & BS_LEFTTEXT)
...@@ -715,9 +770,7 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -715,9 +770,7 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
rbox.right = checkBoxWidth; rbox.right = checkBoxWidth;
} }
/* Draw the check-box bitmap */ /* Draw the check-box bitmap */
if (wndPtr->text) textlen = lstrlenW( wndPtr->text );
if (action == ODA_DRAWENTIRE || action == ODA_SELECT) if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
{ {
if( TWEAK_WineLook == WIN31_LOOK ) if( TWEAK_WineLook == WIN31_LOOK )
...@@ -781,40 +834,31 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -781,40 +834,31 @@ static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
DrawFrameControl( hDC, &rbox, DFC_BUTTON, state ); DrawFrameControl( hDC, &rbox, DFC_BUTTON, state );
} }
if( textlen && action != ODA_SELECT )
{
if (wndPtr->dwStyle & WS_DISABLED &&
GetSysColor(COLOR_GRAYTEXT)==GetBkColor(hDC)) {
/* don't write gray text on gray background */
PaintGrayOnGray( hDC, infoPtr->hFont, &rtext, wndPtr->text,
DT_VCENTER);
} else {
if (wndPtr->dwStyle & WS_DISABLED)
SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
DrawTextW( hDC, wndPtr->text, textlen, &rtext,
DT_SINGLELINE | DT_VCENTER );
}
}
} }
/* Draw label */
client = rtext;
dtFlags = BUTTON_CalcLabelRect(wndPtr, hDC, &rtext);
if (dtFlags == (UINT)-1L) /* Noting to draw */
return;
hRgn = CreateRectRgn(client.left, client.top, client.right, client.bottom);
SelectClipRgn(hDC, hRgn);
DeleteObject(hRgn);
if (action == ODA_DRAWENTIRE)
BUTTON_DrawLabel(wndPtr, hDC, dtFlags, &rtext);
/* ... and focus */
if ((action == ODA_FOCUS) || if ((action == ODA_FOCUS) ||
((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS))) ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
{ {
/* again, this is what CTL3D expects */ rtext.left--;
rtext.right++;
SetRectEmpty(&rbox); IntersectRect(&rtext, &rtext, &client);
if( textlen ) DrawFocusRect( hDC, &rtext );
DrawTextW( hDC, wndPtr->text, textlen, &rbox,
DT_SINGLELINE | DT_CALCRECT );
textlen = rbox.bottom - rbox.top;
delta = ((rtext.bottom - rtext.top) - textlen)/2;
rbox.bottom = (rbox.top = rtext.top + delta - 1) + textlen + 2;
textlen = rbox.right - rbox.left;
rbox.right = (rbox.left += --rtext.left) + textlen + 2;
IntersectRect(&rbox, &rbox, &rtext);
DrawFocusRect( hDC, &rbox );
} }
SelectClipRgn(hDC, 0);
} }
...@@ -852,10 +896,16 @@ static void GB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -852,10 +896,16 @@ static void GB_Paint( WND *wndPtr, HDC hDC, WORD action )
{ {
RECT rc, rcFrame; RECT rc, rcFrame;
BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra; BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
HBRUSH hbr;
UINT dtFlags;
if (action != ODA_DRAWENTIRE) return; if (action != ODA_DRAWENTIRE) return;
BUTTON_SEND_CTLCOLOR( wndPtr, hDC ); if (infoPtr->hFont)
SelectObject (hDC, infoPtr->hFont);
/* GroupBox acts like static control, so it sends CTLCOLORSTATIC */
hbr = GetControlBrush16( wndPtr->hwndSelf, hDC, CTLCOLOR_STATIC );
GetClientRect( wndPtr->hwndSelf, &rc); GetClientRect( wndPtr->hwndSelf, &rc);
if (TWEAK_WineLook == WIN31_LOOK) { if (TWEAK_WineLook == WIN31_LOOK) {
...@@ -871,21 +921,29 @@ static void GB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -871,21 +921,29 @@ static void GB_Paint( WND *wndPtr, HDC hDC, WORD action )
TEXTMETRICA tm; TEXTMETRICA tm;
rcFrame = rc; rcFrame = rc;
if (infoPtr->hFont)
SelectObject (hDC, infoPtr->hFont);
GetTextMetricsA (hDC, &tm); GetTextMetricsA (hDC, &tm);
rcFrame.top += (tm.tmHeight / 2) - 1; rcFrame.top += (tm.tmHeight / 2) - 1;
DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT); DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT |
((wndPtr->dwStyle & BS_FLAT) ? BF_FLAT : 0));
} }
if (wndPtr->text) InflateRect(&rc, -7, 1);
{ dtFlags = BUTTON_CalcLabelRect(wndPtr, hDC, &rc);
if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
if (wndPtr->dwStyle & WS_DISABLED) if (dtFlags == (UINT)-1L)
SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) ); return;
rc.left += 10;
DrawTextW( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE | DT_NOCLIP ); /* Because buttons have CS_PARENTDC class style, there is a chance
} * that label will be drawn out of client rect.
* But Windows doesn't clip label's rect, so do I.
*/
/* There is 1-pixel marging at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr);
rc.left++; rc.right--; rc.bottom--;
BUTTON_DrawLabel(wndPtr, hDC, dtFlags, &rc);
} }
...@@ -930,7 +988,7 @@ static void OB_Paint( WND *wndPtr, HDC hDC, WORD action ) ...@@ -930,7 +988,7 @@ static void OB_Paint( WND *wndPtr, HDC hDC, WORD action )
dis.itemAction = action; dis.itemAction = action;
dis.itemState = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) | dis.itemState = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) | ((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
((wndPtr->dwStyle & WS_DISABLED) ? ODS_DISABLED : 0); (IsWindowEnabled(wndPtr->hwndSelf) ? 0: ODS_DISABLED);
dis.hwndItem = wndPtr->hwndSelf; dis.hwndItem = wndPtr->hwndSelf;
dis.hDC = hDC; dis.hDC = hDC;
dis.itemData = 0; dis.itemData = 0;
......
...@@ -1451,12 +1451,19 @@ static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode, ...@@ -1451,12 +1451,19 @@ static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode,
return retval; return retval;
case DST_COMPLEX: case DST_COMPLEX:
if(func) if(func) {
BOOL bRet;
/* DRAWSTATEPROC assumes that it draws at the center of coordinates */
OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL);
if(_32bit) if(_32bit)
return func(hdc, lp, wp, cx, cy); bRet = func(hdc, lp, wp, cx, cy);
else else
return (BOOL)((DRAWSTATEPROC16)func)((HDC16)hdc, (LPARAM)lp, (WPARAM16)wp, (INT16)cx, (INT16)cy); bRet = (BOOL)((DRAWSTATEPROC16)func)((HDC16)hdc, (LPARAM)lp, (WPARAM16)wp, (INT16)cx, (INT16)cy);
else /* Restore origin */
OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL);
return bRet;
} else
return FALSE; return FALSE;
} }
return FALSE; return FALSE;
...@@ -1472,7 +1479,7 @@ static BOOL PAINTING_DrawState(HDC hdc, HBRUSH hbr, ...@@ -1472,7 +1479,7 @@ static BOOL PAINTING_DrawState(HDC hdc, HBRUSH hbr,
{ {
HBITMAP hbm, hbmsave; HBITMAP hbm, hbmsave;
HFONT hfsave; HFONT hfsave;
HBRUSH hbsave; HBRUSH hbsave, hbrtmp = 0;
HDC memdc; HDC memdc;
RECT rc; RECT rc;
UINT dtflags = DT_NOCLIP; UINT dtflags = DT_NOCLIP;
...@@ -1572,32 +1579,56 @@ static BOOL PAINTING_DrawState(HDC hdc, HBRUSH hbr, ...@@ -1572,32 +1579,56 @@ static BOOL PAINTING_DrawState(HDC hdc, HBRUSH hbr,
SetBkColor(memdc, RGB(255, 255, 255)); SetBkColor(memdc, RGB(255, 255, 255));
SetTextColor(memdc, RGB(0, 0, 0)); SetTextColor(memdc, RGB(0, 0, 0));
hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT)); hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
if(!hfsave && (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)) goto cleanup;
/* DST_COMPLEX may draw text as well,
* so we must be sure that correct font is selected
*/
if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup;
tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit); tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit);
if(hfsave) SelectObject(memdc, hfsave); if(hfsave) SelectObject(memdc, hfsave);
if(!tmp) goto cleanup; if(!tmp) goto cleanup;
/* These states cause the image to be dithered */ /* This state cause the image to be dithered */
if(flags & (DSS_UNION|DSS_DISABLED)) if(flags & DSS_UNION)
{ {
hbsave = (HBRUSH)SelectObject(memdc, CACHE_GetPattern55AABrush()); hbsave = (HBRUSH)SelectObject(memdc, CACHE_GetPattern55AABrush());
if(!hbsave) goto cleanup; if(!hbsave) goto cleanup;
tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089);
if(hbsave) SelectObject(memdc, hbsave); SelectObject(memdc, hbsave);
if(!tmp) goto cleanup; if(!tmp) goto cleanup;
} }
hbsave = (HBRUSH)SelectObject(hdc, hbr ? hbr : GetStockObject(WHITE_BRUSH)); if (flags & DSS_DISABLED)
if(!hbsave) goto cleanup; hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
else if (flags & DSS_DEFAULT)
if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
/* DSS_DEFAULT makes the image boldface */ /* Draw light or dark shadow */
if(flags & DSS_DEFAULT) if (flags & (DSS_DISABLED|DSS_DEFAULT))
{ {
if(!BitBlt(hdc, x+1, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; if(!hbrtmp) goto cleanup;
hbsave = (HBRUSH)SelectObject(hdc, hbrtmp);
if(!hbsave) goto cleanup;
if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
SelectObject(hdc, hbsave);
DeleteObject(hbrtmp);
hbrtmp = 0;
} }
if (flags & DSS_DISABLED)
{
hbr = hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
if(!hbrtmp) goto cleanup;
}
else if (!hbr)
{
hbr = (HBRUSH)GetStockObject(BLACK_BRUSH);
}
hbsave = (HBRUSH)SelectObject(hdc, hbr);
if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
retval = TRUE; /* We succeeded */ retval = TRUE; /* We succeeded */
cleanup: cleanup:
...@@ -1606,6 +1637,7 @@ cleanup: ...@@ -1606,6 +1637,7 @@ cleanup:
if(hbsave) SelectObject(hdc, hbsave); if(hbsave) SelectObject(hdc, hbsave);
if(hbmsave) SelectObject(memdc, hbmsave); if(hbmsave) SelectObject(memdc, hbmsave);
if(hbrtmp) DeleteObject(hbrtmp);
if(hbm) DeleteObject(hbm); if(hbm) DeleteObject(hbm);
if(memdc) DeleteDC(memdc); if(memdc) DeleteDC(memdc);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment