static void STATUSBAR_DrawSizeGrip (HTHEME theme, HDC hdc, LPRECT lpRect) { HPEN hPenFace, hPenShadow, hPenHighlight, hOldPen; POINT pt; INT i; TRACE("draw size grip %s\n", wine_dbgstr_rect(lpRect)); if (theme) { RECT gripperRect; SIZE gripperSize; gripperRect = *lpRect; if (SUCCEEDED (GetThemePartSize (theme, hdc, SP_GRIPPER, 0, lpRect, TS_DRAW, &gripperSize))) { gripperRect.left = gripperRect.right - gripperSize.cx; gripperRect.top = gripperRect.bottom - gripperSize.cy; if (SUCCEEDED (DrawThemeBackground(theme, hdc, SP_GRIPPER, 0, &gripperRect, NULL))) return; } } pt.x = lpRect->right - 1; pt.y = lpRect->bottom - 1; hPenFace = CreatePen( PS_SOLID, 1, comctl32_color.clr3dFace); hOldPen = SelectObject( hdc, hPenFace ); MoveToEx (hdc, pt.x - 12, pt.y, NULL); LineTo (hdc, pt.x, pt.y); LineTo (hdc, pt.x, pt.y - 13); pt.x--; pt.y--; hPenShadow = CreatePen( PS_SOLID, 1, comctl32_color.clr3dShadow); SelectObject( hdc, hPenShadow ); for (i = 1; i < 11; i += 4) { MoveToEx (hdc, pt.x - i, pt.y, NULL); LineTo (hdc, pt.x + 1, pt.y - i - 1); MoveToEx (hdc, pt.x - i - 1, pt.y, NULL); LineTo (hdc, pt.x + 1, pt.y - i - 2); } hPenHighlight = CreatePen( PS_SOLID, 1, comctl32_color.clr3dHilight); SelectObject( hdc, hPenHighlight ); for (i = 3; i < 13; i += 4) { MoveToEx (hdc, pt.x - i, pt.y, NULL); LineTo (hdc, pt.x + 1, pt.y - i - 1); } SelectObject (hdc, hOldPen); DeleteObject( hPenFace ); DeleteObject( hPenShadow ); DeleteObject( hPenHighlight ); }
// TODO run again when the DPI or the theme changes // TODO properly clean things up here // TODO properly destroy the old lists here too HRESULT uiprivUpdateImageListSize(uiTable *t) { HDC dc; int cxList, cyList; HTHEME theme; SIZE sizeCheck; HRESULT hr; dc = GetDC(t->hwnd); if (dc == NULL) { logLastError(L"GetDC()"); return E_FAIL; } cxList = GetSystemMetrics(SM_CXSMICON); cyList = GetSystemMetrics(SM_CYSMICON); sizeCheck.cx = cxList; sizeCheck.cy = cyList; theme = OpenThemeData(t->hwnd, L"button"); if (theme != NULL) { hr = GetThemePartSize(theme, dc, BP_CHECKBOX, CBS_UNCHECKEDNORMAL, NULL, TS_DRAW, &sizeCheck); if (hr != S_OK) { logHRESULT(L"GetThemePartSize()", hr); return hr; // TODO fall back? } // make sure these checkmarks fit // unthemed checkmarks will by the code above be smaller than cxList/cyList here if (cxList < sizeCheck.cx) cxList = sizeCheck.cx; if (cyList < sizeCheck.cy) cyList = sizeCheck.cy; hr = CloseThemeData(theme); if (hr != S_OK) { logHRESULT(L"CloseThemeData()", hr); return hr; } } // TODO handle errors t->imagelist = ImageList_Create(cxList, cyList, ILC_COLOR32, 1, 1); if (t->imagelist == NULL) { logLastError(L"ImageList_Create()"); return E_FAIL; } // TODO will this return NULL here because it's an initial state? SendMessageW(t->hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM) (t->imagelist)); if (ReleaseDC(t->hwnd, dc) == 0) { logLastError(L"ReleaseDC()"); return E_FAIL; } return S_OK; }
static SIZE getStateSize(HDC dc, int cbState, HTHEME theme) { SIZE s; HRESULT res; res = GetThemePartSize(theme, dc, BP_CHECKBOX, themestates[cbState], NULL, TS_DRAW, &s); if (res != S_OK) xpanichresult("error getting theme part size", res); return s; }
bool UGXPThemes::GetThemePartSize(LPCWSTR theme, HDC dc, int iPartId, int iStateId, RECT * pRect, int eSize, SIZE *psz) { bool success = false; if (useThemes) { HANDLE themeHandle = OpenThemeData(NULL, theme); if (themeHandle) { HRESULT hr = GetThemePartSize(themeHandle, dc, iPartId, iStateId, pRect, eSize, psz); success = SUCCEEDED(hr); } } return success; }
const QPixmap *QWindowsXPStylePrivate::tabBody( QWidget *widget ) { if ( !tabbody ) { tabbody = new QPixmap( 1, 1 ); QPainter painter( tabbody ); XPThemeData theme( widget, &painter, "TAB", TABP_BODY, 0 ); SIZE sz; GetThemePartSize( theme.handle(), painter.handle(), TABP_BODY, 0, 0, TS_TRUE, &sz ); painter.end(); tabbody->resize( sz.cx, sz.cy ); painter.begin( tabbody ); theme.rec = QRect( 0, 0, sz.cx, sz.cy ); theme.drawBackground(); painter.end(); } return tabbody; }
static void STATUSBAR_DrawSizeGrip (HTHEME theme, HDC hdc, LPRECT lpRect) { RECT rc = *lpRect; TRACE("draw size grip %s\n", wine_dbgstr_rect(lpRect)); if (theme) { SIZE gripperSize; if (SUCCEEDED (GetThemePartSize (theme, hdc, SP_GRIPPER, 0, lpRect, TS_DRAW, &gripperSize))) { rc.left = rc.right - gripperSize.cx; rc.top = rc.bottom - gripperSize.cy; if (SUCCEEDED (DrawThemeBackground(theme, hdc, SP_GRIPPER, 0, &rc, NULL))) return; } } rc.left = max( rc.left, rc.right - GetSystemMetrics(SM_CXVSCROLL) - 1 ); rc.top = max( rc.top, rc.bottom - GetSystemMetrics(SM_CYHSCROLL) - 1 ); DrawFrameControl( hdc, &rc, DFC_SCROLL, DFCS_SCROLLSIZEGRIP ); }
static HRESULT drawThemedCheckbox(struct drawState *s, HTHEME theme, int checked, int enabled) { RECT r; SIZE size; int state; HRESULT hr; hr = GetThemePartSize(theme, s->dc, BP_CHECKBOX, CBS_UNCHECKEDNORMAL, NULL, TS_DRAW, &size); if (hr != S_OK) { logHRESULT(L"GetThemePartSize()", hr); return hr; // TODO fall back? } r = s->m->subitemIcon; r.right = r.left + size.cx; r.bottom = r.top + size.cy; centerImageRect(&r, &(s->m->subitemIcon)); if (!checked && enabled) state = CBS_UNCHECKEDNORMAL; else if (checked && enabled) state = CBS_CHECKEDNORMAL; else if (!checked && !enabled) state = CBS_UNCHECKEDDISABLED; else state = CBS_CHECKEDDISABLED; hr = DrawThemeBackground(theme, s->dc, BP_CHECKBOX, state, &r, NULL); if (hr != S_OK) { logHRESULT(L"DrawThemeBackground()", hr); return hr; } return S_OK; }
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); }
LRESULT TreeListCustomDraw( HWND hwndHeader, LPNMTVCUSTOMDRAW pdraw ) { TCHAR textbuf[MAX_PATH]; TVITEMEX item; HBRUSH brush; HPEN pen; RECT hr, ir, subr; SIZE tsz; LONG i, c, cx; PTL_SUBITEMS subitem; HGDIOBJ prev; if ((pdraw->nmcd.dwDrawStage & CDDS_ITEM) == 0) return CDRF_NOTIFYITEMDRAW; RtlSecureZeroMemory(&item, sizeof(item)); RtlSecureZeroMemory(&textbuf, sizeof(textbuf)); item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM | TVIF_CHILDREN | TVIF_STATE; item.hItem = (HTREEITEM)pdraw->nmcd.dwItemSpec; item.cchTextMax = (sizeof(textbuf) / sizeof(TCHAR)) - 1; item.pszText = textbuf; TreeView_GetItem(pdraw->nmcd.hdr.hwndFrom, &item); subitem = (PTL_SUBITEMS)item.lParam; RtlSecureZeroMemory(&hr, sizeof(hr)); TreeView_GetItemRect(pdraw->nmcd.hdr.hwndFrom, (HTREEITEM)pdraw->nmcd.dwItemSpec, &ir, TRUE); //FillRect(pdraw->nmcd.hdc, &pdraw->nmcd.rc, GetSysColorBrush(COLOR_WINDOW)); if (item.cChildren == 1) { RtlSecureZeroMemory(&tsz, sizeof(tsz)); if (GetThemePartSize(tl_theme, pdraw->nmcd.hdc, TVP_GLYPH, GLPS_CLOSED, NULL, TS_TRUE, &tsz) != S_OK) { tsz.cx = 8; tsz.cy = 8; } subr.top = ir.top + (((ir.bottom - ir.top) - tsz.cy) / 2); subr.bottom = subr.top + tsz.cy; subr.left = ir.left - tsz.cx - 3; subr.right = ir.left - 3; if ((item.state & TVIS_EXPANDED) == 0) i = GLPS_CLOSED; else i = GLPS_OPENED; DrawThemeBackground(tl_theme, pdraw->nmcd.hdc, TVP_GLYPH, i, &subr, NULL); } cx = 0; c = Header_GetItemCount(hwndHeader); for (i = 0; i < c; i++) { RtlSecureZeroMemory(&hr, sizeof(hr)); Header_GetItemRect(hwndHeader, i, &hr); if (hr.right > cx) cx = hr.right; } if ((subitem) && ((pdraw->nmcd.uItemState & CDIS_FOCUS)) == 0) { if (subitem->ColorFlags & TLF_BGCOLOR_SET) { pdraw->clrTextBk = subitem->BgColor; SetBkColor(pdraw->nmcd.hdc, subitem->BgColor); } if (subitem->ColorFlags & TLF_FONTCOLOR_SET) { pdraw->clrText = subitem->FontColor; SetTextColor(pdraw->nmcd.hdc, subitem->FontColor); } } brush = CreateSolidBrush(pdraw->clrTextBk); subr.top = ir.top; subr.bottom = ir.bottom - 1; subr.left = ir.left; subr.right = cx; FillRect(pdraw->nmcd.hdc, &subr, brush); DeleteObject(brush); Header_GetItemRect(hwndHeader, 0, &hr); subr.right = hr.right - 3; subr.left += 3; DrawText(pdraw->nmcd.hdc, textbuf, -1, &subr, DT_END_ELLIPSIS | DT_VCENTER | DT_SINGLELINE); ir.right = cx; pen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_MENUBAR)); prev = SelectObject(pdraw->nmcd.hdc, pen); for (i = 0; i < c; i++) { RtlSecureZeroMemory(&hr, sizeof(hr)); Header_GetItemRect(hwndHeader, i, &hr); if ((i > 0) && subitem) if (i <= (LONG)subitem->Count) if (subitem->Text[i - 1]) { subr.top = ir.top; subr.bottom = ir.bottom; subr.left = hr.left + 3; subr.right = hr.right - 3; DrawText(pdraw->nmcd.hdc, subitem->Text[i - 1], -1, &subr, DT_END_ELLIPSIS | DT_VCENTER | DT_SINGLELINE); } MoveToEx(pdraw->nmcd.hdc, hr.left, ir.bottom - 1, NULL); LineTo(pdraw->nmcd.hdc, hr.right - 1, ir.bottom - 1); LineTo(pdraw->nmcd.hdc, hr.right - 1, ir.top - 1); } SelectObject(pdraw->nmcd.hdc, prev); DeleteObject(pen); if ((pdraw->nmcd.uItemState & CDIS_FOCUS) != 0) DrawFocusRect(pdraw->nmcd.hdc, &ir); return CDRF_SKIPDEFAULT; }
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 } }; SIZE sz; 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); hPrevFont = SelectObject(hDC, font); } if (FAILED(GetThemePartSize(theme, hDC, part, state, NULL, TS_DRAW, &sz))) sz.cx = sz.cy = 13; 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 - 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; 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); }