static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused) { static const int states[] = { GBS_NORMAL, GBS_DISABLED, GBS_NORMAL, GBS_NORMAL, GBS_NORMAL }; RECT bgRect, textRect, contentRect; int state = states[ drawState ]; WCHAR *text = get_button_text(hwnd); LOGFONTW lf; HFONT font, hPrevFont = NULL; BOOL created_font = FALSE; HRESULT hr = GetThemeFont(theme, hDC, BP_GROUPBOX, state, TMT_FONT, &lf); if (SUCCEEDED(hr)) { font = CreateFontIndirectW(&lf); if (!font) TRACE("Failed to create font\n"); else { hPrevFont = SelectObject(hDC, font); created_font = TRUE; } } else { font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); hPrevFont = SelectObject(hDC, font); } GetClientRect(hwnd, &bgRect); textRect = bgRect; if (text) { SIZE textExtent; GetTextExtentPoint32W(hDC, text, lstrlenW(text), &textExtent); bgRect.top += (textExtent.cy / 2); textRect.left += 10; textRect.bottom = textRect.top + textExtent.cy; textRect.right = textRect.left + textExtent.cx + 4; ExcludeClipRect(hDC, textRect.left, textRect.top, textRect.right, textRect.bottom); } GetThemeBackgroundContentRect(theme, hDC, BP_GROUPBOX, state, &bgRect, &contentRect); ExcludeClipRect(hDC, contentRect.left, contentRect.top, contentRect.right, contentRect.bottom); if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state)) DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_GROUPBOX, state, &bgRect, NULL); SelectClipRgn(hDC, NULL); if (text) { InflateRect(&textRect, -2, 0); DrawThemeText(theme, hDC, BP_GROUPBOX, state, text, lstrlenW(text), 0, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (created_font) DeleteObject(font); if (hPrevFont) SelectObject(hDC, hPrevFont); }
/********************************************************************** * BUTTON_DrawLabel * * Common function for drawing button label. */ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc) { DRAWSTATEPROC lpOutputProc = NULL; LPARAM lp; WPARAM wp = 0; HBRUSH hbr = 0; UINT flags = IsWindowEnabled(hwnd) ? DSS_NORMAL : DSS_DISABLED; LONG state = get_button_state( hwnd ); LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE ); WCHAR *text = NULL; /* 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 ((style & BS_PUSHLIKE) && (state & BST_INDETERMINATE)) { hbr = GetSysColorBrush(COLOR_GRAYTEXT); flags |= DSS_MONO; } switch (style & (BS_ICON|BS_BITMAP)) { case BS_TEXT: /* DST_COMPLEX -- is 0 */ lpOutputProc = BUTTON_DrawTextCallback; if (!(text = get_button_text( hwnd ))) return; lp = (LPARAM)text; wp = (WPARAM)dtFlags; if (dtFlags & DT_HIDEPREFIX) flags |= DSS_HIDEPREFIX; break; case BS_ICON: flags |= DST_ICON; lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); break; case BS_BITMAP: flags |= DST_BITMAP; lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); break; default: return; } DrawStateW(hdc, hbr, lpOutputProc, lp, wp, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, flags); HeapFree( GetProcessHeap(), 0, text ); }
static void CB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags) { static const int cb_states[3][5] = { { CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDDISABLED, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDNORMAL }, { CBS_CHECKEDNORMAL, CBS_CHECKEDDISABLED, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDNORMAL }, { CBS_MIXEDNORMAL, CBS_MIXEDDISABLED, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDNORMAL } }; static const int rb_states[2][5] = { { RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDDISABLED, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDNORMAL }, { RBS_CHECKEDNORMAL, RBS_CHECKEDDISABLED, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDNORMAL } }; static const int cb_size = 13; RECT bgRect, textRect; HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; LRESULT checkState = SendMessageW(hwnd, BM_GETCHECK, 0, 0); DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); int part = ((dwStyle & BUTTON_TYPE) == BS_RADIOBUTTON) || ((dwStyle & BUTTON_TYPE) == BS_AUTORADIOBUTTON) ? BP_RADIOBUTTON : BP_CHECKBOX; int state = (part == BP_CHECKBOX) ? cb_states[ checkState ][ drawState ] : rb_states[ checkState ][ drawState ]; WCHAR *text = get_button_text(hwnd); GetClientRect(hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, part, state, &bgRect, &textRect); if (dtFlags & DT_SINGLELINE) /* Center the checkbox / radio button to the text. */ bgRect.top = bgRect.top + (textRect.bottom - textRect.top - cb_size) / 2; /* adjust for the check/radio marker */ bgRect.bottom = bgRect.top + cb_size; bgRect.right = bgRect.left + cb_size; textRect.left = bgRect.right + 6; if (IsThemeBackgroundPartiallyTransparent(theme, part, state)) DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, part, state, &bgRect, NULL); if (text) { DrawThemeText(theme, hDC, part, state, text, lstrlenW(text), dtFlags, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags) { static const int states[] = { GBS_NORMAL, GBS_DISABLED, GBS_NORMAL, GBS_NORMAL, GBS_NORMAL }; RECT bgRect, textRect, contentRect; HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; int state = states[ drawState ]; WCHAR *text = get_button_text(hwnd); GetClientRect(hwnd, &bgRect); textRect = bgRect; if (text) { SIZE textExtent; GetTextExtentPoint32W(hDC, text, lstrlenW(text), &textExtent); bgRect.top += (textExtent.cy / 2); textRect.left += 10; textRect.bottom = textRect.top + textExtent.cy; textRect.right = textRect.left + textExtent.cx + 4; ExcludeClipRect(hDC, textRect.left, textRect.top, textRect.right, textRect.bottom); } GetThemeBackgroundContentRect(theme, hDC, BP_GROUPBOX, state, &bgRect, &contentRect); ExcludeClipRect(hDC, contentRect.left, contentRect.top, contentRect.right, contentRect.bottom); if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state)) DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_GROUPBOX, state, &bgRect, NULL); SelectClipRgn(hDC, NULL); if (text) { textRect.left += 2; textRect.right -= 2; DrawThemeText(theme, hDC, BP_GROUPBOX, state, text, lstrlenW(text), 0, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused) { static const int states[] = { PBS_NORMAL, PBS_DISABLED, PBS_HOT, PBS_PRESSED, PBS_DEFAULTED }; RECT bgRect, textRect; HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; int state = states[ drawState ]; WCHAR *text = get_button_text(hwnd); GetClientRect(hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect); if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &bgRect, NULL); if (text) { DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (focused) { MARGINS margins; RECT focusRect = bgRect; GetThemeMargins(theme, hDC, BP_PUSHBUTTON, state, TMT_CONTENTMARGINS, NULL, &margins); focusRect.left += margins.cxLeftWidth; focusRect.top += margins.cyTopHeight; focusRect.right -= margins.cxRightWidth; focusRect.bottom -= margins.cyBottomHeight; DrawFocusRect( hDC, &focusRect ); } if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags) { static const int states[] = { PBS_NORMAL, PBS_DISABLED, PBS_HOT, PBS_PRESSED, PBS_DEFAULTED }; RECT bgRect, textRect; HFONT font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; int state = states[ drawState ]; WCHAR *text = get_button_text(hwnd); GetClientRect(hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect); if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &bgRect, NULL); if (text) { DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void GB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused) #endif { static const int states[] = { GBS_NORMAL, GBS_NORMAL, GBS_NORMAL, GBS_DISABLED, GBS_NORMAL }; RECT bgRect, textRect, contentRect; int state = states[ drawState ]; WCHAR *text = get_button_text(hwnd); LOGFONTW lf; HFONT font, hPrevFont = NULL; BOOL created_font = FALSE; #ifdef __REACTOS__ /* r74406 */ HWND parent; HBRUSH hBrush; RECT clientRect; #endif HRESULT hr = GetThemeFont(theme, hDC, BP_GROUPBOX, state, TMT_FONT, &lf); if (SUCCEEDED(hr)) { font = CreateFontIndirectW(&lf); if (!font) TRACE("Failed to create font\n"); else { hPrevFont = SelectObject(hDC, font); created_font = TRUE; } } else { #ifdef __REACTOS__ /* r73885 */ font = get_button_font(hwnd); #else font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); #endif hPrevFont = SelectObject(hDC, font); } GetClientRect(hwnd, &bgRect); textRect = bgRect; if (text) { SIZE textExtent; GetTextExtentPoint32W(hDC, text, lstrlenW(text), &textExtent); bgRect.top += (textExtent.cy / 2); textRect.left += 10; textRect.bottom = textRect.top + textExtent.cy; textRect.right = textRect.left + textExtent.cx + 4; ExcludeClipRect(hDC, textRect.left, textRect.top, textRect.right, textRect.bottom); } GetThemeBackgroundContentRect(theme, hDC, BP_GROUPBOX, state, &bgRect, &contentRect); ExcludeClipRect(hDC, contentRect.left, contentRect.top, contentRect.right, contentRect.bottom); #ifdef __REACTOS__ /* r73885 & r74149 */ if (prfFlag == 0) { if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state)) DrawThemeParentBackground(hwnd, hDC, NULL); } #else if (IsThemeBackgroundPartiallyTransparent(theme, BP_GROUPBOX, state)) DrawThemeParentBackground(hwnd, hDC, NULL); #endif #ifdef __REACTOS__ /* r74406 */ parent = GetParent(hwnd); if (!parent) parent = hwnd; hBrush = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)hwnd); if (!hBrush) /* did the app forget to call defwindowproc ? */ hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)hwnd ); GetClientRect(hwnd, &clientRect); FillRect( hDC, &clientRect, hBrush ); #endif DrawThemeBackground(theme, hDC, BP_GROUPBOX, state, &bgRect, NULL); SelectClipRgn(hDC, NULL); if (text) { InflateRect(&textRect, -2, 0); DrawThemeText(theme, hDC, BP_GROUPBOX, state, text, lstrlenW(text), 0, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (created_font) DeleteObject(font); if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void CB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused, LPARAM prfFlag) { static const int cb_states[3][5] = { { CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDDISABLED, CBS_UNCHECKEDNORMAL }, { CBS_CHECKEDNORMAL, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDDISABLED, CBS_CHECKEDNORMAL }, { CBS_MIXEDNORMAL, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDDISABLED, CBS_MIXEDNORMAL } }; static const int rb_states[2][5] = { { RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDDISABLED, RBS_UNCHECKEDNORMAL }, { RBS_CHECKEDNORMAL, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDDISABLED, RBS_CHECKEDNORMAL } }; SIZE sz; RECT bgRect, textRect; HFONT font, hPrevFont = NULL; LRESULT checkState = get_button_state(hwnd) & 3; DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); int part = ((dwStyle & BUTTON_TYPE) == BS_RADIOBUTTON) || ((dwStyle & BUTTON_TYPE) == BS_AUTORADIOBUTTON) ? BP_RADIOBUTTON : BP_CHECKBOX; int state = (part == BP_CHECKBOX) ? cb_states[ checkState ][ drawState ] : rb_states[ checkState ][ drawState ]; WCHAR *text; LOGFONTW lf; BOOL created_font = FALSE; HWND parent; HBRUSH hBrush; DWORD cdrf; HRESULT hr = GetThemeFont(theme, hDC, part, state, TMT_FONT, &lf); if (SUCCEEDED(hr)) { font = CreateFontIndirectW(&lf); if (!font) TRACE("Failed to create font\n"); else { TRACE("font = %s\n", debugstr_w(lf.lfFaceName)); hPrevFont = SelectObject(hDC, font); created_font = TRUE; } } else { font = get_button_font(hwnd); hPrevFont = SelectObject(hDC, font); } if (FAILED(GetThemePartSize(theme, hDC, part, state, NULL, TS_DRAW, &sz))) sz.cx = sz.cy = 13; GetClientRect(hwnd, &bgRect); if (prfFlag == 0) { DrawThemeParentBackground(hwnd, hDC, NULL); } parent = GetParent(hwnd); if (!parent) parent = hwnd; hBrush = (HBRUSH)SendMessageW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)hwnd); if (!hBrush) /* did the app forget to call defwindowproc ? */ hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, (WPARAM)hDC, (LPARAM)hwnd ); FillRect( hDC, &bgRect, hBrush ); cdrf = BUTTON_SendCustomDraw(hwnd, hDC, CDDS_PREERASE, &bgRect); if (cdrf == CDRF_SKIPDEFAULT) goto cleanup; GetThemeBackgroundContentRect(theme, hDC, part, state, &bgRect, &textRect); if (dtFlags & DT_SINGLELINE) /* Center the checkbox / radio button to the text. */ bgRect.top = bgRect.top + (textRect.bottom - textRect.top - sz.cy) / 2; /* adjust for the check/radio marker */ bgRect.bottom = bgRect.top + sz.cy; bgRect.right = bgRect.left + sz.cx; textRect.left = bgRect.right + 6; DrawThemeBackground(theme, hDC, part, state, &bgRect, NULL); if (cdrf == CDRF_NOTIFYPOSTERASE) BUTTON_SendCustomDraw(hwnd, hDC, CDDS_POSTERASE, &bgRect); cdrf = BUTTON_SendCustomDraw(hwnd, hDC, CDDS_PREPAINT, &bgRect); if (cdrf == CDRF_SKIPDEFAULT) goto cleanup; text = get_button_text(hwnd); if (text) { DrawThemeText(theme, hDC, part, state, text, lstrlenW(text), dtFlags, 0, &textRect); if (focused) { RECT focusRect; focusRect = textRect; DrawTextW(hDC, text, lstrlenW(text), &focusRect, dtFlags | DT_CALCRECT); if (focusRect.right < textRect.right) focusRect.right++; focusRect.bottom = textRect.bottom; DrawFocusRect( hDC, &focusRect ); } HeapFree(GetProcessHeap(), 0, text); } if (cdrf == CDRF_NOTIFYPOSTPAINT) BUTTON_SendCustomDraw(hwnd, hDC, CDDS_POSTPAINT, &bgRect); cleanup: if (created_font) DeleteObject(font); if (hPrevFont) SelectObject(hDC, hPrevFont); }
static void PB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused, LPARAM prfFlag) { static const int states[] = { PBS_NORMAL, PBS_HOT, PBS_PRESSED, PBS_DISABLED, PBS_DEFAULTED }; RECT bgRect, textRect; HFONT font = get_button_font(hwnd); HFONT hPrevFont = font ? SelectObject(hDC, font) : NULL; int state = states[ drawState ]; WCHAR *text; PBUTTON_DATA pdata = _GetButtonData(hwnd); HWND parent; DWORD cdrf; GetClientRect(hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, BP_PUSHBUTTON, state, &bgRect, &textRect); if (prfFlag == 0) { if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) DrawThemeParentBackground(hwnd, hDC, NULL); } parent = GetParent(hwnd); if (!parent) parent = hwnd; SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); cdrf = BUTTON_SendCustomDraw(hwnd, hDC, CDDS_PREERASE, &bgRect); if (cdrf == CDRF_SKIPDEFAULT) goto cleanup; DrawThemeBackground(theme, hDC, BP_PUSHBUTTON, state, &bgRect, NULL); if (cdrf == CDRF_NOTIFYPOSTERASE) BUTTON_SendCustomDraw(hwnd, hDC, CDDS_POSTERASE, &bgRect); cdrf = BUTTON_SendCustomDraw(hwnd, hDC, CDDS_PREPAINT, &bgRect); if (cdrf == CDRF_SKIPDEFAULT) goto cleanup; BUTTON_DrawIml(hDC, &pdata->imlData, &textRect, FALSE, drawState); text = get_button_text(hwnd); if (text) { DrawThemeText(theme, hDC, BP_PUSHBUTTON, state, text, lstrlenW(text), dtFlags, 0, &textRect); HeapFree(GetProcessHeap(), 0, text); } if (focused) { MARGINS margins; RECT focusRect = bgRect; GetThemeMargins(theme, hDC, BP_PUSHBUTTON, state, TMT_CONTENTMARGINS, NULL, &margins); focusRect.left += margins.cxLeftWidth; focusRect.top += margins.cyTopHeight; focusRect.right -= margins.cxRightWidth; focusRect.bottom -= margins.cyBottomHeight; DrawFocusRect( hDC, &focusRect ); } if (cdrf == CDRF_NOTIFYPOSTPAINT) BUTTON_SendCustomDraw(hwnd, hDC, CDDS_POSTPAINT, &bgRect); cleanup: if (hPrevFont) SelectObject(hDC, hPrevFont); }
/********************************************************************** * 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(HWND hwnd, HDC hdc, RECT *rc) { LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE ); LONG ex_style = GetWindowLongPtrW( hwnd, GWL_EXSTYLE ); WCHAR *text; ICONINFO iconInfo; BITMAP bm; UINT dtStyle = BUTTON_BStoDT( style, ex_style ); RECT r = *rc; INT n; /* Calculate label rectangle according to label type */ switch (style & (BS_ICON|BS_BITMAP)) { case BS_TEXT: if (!(text = get_button_text( hwnd ))) goto empty_rect; if (!text[0]) { HeapFree( GetProcessHeap(), 0, text ); goto empty_rect; } DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT); HeapFree( GetProcessHeap(), 0, text ); if (get_ui_state( hwnd ) & UISF_HIDEACCEL) dtStyle |= DT_HIDEPREFIX; break; case BS_ICON: if (!GetIconInfo((HICON)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), &iconInfo)) goto empty_rect; GetObjectW (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 (!GetObjectW( (HANDLE)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), sizeof(BITMAP), &bm)) goto empty_rect; r.right = r.left + bm.bmWidth; r.bottom = r.top + bm.bmHeight; break; default: empty_rect: rc->right = r.left; rc->bottom = r.top; return (UINT)-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; }
static void CB_draw(HTHEME theme, HWND hwnd, HDC hDC, ButtonState drawState, UINT dtFlags, BOOL focused) { static const int cb_states[3][5] = { { CBS_UNCHECKEDNORMAL, CBS_UNCHECKEDDISABLED, CBS_UNCHECKEDHOT, CBS_UNCHECKEDPRESSED, CBS_UNCHECKEDNORMAL }, { CBS_CHECKEDNORMAL, CBS_CHECKEDDISABLED, CBS_CHECKEDHOT, CBS_CHECKEDPRESSED, CBS_CHECKEDNORMAL }, { CBS_MIXEDNORMAL, CBS_MIXEDDISABLED, CBS_MIXEDHOT, CBS_MIXEDPRESSED, CBS_MIXEDNORMAL } }; static const int rb_states[2][5] = { { RBS_UNCHECKEDNORMAL, RBS_UNCHECKEDDISABLED, RBS_UNCHECKEDHOT, RBS_UNCHECKEDPRESSED, RBS_UNCHECKEDNORMAL }, { RBS_CHECKEDNORMAL, RBS_CHECKEDDISABLED, RBS_CHECKEDHOT, RBS_CHECKEDPRESSED, RBS_CHECKEDNORMAL } }; static const int cb_size = 13; RECT bgRect, textRect; HFONT font, hPrevFont = NULL; LRESULT checkState = SendMessageW(hwnd, BM_GETCHECK, 0, 0); DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); int part = ((dwStyle & BUTTON_TYPE) == BS_RADIOBUTTON) || ((dwStyle & BUTTON_TYPE) == BS_AUTORADIOBUTTON) ? BP_RADIOBUTTON : BP_CHECKBOX; int state = (part == BP_CHECKBOX) ? cb_states[ checkState ][ drawState ] : rb_states[ checkState ][ drawState ]; WCHAR *text = get_button_text(hwnd); LOGFONTW lf; BOOL created_font = FALSE; HRESULT hr = GetThemeFont(theme, hDC, part, state, TMT_FONT, &lf); if (SUCCEEDED(hr)) { font = CreateFontIndirectW(&lf); if (!font) TRACE("Failed to create font\n"); else { TRACE("font = %s\n", debugstr_w(lf.lfFaceName)); hPrevFont = SelectObject(hDC, font); created_font = TRUE; } } else font = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0); GetClientRect(hwnd, &bgRect); GetThemeBackgroundContentRect(theme, hDC, part, state, &bgRect, &textRect); if (dtFlags & DT_SINGLELINE) /* Center the checkbox / radio button to the text. */ bgRect.top = bgRect.top + (textRect.bottom - textRect.top - cb_size) / 2; /* adjust for the check/radio marker */ bgRect.bottom = bgRect.top + cb_size; bgRect.right = bgRect.left + cb_size; textRect.left = bgRect.right + 6; DrawThemeParentBackground(hwnd, hDC, NULL); DrawThemeBackground(theme, hDC, part, state, &bgRect, NULL); if (text) { DrawThemeText(theme, hDC, part, state, text, lstrlenW(text), dtFlags, 0, &textRect); if (focused) { RECT focusRect; focusRect = textRect; DrawTextW(hDC, text, lstrlenW(text), &focusRect, dtFlags | DT_CALCRECT); if (focusRect.right < textRect.right) focusRect.right++; focusRect.bottom = textRect.bottom; DrawFocusRect( hDC, &focusRect ); } HeapFree(GetProcessHeap(), 0, text); } if (created_font) DeleteObject(font); if (hPrevFont) SelectObject(hDC, hPrevFont); }