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); }
void CEditWithButton_Base::DrawButton(CRect rectButton) { CWindowDC dc(this); HTHEME hButtonTheme = OpenThemeData(m_hWnd, _T("Button")); if (hButtonTheme) { int ButtonState = GetButtonThemeState(); // If necessary, first fill with the edit control's background color. if (IsThemeBackgroundPartiallyTransparent(hButtonTheme, BP_PUSHBUTTON, ButtonState)) { HTHEME hEditTheme = OpenThemeDataEx(m_hWnd, _T("Edit"), OTD_NONCLIENT); COLORREF BgColor = RGB(0, 0, 0); BgColor = GetThemeSysColor(hEditTheme, (GetStyle() & (ES_READONLY | WS_DISABLED)) ? COLOR_3DFACE : COLOR_WINDOW); dc.FillSolidRect(rectButton, BgColor); CloseThemeData(hEditTheme); } DrawThemeBackground(hButtonTheme, dc, BP_PUSHBUTTON, ButtonState, rectButton, NULL); DrawButtonContent(dc, rectButton, hButtonTheme); CloseThemeData(hButtonTheme); } else { UINT uState = DFCS_BUTTONPUSH; if (GetStyle() & (ES_READONLY | WS_DISABLED)) uState |= DFCS_INACTIVE; else if (m_IsButtonPressed) uState |= DFCS_PUSHED; dc.DrawFrameControl(rectButton, DFC_BUTTON, uState); // If the button is in a pressed state, then contents should move slightly as part of the "push" effect. if (m_IsButtonPressed) rectButton.OffsetRect(1, 1); DrawButtonContent(dc, rectButton, NULL); } }
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HDC hdc = (HDC) wParam; if (!TrayTheme) { bHandled = FALSE; return 0; } RECT rect; GetClientRect(&rect); if (IsThemeBackgroundPartiallyTransparent(TrayTheme, TNP_BACKGROUND, 0)) DrawThemeParentBackground(m_hWnd, hdc, &rect); DrawThemeBackground(TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0); return TRUE; }
/* Draw themed border */ static void nc_paint (HTHEME theme, HWND hwnd, HRGN region) { HRGN cliprgn = region; DWORD exStyle = GetWindowLongW (hwnd, GWL_EXSTYLE); if (exStyle & WS_EX_CLIENTEDGE) { HDC dc; RECT r; int cxEdge = GetSystemMetrics (SM_CXEDGE), cyEdge = GetSystemMetrics (SM_CYEDGE); int part = EP_EDITTEXT; int state = ETS_NORMAL; DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); if (!IsWindowEnabled (hwnd)) state = ETS_DISABLED; else if (dwStyle & ES_READONLY) state = ETS_READONLY; else if (GetFocus() == hwnd) state = ETS_FOCUSED; GetWindowRect(hwnd, &r); /* New clipping region passed to default proc to exclude border */ cliprgn = CreateRectRgn (r.left + cxEdge, r.top + cyEdge, r.right - cxEdge, r.bottom - cyEdge); if (region != (HRGN)1) CombineRgn (cliprgn, cliprgn, region, RGN_AND); OffsetRect(&r, -r.left, -r.top); dc = GetDCEx(hwnd, region, DCX_WINDOW|DCX_INTERSECTRGN); OffsetRect(&r, -r.left, -r.top); if (IsThemeBackgroundPartiallyTransparent (theme, part, state)) DrawThemeParentBackground(hwnd, dc, &r); DrawThemeBackground (theme, dc, part, state, &r, 0); ReleaseDC(hwnd, dc); } /* Call default proc to get the scrollbars etc. also painted */ DefWindowProcW (hwnd, WM_NCPAINT, (WPARAM)cliprgn, 0); }
/******************************************** DrawBackground Purpose Provides a more straightforward way to draw a background by wrapping all the calls required into the dll, as well as using our theme data mappings to find the core info required. Params hwnd - the HWND of the control we draw to, or NUL hdc - the device context for the dll to draw to type - the cell type we want to draw state - the state of the cell we want to draw pRect - represents the area we want to draw to pClipRect - is exposed, but is almost always NULL Return A bool to indicate success or failure, which is used to control drawing in the old style throughout the library *********************************************/ bool UGXPThemes::DrawBackground(HWND hwnd, HDC hdc, UGXPCellType type, UGXPThemeState state, const RECT *pRect, const RECT *pClipRect) { bool success = false; if (useThemes) { UGThemeData * td = LookupThemeData(type, state); if (!td) { return false; } HANDLE hTheme = OpenThemeData(hwnd, td->GetThemeName()); if(hTheme) { // If the background is transparent, we draw using the Data cell type first, // which fills the background. DrawThemeParentBackground just plain does not work // for us, perhaps because the parent is an owner drawn control ? // Of course, if the Data cell type has transparency, all we can do is return E_FAILED if (IsThemeBackgroundPartiallyTransparent(hTheme, td->GetPartID(), td->GetStateID())) { if (type == XPCellTypeData) return FALSE; UGThemeData * tdCell = LookupThemeData(XPCellTypeData, (state == ThemeStatePressed || state == ThemeStateTriState) ? ThemeStateNormal : state); HANDLE hThemeCell = OpenThemeData(hwnd, tdCell->GetThemeName()); DrawThemeBackground(hThemeCell, hdc, tdCell->GetPartID(), tdCell->GetStateID(), pRect, pClipRect); } success = SUCCEEDED(DrawThemeBackground(hTheme, hdc, td->GetPartID(), td->GetStateID(), pRect, pClipRect)); // CloseThemeData(hTheme); } } return success; }
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); }
/******************************************** DrawBackground Purpose Provides a more straightforward way to draw a background by wrapping all the calls required into the dll, as well as using our theme data mappings to find the core info required. This version still takes a theme name instead of using our lookup table, it's used in cases where we hard code the theme part ( such a progress bars ) Params hwnd - the HWND of the control we draw to, or NUL hdc - the device context for the dll to draw to theme - the name of the theme to use iPartId - the theme part to draw iStateId - the state of the part to draw pRect - represents the area we want to draw to pClipRect - is exposed, but is almost always NULL Return A bool to indicate success or failure, which is used to control drawing in the old style throughout the library *********************************************/ bool UGXPThemes::DrawBackground(HWND hwnd, HDC hdc, LPCWSTR theme, int partID, int stateID, const RECT *pRect, const RECT *pClipRect, bool useCache) { bool success = false; if (useThemes) { HANDLE themeHandle = OpenThemeData(hwnd, theme, useCache); if (themeHandle) { // If the background is transparent, we draw using the Data cell type first, // which fills the background. DrawThemeParentBackground just plain does not work // for us, perhaps because the parent is an owner drawn control ? // Of course, if the Data cell type has transparency, this will fail. if (IsThemeBackgroundPartiallyTransparent(themeHandle, partID, stateID)) { //RECT temp = *pRect; UGThemeData * tdCell = LookupThemeData(XPCellTypeData, ThemeStateNormal); HANDLE hThemeCell = OpenThemeData(hwnd, tdCell->GetThemeName()); DrawThemeBackground(hThemeCell, hdc, partID, stateID, pRect, pClipRect); } HRESULT hr = DrawThemeBackground(themeHandle, hdc, partID, stateID, pRect, pClipRect); success = SUCCEEDED(hr); if (!useCache) { CloseThemeData(themeHandle); } } } return success; }
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); }
void CClosableTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS) { CRect rect(lpDIS->rcItem); int nTabIndex = lpDIS->itemID; if (nTabIndex < 0) return; TCHAR szLabel[256]; TC_ITEM tci; tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE; tci.pszText = szLabel; tci.cchTextMax = _countof(szLabel); tci.dwStateMask = TCIS_HIGHLIGHTED; if (!GetItem(nTabIndex, &tci)) return; szLabel[_countof(szLabel) - 1] = _T('\0'); //TRACE("CClosableTabCtrl::DrawItem: item=%u, state=%08x, color=%08x, rc=%3d,%3d,%3dx%3d\n", nTabIndex, tci.dwState, GetTextColor(lpDIS->hDC), lpDIS->rcItem.left, lpDIS->rcItem.top, lpDIS->rcItem.right - lpDIS->rcItem.left, lpDIS->rcItem.bottom - lpDIS->rcItem.top); CDC* pDC = CDC::FromHandle(lpDIS->hDC); if (!pDC) return; CRect rcFullItem(lpDIS->rcItem); bool bSelected = (lpDIS->itemState & ODS_SELECTED) != 0; /////////////////////////////////////////////////////////////////////////////////////// // Adding support for XP Styles (Vista Themes) for owner drawn tab controls simply // does *not* work under Vista. Maybe it works under XP (did not try), but that is // meaningless because under XP a owner drawn tab control is already rendered *with* // the proper XP Styles. So, for XP there is no need to care about the theme API at all. // // However, under Vista, a tab control which has the TCS_OWNERDRAWFIXED // style gets additional 3D-borders which are applied by Vista *after* WM_DRAWITEM // was processed. Thus, there is no known workaround available to prevent Vista from // adding those old fashioned 3D-borders. We can render the tab control items within // the WM_DRAWITEM handler in whatever style we want, but Vista will in each case // overwrite the borders of each tab control item with old fashioned 3D-borders... // // To complete this experience, tab controls also do not support NMCUSTOMDRAW. So, the // only known way to customize a tab control is by using TCS_OWNERDRAWFIXED which does // however not work properly under Vista. // // The "solution" which is currently implemented to prevent Vista from drawing those // 3D-borders is by using "ExcludeClipRect" to reduce the drawing area which is used // by Windows after WM_DRAWITEM was processed. This "solution" is very sensitive to // the used rectangles and offsets in general. Incrementing/Decrementing one of the // "rcItem", "rcFullItem", etc. rectangles makes the entire "solution" flawed again // because some borders would become visible again. // HTHEME hTheme = NULL; int iPartId = TABP_TABITEM; int iStateId = TIS_NORMAL; bool bVistaHotTracked = false; bool bVistaThemeActive = theApp.IsVistaThemeActive(); if (bVistaThemeActive) { // To determine if the current item is in 'hot tracking' mode, we need to evaluate // the current foreground color - there is no flag which would indicate this state // more safely. This applies only for Vista and for tab controls which have the // TCS_OWNERDRAWFIXED style. bVistaHotTracked = pDC->GetTextColor() == GetSysColor(COLOR_HOTLIGHT); hTheme = OpenThemeData(m_hWnd, L"TAB"); if (hTheme) { if (bSelected) { // get the real tab item rect rcFullItem.left += 1; rcFullItem.right -= 1; rcFullItem.bottom -= 1; } else rcFullItem.InflateRect(2, 2); // get the real tab item rect CRect rcBk(rcFullItem); if (bSelected) { iStateId = TTIS_SELECTED; if (nTabIndex == 0) { // First item if (nTabIndex == GetItemCount() - 1) iPartId = TABP_TOPTABITEMBOTHEDGE; // First & Last item else iPartId = TABP_TOPTABITEMLEFTEDGE; } else if (nTabIndex == GetItemCount() - 1) { // Last item iPartId = TABP_TOPTABITEMRIGHTEDGE; } else { iPartId = TABP_TOPTABITEM; } } else { rcBk.top += 2; iStateId = bVistaHotTracked ? TIS_HOT : TIS_NORMAL; if (nTabIndex == 0) { // First item if (nTabIndex == GetItemCount() - 1) iPartId = TABP_TABITEMBOTHEDGE; // First & Last item else iPartId = TABP_TABITEMLEFTEDGE; } else if (nTabIndex == GetItemCount() - 1) { // Last item iPartId = TABP_TABITEMRIGHTEDGE; } else { iPartId = TABP_TABITEM; } } if (IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId)) DrawThemeParentBackground(m_hWnd, *pDC, &rcFullItem); DrawThemeBackground(hTheme, *pDC, iPartId, iStateId, &rcBk, NULL); } } // Following background clearing is needed for: // WinXP/Vista (when used without an application theme) // Vista (when used with an application theme but without a theme for the tab control) if ( (!IsThemeActive() || !IsAppThemed()) || (hTheme == NULL && bVistaThemeActive) ) pDC->FillSolidRect(&lpDIS->rcItem, GetSysColor(COLOR_BTNFACE)); int iOldBkMode = pDC->SetBkMode(TRANSPARENT); // Draw image on left side CImageList *piml = GetImageList(); if (tci.iImage >= 0 && piml && piml->m_hImageList) { IMAGEINFO ii; piml->GetImageInfo(0, &ii); rect.left += bSelected ? 8 : 4; piml->Draw(pDC, tci.iImage, CPoint(rect.left, rect.top + 2), ILD_TRANSPARENT); rect.left += (ii.rcImage.right - ii.rcImage.left); if (!bSelected) rect.left += 4; } bool bCloseable = m_bCloseable; if (bCloseable && GetParent()->SendMessage(UM_QUERYTAB, nTabIndex)) bCloseable = false; // Draw 'Close button' at right side if (bCloseable && m_ImgLstCloseButton.m_hImageList) { CRect rcCloseButton; GetCloseButtonRect(nTabIndex, rect, rcCloseButton, bSelected, bVistaThemeActive); HTHEME hThemeNC = bVistaThemeActive ? OpenThemeData(m_hWnd, _T("WINDOW")) : NULL; if (hThemeNC) { // Possible "Close" parts: WP_CLOSEBUTTON, WP_SMALLCLOSEBUTTON, WP_MDICLOSEBUTTON int iPartId = WP_SMALLCLOSEBUTTON; int iStateId = (bSelected || bVistaHotTracked) ? CBS_NORMAL : CBS_DISABLED; if (IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId)) DrawThemeParentBackground(m_hWnd, *pDC, &rcCloseButton); DrawThemeBackground(hThemeNC, *pDC, iPartId, iStateId, rcCloseButton, NULL); CloseThemeData(hThemeNC); } else { m_ImgLstCloseButton.Draw(pDC, (bSelected || bVistaHotTracked) ? 0 : 1, rcCloseButton.TopLeft(), ILD_TRANSPARENT); } rect.right = rcCloseButton.left - 2; if (bSelected) rect.left += hTheme ? 4 : 2; } COLORREF crOldColor = CLR_NONE; if (tci.dwState & TCIS_HIGHLIGHTED) crOldColor = pDC->SetTextColor(RGB(192, 0, 0)); else if (bVistaHotTracked) crOldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT)); rect.top += bSelected ? 4 : 3; // Vista: Tab control has troubles with determining the width of a tab if the // label contains one '&' character. To get around this, we use the old code which // replaces one '&' character with two '&' characters and we do not specify DT_NOPREFIX // here when drawing the text. // // Vista: "DrawThemeText" can not be used in case we need a certain foreground color. Thus we always us // "DrawText" to always get the same font and metrics (just for safety). pDC->DrawText(szLabel, rect, DT_SINGLELINE | DT_TOP | DT_CENTER /*| DT_NOPREFIX*/); if (crOldColor != CLR_NONE) pDC->SetTextColor(crOldColor); pDC->SetBkMode(iOldBkMode); if (hTheme) { CRect rcClip(rcFullItem); if (bSelected) { rcClip.left -= 2 + 1; rcClip.right += 2 + 1; } else { rcClip.top += 2; } pDC->ExcludeClipRect(&rcClip); CloseThemeData(hTheme); } }
static void on_draw_item(HWND hDlg, WPARAM wParam, LPARAM lParam) { static HBRUSH black_brush = 0; LPDRAWITEMSTRUCT draw_info = (LPDRAWITEMSTRUCT)lParam; if (!black_brush) black_brush = CreateSolidBrush(0); if (draw_info->CtlID == IDC_SYSPARAM_COLOR) { UINT state; HTHEME theme; RECT buttonrect; theme = OpenThemeData(NULL, WC_BUTTONW); if (theme) { MARGINS margins; if (draw_info->itemState & ODS_DISABLED) state = PBS_DISABLED; else if (draw_info->itemState & ODS_SELECTED) state = PBS_PRESSED; else state = PBS_NORMAL; if (IsThemeBackgroundPartiallyTransparent(theme, BP_PUSHBUTTON, state)) DrawThemeParentBackground(draw_info->hwndItem, draw_info->hDC, NULL); DrawThemeBackground(theme, draw_info->hDC, BP_PUSHBUTTON, state, &draw_info->rcItem, NULL); buttonrect = draw_info->rcItem; GetThemeMargins(theme, draw_info->hDC, BP_PUSHBUTTON, state, TMT_CONTENTMARGINS, &draw_info->rcItem, &margins); buttonrect.left += margins.cxLeftWidth; buttonrect.top += margins.cyTopHeight; buttonrect.right -= margins.cxRightWidth; buttonrect.bottom -= margins.cyBottomHeight; if (draw_info->itemState & ODS_FOCUS) DrawFocusRect(draw_info->hDC, &buttonrect); CloseThemeData(theme); } else { state = DFCS_ADJUSTRECT | DFCS_BUTTONPUSH; if (draw_info->itemState & ODS_DISABLED) state |= DFCS_INACTIVE; else state |= draw_info->itemState & ODS_SELECTED ? DFCS_PUSHED : 0; DrawFrameControl(draw_info->hDC, &draw_info->rcItem, DFC_BUTTON, state); buttonrect = draw_info->rcItem; } if (!(draw_info->itemState & ODS_DISABLED)) { HBRUSH brush; int index = SendDlgItemMessageW(hDlg, IDC_SYSPARAM_COMBO, CB_GETCURSEL, 0, 0); index = SendDlgItemMessageW(hDlg, IDC_SYSPARAM_COMBO, CB_GETITEMDATA, index, 0); brush = CreateSolidBrush(metrics[index].color); InflateRect(&buttonrect, -1, -1); FrameRect(draw_info->hDC, &buttonrect, black_brush); InflateRect(&buttonrect, -1, -1); FillRect(draw_info->hDC, &buttonrect, brush); DeleteObject(brush); } } }
/** * paints the background for a switchbar item. It can paint aero, visual styles, skins or * classic buttons (depending on os and current plugin settings). * * @param hdc HDC: target device context * @param rc RECT*: target rectangle * @param stateId the state identifier (normal, pressed, hot, disabled etc.) */ void __fastcall CSideBar::m_DefaultBackgroundRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item) { UINT id = item->getID(); int stateId = item->m_buttonControl->stateId; bool fIsActiveItem = (item->m_sideBar->getActiveItem() == item); if (CSkin::m_skinEnabled) { TContainerData *pContainer = const_cast<TContainerData *>(item->m_sideBar->getContainer()); int ctrlId = stateId == PBS_PRESSED || fIsActiveItem ? ID_EXTBKBUTTONSPRESSED : (stateId == PBS_HOT ? ID_EXTBKBUTTONSMOUSEOVER : ID_EXTBKBUTTONSNPRESSED); CSkinItem *skinItem = &SkinItems[ctrlId]; HWND hwnd = item->m_buttonControl->hwnd; CSkin::SkinDrawBG(hwnd, pContainer->hwnd, pContainer, const_cast<RECT *>(rc), hdc); CSkin::DrawItem(hdc, rc, skinItem); } else if (M.isAero() || PluginConfig.m_fillColor) { if (id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) { if (M.isAero()) ::FillRect(hdc, const_cast<RECT *>(rc), CSkin::m_BrushBack); else CSkin::FillBack(hdc, const_cast<RECT *>(rc)); if (stateId == PBS_HOT || stateId == PBS_PRESSED) DrawAlpha(hdc, const_cast<RECT *>(rc), 0xf0f0f0, 70, 0x000000, 0, 9, 31, 4, 0); else DrawAlpha(hdc, const_cast<RECT *>(rc), 0xf0f0f0, 30, 0x707070, 0, 9, 31, 4, 0); } else { if (PluginConfig.m_fillColor) FillTabBackground(hdc, stateId, item->getDat(), const_cast<RECT *>(rc)); CSkin::m_switchBarItem->setAlphaFormat(AC_SRC_ALPHA, (stateId == PBS_HOT && !fIsActiveItem) ? 250 : (fIsActiveItem || stateId == PBS_PRESSED ? 250 : 230)); CSkin::m_switchBarItem->Render(hdc, rc, true); if (stateId == PBS_HOT || stateId == PBS_PRESSED || fIsActiveItem) { RECT rcGlow = *rc; rcGlow.top += 1; rcGlow.bottom -= 2; CSkin::m_tabGlowTop->setAlphaFormat(AC_SRC_ALPHA, (stateId == PBS_PRESSED || fIsActiveItem) ? 180 : 100); CSkin::m_tabGlowTop->Render(hdc, &rcGlow, true); } } } else if (M.isVSThemed()) { RECT *rcDraw = const_cast<RECT *>(rc); if (id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) { ::FillRect(hdc, rc, stateId == PBS_HOT ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); ::InflateRect(rcDraw, -2, 0); ::DrawEdge(hdc, rcDraw, EDGE_ETCHED, BF_SOFT | BF_RECT | BF_FLAT); } else { CSkin::FillBack(hdc, rcDraw); if (IsThemeBackgroundPartiallyTransparent(item->m_buttonControl->hThemeToolbar, TP_BUTTON, stateId)) DrawThemeParentBackground(item->getHwnd(), hdc, rcDraw); if (M.isAero() || PluginConfig.m_WinVerMajor >= 6) { stateId = (fIsActiveItem ? PBS_PRESSED : PBS_HOT); DrawThemeBackground(item->m_buttonControl->hThemeToolbar, hdc, 8, RBStateConvert2Flat(stateId), rcDraw, rcDraw); } else { stateId = (fIsActiveItem ? PBS_PRESSED : PBS_HOT); DrawThemeBackground(item->m_buttonControl->hThemeToolbar, hdc, TP_BUTTON, TBStateConvert2Flat(stateId), rcDraw, rcDraw); } } } else { RECT *rcDraw = const_cast<RECT *>(rc); if (!(id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN)) { HBRUSH br = (stateId == PBS_HOT && !fIsActiveItem) ? ::GetSysColorBrush(COLOR_BTNSHADOW) : (fIsActiveItem || stateId == PBS_PRESSED ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); ::FillRect(hdc, rc, br); ::DrawEdge(hdc, rcDraw, (stateId == PBS_HOT && !fIsActiveItem) ? EDGE_ETCHED : (fIsActiveItem || stateId == PBS_PRESSED) ? EDGE_BUMP : EDGE_ETCHED, BF_RECT | BF_SOFT | BF_FLAT); } else { ::FillRect(hdc, rc, stateId == PBS_HOT ? ::GetSysColorBrush(COLOR_HOTLIGHT) : ::GetSysColorBrush(COLOR_3DFACE)); ::InflateRect(rcDraw, -2, 0); ::DrawEdge(hdc, rcDraw, EDGE_ETCHED, BF_SOFT | BF_RECT | BF_FLAT); } } }
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); }
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); }
bool playlist_view::draw_items(HDC dc, int start_item, int count) { // profiler(draw_items); if (!drawing_enabled) return false; static_api_ptr_t<playlist_manager> playlist_api; HDC hdc_mem = 0; RECT rect, item, item_area, bk, draw/*,text*/; GetClientRect(wnd_playlist, &rect); rect.top += get_header_height(); int item_height = get_item_height(); HBRUSH br = 0; HBITMAP hbm_mem = 0, hbm_old = 0; pfc::array_t<int, pfc::alloc_fast_aggressive> widths; int total_width = get_column_widths(widths); int t = columns.get_count(); const bit_array & p_mask = g_cache.active_get_columns_mask(); item_area.left = rect.left; item_area.right = rect.right; item_area.top = rect.top + (item_height*start_item); item_area.bottom = item_area.top + (item_height*count); item.left = 0 - horizontal_offset; item.right = item.left + total_width; item.top = 0; item.bottom = item.top + item_height; bk.top = 0; bk.left = 0; bk.bottom = item_height*count; bk.right = rect.right - rect.left; /*static */pfc::string8_fast_aggressive temp; temp.prealloc(512); /* edit01 */ hdc_mem = CreateCompatibleDC(dc); COLORREF colourfore = 0xff; hbm_mem = CreateCompatibleBitmap(dc, rect.right - rect.left, item_height*count); hbm_old = (HBITMAP)SelectObject(hdc_mem, hbm_mem); HGDIOBJ font_old = SelectObject(hdc_mem, g_font); cui::colours::helper p_helper(appearance_client_pv_impl::g_guid); //fill entire area with back colour br = CreateSolidBrush(p_helper.get_colour(cui::colours::colour_background)); FillRect(hdc_mem, &bk, br); DeleteObject(br); //need checks here because of filling background { int total = playlist_api->activeplaylist_get_item_count(); if (start_item + count + scroll_item_offset > total) //end item is NOT inclusive { count -= (start_item + count + scroll_item_offset) - total; } } int end_item = start_item + count; //draw each item int n, focus = playlist_api->activeplaylist_get_focus_item(); // static int pcount; t_size playing_index, playing_playlist; playlist_api->get_playing_item_location(&playing_playlist, &playing_index); bool b_playback = static_api_ptr_t<play_control>()->is_playing(); if (g_cache.get_active_playlist() != playing_playlist) playing_index = pfc_infinite; for (n = start_item; n < end_item; n++) { bool sel = playlist_api->activeplaylist_is_item_selected(n + scroll_item_offset); bool b_focused = GetFocus() == wnd_playlist || IsChild(wnd_playlist, GetFocus()); bool b_playing = b_playback && playing_index == (n + scroll_item_offset); //draw each column of each item int theme_state = NULL; if (sel) theme_state = (b_playing ? LISS_HOTSELECTED : (b_focused ? LISS_SELECTED : LISS_SELECTEDNOTFOCUS)); else if (b_playing) theme_state = LISS_HOT; bool b_themed = m_theme && p_helper.get_themed() && IsThemePartDefined(m_theme, LVP_LISTITEM, theme_state); if (b_themed && theme_state) { if (IsThemeBackgroundPartiallyTransparent(m_theme, LVP_LISTITEM, theme_state)) DrawThemeParentBackground(get_wnd(), hdc_mem, &item); DrawThemeBackground(m_theme, hdc_mem, LVP_LISTITEM, theme_state, &item, NULL); } //int total = playlist_api->activeplaylist_get_item_count(); int c, offset = 0, i = 0; for (c = 0; c < t; c++) { if (p_mask[c]) { draw.left = item.left + offset; draw.top = item.top; offset += widths[i]; draw.right = item.left + offset; draw.bottom = item.bottom; { // profiler_debug(draw_item_get_string); g_cache.active_get_display_name(n + scroll_item_offset, i, temp); } colourinfo colours(0x000000, 0x000000, 0xFF, 0xFF, 0, 0xFF); g_cache.active_get_colour(n + scroll_item_offset, i, colours); if (b_themed) { //COLORREF cr_back= get_default_colour(colours::COLOUR_BACK); //colourfore = get_default_colour(colours::COLOUR_TEXT); //GetThemeColor(m_theme, LVP_LISTITEM, sel ? (GetFocus() == wnd_playlist ? LIS_SELECTED : LIS_SELECTEDNOTFOCUS) : LIS_NORMAL, TMT_WINDOWTEXT, &colourfore); colourfore = GetThemeSysColor(m_theme, sel ? COLOR_BTNTEXT : COLOR_WINDOWTEXT); //GetThemeColor(m_theme, LVP_LISTITEM, sel ? (GetFocus() == wnd_playlist ? LIS_SELECTED : LIS_SELECTEDNOTFOCUS) : LIS_NORMAL, TMT_TEXTCOLOR, &colourfore); if (!theme_state) { //GetThemeColor(m_theme, LVP_LISTITEM, LIS_NORMAL, TMT_FILLCOLOR, &colourfore); br = CreateSolidBrush(colours.background_colour); FillRect(hdc_mem, &draw, br); } } else { if (sel) { /* TEST */ if (GetFocus() == wnd_playlist) { colourfore = colours.selected_text_colour; br = CreateSolidBrush(colours.selected_background_colour); } else { colourfore = colours.selected_text_colour_non_focus; br = CreateSolidBrush(colours.selected_background_colour_non_focus); } } else { colourfore = colours.text_colour; br = CreateSolidBrush(colours.background_colour); } //draw cell background //if (!b_themed) FillRect(hdc_mem, &draw, br); } if (br) { DeleteObject(br); br = 0; } //render text //if (b_themed) // DrawThemeText(m_theme, hdc_mem, LVP_LISTITEM, sel ? (GetFocus() == wnd_playlist ? LIS_SELECTED : LIS_SELECTEDNOTFOCUS) : LIS_NORMAL, L"test", 4, 0, 0, &draw); //else ui_helpers::text_out_colours_tab(hdc_mem, temp, temp.length(), 2, 1, &draw, sel, colourfore, TRUE, true, (cfg_ellipsis != 0), (ui_helpers::alignment)columns[c]->align); if (colours.use_frame_left) { HPEN pen = CreatePen(PS_SOLID, 1, colours.frame_left); HPEN pen_old = (HPEN)SelectObject(hdc_mem, pen); MoveToEx(hdc_mem, draw.left, draw.top, 0); LineTo(hdc_mem, draw.left, draw.bottom); SelectObject(hdc_mem, pen_old); DeleteObject(pen); } if (colours.use_frame_top) { HPEN pen = CreatePen(PS_SOLID, 1, colours.frame_top); HPEN pen_old = (HPEN)SelectObject(hdc_mem, pen); MoveToEx(hdc_mem, draw.left, draw.top, 0); LineTo(hdc_mem, draw.right, draw.top); SelectObject(hdc_mem, pen_old); DeleteObject(pen); } if (colours.use_frame_right) { HPEN pen = CreatePen(PS_SOLID, 1, colours.frame_right); HPEN pen_old = (HPEN)SelectObject(hdc_mem, pen); MoveToEx(hdc_mem, draw.right - 1, draw.top, 0); LineTo(hdc_mem, draw.right - 1, draw.bottom); SelectObject(hdc_mem, pen_old); DeleteObject(pen); } if (colours.use_frame_bottom) { HPEN pen = CreatePen(PS_SOLID, 1, colours.frame_bottom); HPEN pen_old = (HPEN)SelectObject(hdc_mem, pen); MoveToEx(hdc_mem, draw.right - 1, draw.bottom - 1, 0); LineTo(hdc_mem, draw.left - 1, draw.bottom - 1); SelectObject(hdc_mem, pen_old); DeleteObject(pen); } i++; } } //draw focus frame if ((n + scroll_item_offset) == focus) { if (m_always_show_focus || (!(SendMessage(get_wnd(), WM_QUERYUISTATE, NULL, NULL) & UISF_HIDEFOCUS) && b_focused)) { RECT rc_focus = item; if (m_theme && p_helper.get_themed() && IsThemePartDefined(m_theme, LVP_LISTITEM, LISS_SELECTED)) InflateRect(&rc_focus, -1, -1); if (!p_helper.get_bool(cui::colours::bool_use_custom_active_item_frame)) { DrawFocusRect(hdc_mem, &rc_focus); } else { br = CreateSolidBrush(p_helper.get_colour(cui::colours::colour_active_item_frame)); FrameRect(hdc_mem, &rc_focus, br); DeleteObject(br); } } } item.top += item_height; item.bottom += item_height; } BitBlt(dc, item_area.left, item_area.top, item_area.right - item_area.left, item_area.bottom - item_area.top, hdc_mem, 0, 0, SRCCOPY); if (font_old) SelectObject(hdc_mem, font_old); SelectObject(hdc_mem, hbm_old); DeleteObject(hbm_mem); DeleteDC(hdc_mem); return true; }
static LRESULT CALLBACK OptionsFilterSubclassProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message != WM_PAINT && message != WM_PRINT) return mir_callNextSubclass(hWnd, OptionsFilterSubclassProc, message, wParam, lParam); if (GetFocus() == hWnd || GetWindowTextLength(hWnd)) return mir_callNextSubclass(hWnd, OptionsFilterSubclassProc, message, wParam, lParam); RECT rc; GetClientRect(hWnd, &rc); HDC hdc; PAINTSTRUCT paint; if (message == WM_PAINT) hdc = BeginPaint(hWnd, &paint); else hdc = (HDC)wParam; TCHAR buf[255]; if (bSearchState == 1 && FilterLoadProgress < 100 && FilterLoadProgress > 0) mir_sntprintf(buf, SIZEOF(buf), TranslateT("Loading... %d%%"), FilterLoadProgress); else mir_sntprintf(buf, SIZEOF(buf), TranslateT("Search")); BOOL bDrawnByTheme = FALSE; int oldMode = SetBkMode(hdc, TRANSPARENT); HTHEME hTheme = OpenThemeData(hWnd, L"EDIT"); if (hTheme) { if (IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) DrawThemeParentBackground(hWnd, hdc, &rc); RECT rc2; GetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &rc, &rc2); rc2.top = 2 * rc.top - rc2.top; rc2.left = 2 * rc.left - rc2.left; rc2.bottom = 2 * rc.bottom - rc2.bottom; rc2.right = 2 * rc.right - rc2.right; DrawThemeBackground(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &rc2, &rc); HFONT hFont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0); HFONT oldFont = (HFONT)SelectObject(hdc, hFont); wchar_t *bufW = mir_t2u(buf); DrawThemeText(hTheme, hdc, EP_EDITTEXT, ETS_DISABLED, bufW, -1, 0, 0, &rc); mir_free(bufW); SelectObject(hdc, oldFont); CloseThemeData(hTheme); bDrawnByTheme = TRUE; } SetBkMode(hdc, oldMode); if (!bDrawnByTheme) { HFONT hFont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0); HFONT oldFont = (HFONT)SelectObject(hdc, hFont); SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); int oldMode = SetBkMode(hdc, TRANSPARENT); DrawText(hdc, buf, -1, &rc, 0); SetBkMode(hdc, oldMode); SelectObject(hdc, oldFont); } if (message == WM_PAINT) EndPaint(hWnd, &paint); return 0; }
static LRESULT IPADDRESS_Draw (const IPADDRESS_INFO *infoPtr, HDC hdc) { static const WCHAR dotW[] = { '.', 0 }; RECT rect, rcPart; COLORREF bgCol, fgCol; HTHEME theme; int i, state = ETS_NORMAL; TRACE("\n"); GetClientRect (infoPtr->Self, &rect); theme = OpenThemeData(infoPtr->Self, WC_EDITW); if (theme) { DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); if (!infoPtr->Enabled) state = ETS_DISABLED; else if (dwStyle & ES_READONLY) state = ETS_READONLY; else if (GetFocus() == infoPtr->Self) state = ETS_FOCUSED; GetThemeColor(theme, EP_EDITTEXT, state, TMT_FILLCOLOR, &bgCol); GetThemeColor(theme, EP_EDITTEXT, state, TMT_TEXTCOLOR, &fgCol); if (IsThemeBackgroundPartiallyTransparent (theme, EP_EDITTEXT, state)) DrawThemeParentBackground(infoPtr->Self, hdc, &rect); DrawThemeBackground (theme, hdc, EP_EDITTEXT, state, &rect, 0); } else { if (infoPtr->Enabled) { bgCol = comctl32_color.clrWindow; fgCol = comctl32_color.clrWindowText; } else { bgCol = comctl32_color.clr3dFace; fgCol = comctl32_color.clrGrayText; } FillRect (hdc, &rect, (HBRUSH)(DWORD_PTR)(bgCol+1)); DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); } SetBkColor (hdc, bgCol); SetTextColor(hdc, fgCol); for (i = 0; i < 3; i++) { GetWindowRect (infoPtr->Part[i].EditHwnd, &rcPart); MapWindowPoints( 0, infoPtr->Self, (POINT *)&rcPart, 2 ); rect.left = rcPart.right; GetWindowRect (infoPtr->Part[i+1].EditHwnd, &rcPart); MapWindowPoints( 0, infoPtr->Self, (POINT *)&rcPart, 2 ); rect.right = rcPart.left; if (theme) DrawThemeText(theme, hdc, EP_EDITTEXT, state, dotW, 1, DT_SINGLELINE | DT_CENTER | DT_BOTTOM, 0, &rect); else DrawTextW(hdc, dotW, 1, &rect, DT_SINGLELINE | DT_CENTER | DT_BOTTOM); } if (theme) CloseThemeData(theme); return 0; }
void CToolTipCtrlX::CustomPaint(LPNMTTCUSTOMDRAW pNMCD) { CWnd* pwnd = CWnd::FromHandle(pNMCD->nmcd.hdr.hwndFrom); CDC* pdc = CDC::FromHandle(pNMCD->nmcd.hdc); // Windows Vista (General) // ----------------------- // *Need* to use (some aspects) of the 'TOOLTIP' theme to get typical Vista tooltips. // // Windows Vista *without* SP1 // --------------------------- // The Vista 'TOOLTIP' theme offers a bold version of the standard tooltip font via // the TTP_STANDARDTITLE part id. Furthermore TTP_STANDARDTITLE is the same font as // the standard tooltip font (TTP_STANDARD). So, the 'TOOLTIP' theme can get used // thoroughly. // // Windows Vista *with* SP1 // ------------------------ // The Vista SP1(!) 'TOOLTIP' theme does though *not* offer a bold font. Keep // in mind that TTP_STANDARDTITLE does not return a bold font. Keep also in mind // that TTP_STANDARDTITLE is even a *different* font than TTP_STANDARD! // Which means, that TTP_STANDARDTITLE should *not* be used within the same line // as TTP_STANDARD. It just looks weird. TTP_STANDARDTITLE could be used for a // single line (the title line), but it would though not give us a bold font. // So, actually we can use the Vista 'TOOLTIP' theme only for getting the proper // tooltip background. // // Windows XP // ---------- // Can *not* use the 'TOOLTIP' theme at all because it would give us only a (non-bold) // black font on a white tooltip window background. Seems that the 'TOOLTIP' theme under // WinXP is just using the default Window values (black+white) and does not // use any of the tooltip specific Window metrics... // bool bUseEmbeddedThemeFonts = false; HTHEME hTheme = NULL; if (theApp.IsVistaThemeActive()) { hTheme = OpenThemeData(*pwnd, L"TOOLTIP"); // Using the theme's fonts works only under Vista without SP1. When SP1 // is installed the fonts which are used for TTP_STANDARDTITLE and TTP_STANDARD // do no longer match (should not get displayed within the same text line). if (hTheme) bUseEmbeddedThemeFonts = true; } CString strText; pwnd->GetWindowText(strText); CRect rcWnd; pwnd->GetWindowRect(&rcWnd); CFont* pOldDCFont = NULL; if (hTheme == NULL || !bUseEmbeddedThemeFonts) { // If we have a theme, we try to query the correct fonts from it if (m_fontNormal.m_hObject == NULL && hTheme) { // Windows Vista Ultimate, 6.0.6001 SP1 Build 6001, English with German Language Pack // ---------------------------------------------------------------------------------- // TTP_STANDARD, TTSS_NORMAL // Height -12 // Weight 400 // CharSet 1 // Quality 5 // FaceName "Segoe UI" // // TTP_STANDARDTITLE, TTSS_NORMAL // Height -12 // Weight 400 // CharSet 1 // Quality 5 // FaceName "Segoe UI Fett" (!!!) Note: "Fett" (that is German !?) // // That font name ("Segoe UI *Fett*") looks quite suspicious. I would not be surprised // if that eventually leads to a problem within the font mapper which may not be capable // of finding the (english) version of that font and thus falls back to the standard // system font. At least this would explain why the TTP_STANDARD and TTP_STANDARDTITLE // fonts are *different* on that particular Windows Vista system. LOGFONT lf = {0}; if (GetThemeFont(hTheme, pdc->m_hDC, TTP_STANDARD, TTSS_NORMAL, TMT_FONT, &lf) == S_OK) { VERIFY( m_fontNormal.CreateFontIndirect(&lf) ); if (m_bCol1Bold && m_fontBold.m_hObject == NULL) { memset(&lf, 0, sizeof(lf)); if (GetThemeFont(hTheme, pdc->m_hDC, TTP_STANDARDTITLE, TTSS_NORMAL, TMT_FONT, &lf) == S_OK) VERIFY( m_fontBold.CreateFontIndirect(&lf) ); } // Get the tooltip font color COLORREF crText; if (GetThemeColor(hTheme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &crText) == S_OK) m_crTooltipTextColor = crText; } } // If needed, create the standard tooltip font which was queried from the system metrics if (m_fontNormal.m_hObject == NULL && m_lfNormal.lfHeight != 0) VERIFY( m_fontNormal.CreateFontIndirect(&m_lfNormal) ); // Select the tooltip font if (m_fontNormal.m_hObject != NULL) { pOldDCFont = pdc->SelectObject(&m_fontNormal); // If needed, create the bold version of the tooltip font by deriving it from the standard font if (m_bCol1Bold && m_fontBold.m_hObject == NULL) { LOGFONT lf; m_fontNormal.GetLogFont(&lf); lf.lfWeight = FW_BOLD; VERIFY( m_fontBold.CreateFontIndirect(&lf) ); } } // Set the font color (queried from system metrics or queried from theme) pdc->SetTextColor(m_crTooltipTextColor); } // Auto-format the text only if explicitly requested. Otherwise we would also format // single line tooltips for regular list items, and if those list items contain ':' // characters they would be shown partially in bold. For performance reasons, the // auto-format is to be requested by appending the TOOLTIP_AUTOFORMAT_SUFFIX_CH // character. Appending, because we can remove that character efficiently without // re-allocating the entire string. bool bAutoFormatText = strText.GetLength() > 0 && strText[strText.GetLength() - 1] == TOOLTIP_AUTOFORMAT_SUFFIX_CH; if (bAutoFormatText) strText.Truncate(strText.GetLength() - 1); // truncate the TOOLTIP_AUTOFORMAT_SUFFIX_CH char by setting it to NUL bool bShowFileIcon = m_bShowFileIcon && bAutoFormatText; if (bShowFileIcon) { int iPosNL = strText.Find(_T('\n')); if (iPosNL > 0) { int iPosColon = strText.Find(_T(':')); if (iPosColon < iPosNL) bShowFileIcon = false; // 1st line does not contain a filename } } int iTextHeight = 0; int iMaxCol1Width = 0; int iMaxCol2Width = 0; int iMaxSingleLineWidth = 0; CSize sizText(0); int iPos = 0; int iCaptionHeight = 0; const int iCaptionEnd = bShowFileIcon ? max(strText.Find(_T("\n<br_head>\n")), 0) : 0; // special tooltip with file icon const int iLineHeightOff = 1; const int iIconMinYBorder = bShowFileIcon ? 3 : 0; const int iIconWidth = bShowFileIcon ? theApp.GetBigSytemIconSize().cx : 0; const int iIconHeight = bShowFileIcon ? theApp.GetBigSytemIconSize().cy : 0; const int iIconDrawingWidth = bShowFileIcon ? (iIconWidth + 9) : 0; while (iPos != -1) { CString strLine = GetNextString(strText, _T('\n'), iPos); int iColon = bAutoFormatText ? strLine.Find(_T(':')) : -1; if (iColon != -1) { CSize siz; if (hTheme && bUseEmbeddedThemeFonts) { CRect rcExtent; CRect rcBounding(0, 0, 32767, 32767); GetThemeTextExtent(hTheme, *pdc, m_bCol1Bold ? TTP_STANDARDTITLE : TTP_STANDARD, TTSS_NORMAL, strLine, iColon + 1, m_dwCol1DrawTextFlags, &rcBounding, &rcExtent); siz.cx = rcExtent.Width(); siz.cy = rcExtent.Height(); } else { CFont* pOldFont = m_bCol1Bold ? pdc->SelectObject(&m_fontBold) : NULL; siz = pdc->GetTextExtent(strLine, iColon + 1); if (pOldFont) pdc->SelectObject(pOldFont); } iMaxCol1Width = max<int>(iMaxCol1Width, siz.cx + ((bShowFileIcon && iPos <= iCaptionEnd + strLine.GetLength()) ? iIconDrawingWidth : 0)); iTextHeight = siz.cy + iLineHeightOff; // update height with 'col1' string, because 'col2' string might be empty and therefore has no height if (iPos <= iCaptionEnd) iCaptionHeight += siz.cy + iLineHeightOff; else sizText.cy += siz.cy + iLineHeightOff; LPCTSTR pszCol2 = (LPCTSTR)strLine + iColon + 1; while (_istspace((_TUCHAR)*pszCol2)) pszCol2++; if (*pszCol2 != _T('\0')) { if (hTheme && bUseEmbeddedThemeFonts) { CRect rcExtent; CRect rcBounding(0, 0, 32767, 32767); GetThemeTextExtent(hTheme, *pdc, TTP_STANDARD, TTSS_NORMAL, pszCol2, ((LPCTSTR)strLine + strLine.GetLength()) - pszCol2, m_dwCol2DrawTextFlags, &rcBounding, &rcExtent); siz.cx = rcExtent.Width(); siz.cy = rcExtent.Height(); } else { siz = pdc->GetTextExtent(pszCol2, ((LPCTSTR)strLine + strLine.GetLength()) - pszCol2); } iMaxCol2Width = max<int>(iMaxCol2Width, siz.cx); } } else if (bShowFileIcon && iPos <= iCaptionEnd && iPos == strLine.GetLength() + 1){ // file name, printed bold on top without any tabbing or desc CSize siz; if (hTheme && bUseEmbeddedThemeFonts) { CRect rcExtent; CRect rcBounding(0, 0, 32767, 32767); GetThemeTextExtent(hTheme, *pdc, m_bCol1Bold ? TTP_STANDARDTITLE : TTP_STANDARD, TTSS_NORMAL, strLine, strLine.GetLength(), m_dwCol1DrawTextFlags, &rcBounding, &rcExtent); siz.cx = rcExtent.Width(); siz.cy = rcExtent.Height(); } else { CFont* pOldFont = m_bCol1Bold ? pdc->SelectObject(&m_fontBold) : NULL; siz = pdc->GetTextExtent(strLine); if (pOldFont) pdc->SelectObject(pOldFont); } iMaxSingleLineWidth = max<int>(iMaxSingleLineWidth, siz.cx + iIconDrawingWidth); iCaptionHeight += siz.cy + iLineHeightOff; } else if (!strLine.IsEmpty() && strLine.Compare(_T("<br>")) != 0 && strLine.Compare(_T("<br_head>")) != 0) { CSize siz; if (hTheme && bUseEmbeddedThemeFonts) { CRect rcExtent; CRect rcBounding(0, 0, 32767, 32767); GetThemeTextExtent(hTheme, *pdc, TTP_STANDARD, TTSS_NORMAL, strLine, strLine.GetLength(), m_dwCol2DrawTextFlags, &rcBounding, &rcExtent); siz.cx = rcExtent.Width(); siz.cy = rcExtent.Height(); } else { siz = pdc->GetTextExtent(strLine); } iMaxSingleLineWidth = max<int>(iMaxSingleLineWidth, siz.cx + ((bShowFileIcon && iPos <= iCaptionEnd) ? iIconDrawingWidth : 0)); if (bShowFileIcon && iPos <= iCaptionEnd + strLine.GetLength()) iCaptionHeight += siz.cy + iLineHeightOff; else sizText.cy += siz.cy + iLineHeightOff; } else{ CSize siz; if (hTheme && bUseEmbeddedThemeFonts) { CRect rcExtent; CRect rcBounding(0, 0, 32767, 32767); GetThemeTextExtent(hTheme, *pdc, TTP_STANDARD, TTSS_NORMAL, _T(" "), 1, m_dwCol2DrawTextFlags, &rcBounding, &rcExtent); siz.cx = rcExtent.Width(); siz.cy = rcExtent.Height(); } else { // TODO: Would need to use 'GetTabbedTextExtent' here, but do we actually use 'tabbed' text here at all ?? siz = pdc->GetTextExtent(_T(" "), 1); } sizText.cy += siz.cy + iLineHeightOff; } } if (bShowFileIcon && iCaptionEnd > 0) iCaptionHeight = max<int>(iCaptionHeight, theApp.GetBigSytemIconSize().cy + (2*iIconMinYBorder)); sizText.cy += iCaptionHeight; if (hTheme && theApp.m_ullComCtrlVer >= MAKEDLLVERULL(6,16,0,0)) sizText.cy += 2; // extra bottom margin for Vista/Theme iMaxCol1Width = min(m_iScreenWidth4, iMaxCol1Width); iMaxCol2Width = min(m_iScreenWidth4*2, iMaxCol2Width); const int iMiddleMargin = 6; iMaxSingleLineWidth = max(iMaxSingleLineWidth, iMaxCol1Width + iMiddleMargin + iMaxCol2Width); if (iMaxSingleLineWidth > m_iScreenWidth4*3) iMaxSingleLineWidth = m_iScreenWidth4*3; sizText.cx = iMaxSingleLineWidth; if (pNMCD->uDrawFlags & DT_CALCRECT) { pNMCD->nmcd.rc.left = rcWnd.left; pNMCD->nmcd.rc.top = rcWnd.top; pNMCD->nmcd.rc.right = rcWnd.left + sizText.cx; pNMCD->nmcd.rc.bottom = rcWnd.top + sizText.cy; } else { pwnd->ScreenToClient(&rcWnd); int iOldBkColor = -1; if (hTheme) { int iPartId = TTP_STANDARD; int iStateId = TTSS_NORMAL; if (IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId)) DrawThemeParentBackground(m_hWnd, pdc->m_hDC, &rcWnd); DrawThemeBackground(hTheme, pdc->m_hDC, iPartId, iStateId, &rcWnd, NULL); } else { ::FillRect(*pdc, &rcWnd, GetSysColorBrush(COLOR_INFOBK)); iOldBkColor = pdc->SetBkColor(m_crTooltipBkColor); // Vista: Need to draw the window border explicitly !? if (theApp.m_ullComCtrlVer >= MAKEDLLVERULL(6,16,0,0)) { CPen pen; pen.CreatePen(0, 1, m_crTooltipTextColor); CPen *pOP = pdc->SelectObject(&pen); pdc->MoveTo(rcWnd.left, rcWnd.top); pdc->LineTo(rcWnd.right - 1, rcWnd.top); pdc->LineTo(rcWnd.right - 1, rcWnd.bottom - 1); pdc->LineTo(rcWnd.left, rcWnd.bottom - 1); pdc->LineTo(rcWnd.left, rcWnd.top); pdc->SelectObject(pOP); pen.DeleteObject(); } } int iOldBkMode = 0; if ((hTheme && !bUseEmbeddedThemeFonts) || (hTheme == NULL && iOldBkColor != -1)) iOldBkMode = pdc->SetBkMode(TRANSPARENT); CPoint ptText(pNMCD->nmcd.rc.left, pNMCD->nmcd.rc.top); iPos = 0; while (iPos != -1) { CString strLine = GetNextString(strText, _T('\n'), iPos); int iColon = bAutoFormatText ? strLine.Find(_T(':')) : -1; CRect rcDT; if (!bShowFileIcon || (unsigned)iPos > (unsigned)iCaptionEnd + strLine.GetLength()) rcDT.SetRect(ptText.x, ptText.y, ptText.x + iMaxCol1Width, ptText.y + iTextHeight); else rcDT.SetRect(ptText.x + iIconDrawingWidth, ptText.y, ptText.x + iMaxCol1Width, ptText.y + iTextHeight); if (iColon != -1) { // don't draw empty <col1> strings (they are still handy to use for skipping the <col1> space) if (iColon > 0) { if (hTheme && bUseEmbeddedThemeFonts) DrawThemeText(hTheme, pdc->m_hDC, m_bCol1Bold ? TTP_STANDARDTITLE : TTP_STANDARD, TTSS_NORMAL, strLine, iColon + 1, m_dwCol1DrawTextFlags, 0, &rcDT); else { CFont* pOldFont = m_bCol1Bold ? pdc->SelectObject(&m_fontBold) : NULL; pdc->DrawText(strLine, iColon + 1, &rcDT, m_dwCol1DrawTextFlags); if (pOldFont) pdc->SelectObject(pOldFont); } } LPCTSTR pszCol2 = (LPCTSTR)strLine + iColon + 1; while (_istspace((_TUCHAR)*pszCol2)) pszCol2++; if (*pszCol2 != _T('\0')) { rcDT.left = ptText.x + iMaxCol1Width + iMiddleMargin; rcDT.right = rcDT.left + iMaxCol2Width; if (hTheme && bUseEmbeddedThemeFonts) DrawThemeText(hTheme, pdc->m_hDC, TTP_STANDARD, TTSS_NORMAL, pszCol2, ((LPCTSTR)strLine + strLine.GetLength()) - pszCol2, m_dwCol2DrawTextFlags, 0, &rcDT); else pdc->DrawText(pszCol2, ((LPCTSTR)strLine + strLine.GetLength()) - pszCol2, &rcDT, m_dwCol2DrawTextFlags); } ptText.y += iTextHeight; } else if (bShowFileIcon && iPos <= iCaptionEnd && iPos == strLine.GetLength() + 1){ // first line on special fileicon tab - draw icon and bold filename if (hTheme && bUseEmbeddedThemeFonts) DrawThemeText(hTheme, pdc->m_hDC, m_bCol1Bold ? TTP_STANDARDTITLE : TTP_STANDARD, TTSS_NORMAL, strLine, strLine.GetLength(), m_dwCol1DrawTextFlags, 0, &CRect(ptText.x + iIconDrawingWidth, ptText.y, ptText.x + iMaxSingleLineWidth, ptText.y + iTextHeight)); else { CFont* pOldFont = m_bCol1Bold ? pdc->SelectObject(&m_fontBold) : NULL; pdc->DrawText(strLine, CRect(ptText.x + iIconDrawingWidth, ptText.y, ptText.x + iMaxSingleLineWidth, ptText.y + iTextHeight), m_dwCol1DrawTextFlags); if (pOldFont) pdc->SelectObject(pOldFont); } ptText.y += iTextHeight; int iImage = (int) theApp.GetFileTypeSystemImageIdx(strLine, -1, true); if (theApp.GetBigSystemImageList() != NULL) { int iPosY = rcDT.top; if (iCaptionHeight > iIconHeight) iPosY += (iCaptionHeight - iIconHeight) / 2; ::ImageList_Draw(theApp.GetBigSystemImageList(), iImage, pdc->GetSafeHdc(), ptText.x, iPosY, ILD_TRANSPARENT); } } else { bool bIsBrHeadLine = false; if (bAutoFormatText && (strLine.Compare(_T("<br>")) == 0 || (bIsBrHeadLine = strLine.Compare(_T("<br_head>")) == 0) == true)){ CPen pen; pen.CreatePen(0, 1, m_crTooltipTextColor); CPen *pOP = pdc->SelectObject(&pen); if (bIsBrHeadLine) ptText.y = iCaptionHeight; pdc->MoveTo(ptText.x, ptText.y + ((iTextHeight - 2) / 2)); pdc->LineTo(ptText.x + iMaxSingleLineWidth, ptText.y + ((iTextHeight - 2) / 2)); ptText.y += iTextHeight; pdc->SelectObject(pOP); pen.DeleteObject(); } else{ if (hTheme && bUseEmbeddedThemeFonts) { CRect rcLine(ptText.x, ptText.y, 32767, 32767); DrawThemeText(hTheme, pdc->m_hDC, TTP_STANDARD, TTSS_NORMAL, strLine, strLine.GetLength(), DT_EXPANDTABS | m_dwCol2DrawTextFlags, 0, &rcLine); ptText.y += iTextHeight; } else { // Text is written in the currently selected font. If 'nTabPositions' is 0 and 'lpnTabStopPositions' is NULL, // tabs are expanded to eight times the average character width. CSize siz; if (strLine.IsEmpty()) // Win98: To draw an empty line we need to output at least a space. siz = pdc->TabbedTextOut(ptText.x, ptText.y, _T(" "), 1, NULL, 0); else siz = pdc->TabbedTextOut(ptText.x, ptText.y, strLine, strLine.GetLength(), NULL, 0); ptText.y += siz.cy + iLineHeightOff; } } } } if (iOldBkColor != -1) pdc->SetBkColor(iOldBkColor); if (hTheme && !bUseEmbeddedThemeFonts) pdc->SetBkMode(iOldBkMode); } if (pOldDCFont) pdc->SelectObject(pOldDCFont); if (hTheme) CloseThemeData(hTheme); }
static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { TRichUtil *ru; EnterCriticalSection(&csRich); ru = rlist_find(slist, hwnd); LeaveCriticalSection(&csRich); switch(msg) { case WM_THEMECHANGED: case WM_STYLECHANGED: RichUtil_ClearUglyBorder(ru); break; case WM_NCPAINT: { LRESULT ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); if (ru->hasUglyBorder && IsThemeActive()) { HANDLE hTheme = OpenThemeData(ru->hwnd, L"EDIT"); if (hTheme) { RECT rcBorder; RECT rcClient; int nState; HDC hdc = GetWindowDC(ru->hwnd); GetWindowRect(hwnd, &rcBorder); rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top; rcBorder.left = rcBorder.top = 0; CopyRect(&rcClient, &rcBorder); rcClient.left += ru->rect.left; rcClient.top += ru->rect.top; rcClient.right -= ru->rect.right; rcClient.bottom -= ru->rect.bottom; ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); if(IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) DrawThemeParentBackground(hwnd, hdc, &rcBorder); if (!IsWindowEnabled(hwnd)) nState = ETS_DISABLED; else if(SendMessage(hwnd, EM_GETOPTIONS, 0, 0) & ECO_READONLY) nState = ETS_READONLY; else nState = ETS_NORMAL; DrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL); CloseThemeData(hTheme); ReleaseDC(hwnd, hdc); return 0; } } return ret; } case WM_NCCALCSIZE: { LRESULT ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS*)lParam; if (ru->hasUglyBorder && IsThemeActive()) { HANDLE hTheme = OpenThemeData(hwnd, L"EDIT"); if (hTheme) { RECT rcClient; HDC hdc = GetDC(GetParent(hwnd)); ZeroMemory(&rcClient, sizeof(RECT)); if(GetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK) { ru->rect.left = rcClient.left-ncsParam->rgrc[0].left; ru->rect.top = rcClient.top-ncsParam->rgrc[0].top; ru->rect.right = ncsParam->rgrc[0].right-rcClient.right; ru->rect.bottom = ncsParam->rgrc[0].bottom-rcClient.bottom; CopyRect(&ncsParam->rgrc[0], &rcClient); CloseThemeData(hTheme); ReleaseDC(GetParent(hwnd), hdc); return WVR_REDRAW; } ReleaseDC(GetParent(hwnd), hdc); CloseThemeData(hTheme); } } return ret; } case WM_ENABLE: RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_NOCHILDREN|RDW_UPDATENOW|RDW_FRAME); break; case WM_DESTROY: { LRESULT ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); EnterCriticalSection(&csRich); slist = rlist_remove(slist, ru); LeaveCriticalSection(&csRich); if (ru) free(ru); return ret; } } return mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); }
/** * name: PaintThemeButton * desc: Draws the themed button * param: ctl - BTNCTRL structure for the button * hdcMem - device context to draw to * rcClient - rectangle of the whole button * return: nothing **/ static void __fastcall PaintThemeButton(BTNCTRL *ctl, HDC hdcMem, LPRECT rcClient) { RECT rcText = { 0, 0, 0, 0 }; WCHAR wszText[MAX_PATH] = { 0 }; WORD ccText; // Draw the flat button if ((ctl->dwStyle & MBS_FLAT) && ctl->hThemeToolbar) { int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->defbutton ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED; if (IsThemeBackgroundPartiallyTransparent(ctl->hThemeToolbar, TP_BUTTON, TBStateConvert2Flat(state))) { if (SUCCEEDED(DrawThemeParentBackground(ctl->hwnd, hdcMem, rcClient))) DrawThemeParentBackground(GetParent(ctl->hwnd), hdcMem, rcClient); } DrawThemeBackground(ctl->hThemeToolbar, hdcMem, TP_BUTTON, TBStateConvert2Flat(state), rcClient, rcClient); } else { // draw themed button background if (ctl->hThemeButton) { int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->defbutton ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED; if (IsThemeBackgroundPartiallyTransparent(ctl->hThemeButton, BP_PUSHBUTTON, state)) { if (SUCCEEDED(DrawThemeParentBackground(ctl->hwnd, hdcMem, rcClient))) DrawThemeParentBackground(GetParent(ctl->hwnd), hdcMem, rcClient); } DrawThemeBackground(ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, state, rcClient, rcClient); } } // calculate text rect { RECT sizeText; HFONT hOldFont; ccText = GetWindowTextW(ctl->hwnd, wszText, _countof(wszText)); if (ccText > 0) { hOldFont = (HFONT)SelectObject(hdcMem, ctl->hFont); GetThemeTextExtent( ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, IsWindowEnabled(ctl->hwnd) ? ctl->stateId : PBS_DISABLED, wszText, ccText, DST_PREFIXTEXT, NULL, &sizeText); if (ctl->cHot) { RECT rcHot; GetThemeTextExtent(ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, IsWindowEnabled(ctl->hwnd) ? ctl->stateId : PBS_DISABLED, L"&", 1, DST_PREFIXTEXT, NULL, &rcHot); sizeText.right -= (rcHot.right - rcHot.left); } SelectObject(hdcMem, hOldFont); rcText.left = (ctl->hIcon) ? 0 : (rcClient->right - rcClient->left - (sizeText.right - sizeText.left)) / 2; rcText.top = (rcClient->bottom - rcClient->top - (sizeText.bottom - sizeText.top)) / 2; rcText.right = rcText.left + (sizeText.right - sizeText.left); rcText.bottom = rcText.top + (sizeText.bottom - sizeText.top); if (ctl->stateId == PBS_PRESSED) { OffsetRect(&rcText, 1, 1); } } } PaintIcon(ctl, hdcMem, &ccText, rcClient, &rcText); // draw text if (ccText > 0 && ctl->hThemeButton) { HFONT hOldFont = (HFONT)SelectObject(hdcMem, ctl->hFont); DrawThemeText(ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, IsWindowEnabled(ctl->hwnd) ? ctl->stateId : PBS_DISABLED, wszText, ccText, DST_PREFIXTEXT, 0, &rcText); SelectObject(hdcMem, hOldFont); } }
static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { TRichUtil *ru = NULL, tru; int idx; LRESULT ret; tru.hwnd = hwnd; { mir_cslock lck(csRich); if (List_GetIndex(&sListInt, &tru, &idx)) ru = (TRichUtil *)sListInt.items[idx]; } switch (msg) { case WM_THEMECHANGED: case WM_STYLECHANGED: RichUtil_ClearUglyBorder(ru); break; case WM_NCPAINT: ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); if (ru->hasUglyBorder && IsThemeActive()) { HANDLE hTheme = OpenThemeData(ru->hwnd, L"EDIT"); if (hTheme) { RECT rcBorder; RECT rcClient; int nState; HDC hdc = GetWindowDC(ru->hwnd); GetWindowRect(hwnd, &rcBorder); rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top; rcBorder.left = rcBorder.top = 0; CopyRect(&rcClient, &rcBorder); rcClient.left += ru->rect.left; rcClient.top += ru->rect.top; rcClient.right -= ru->rect.right; rcClient.bottom -= ru->rect.bottom; ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); if (IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) DrawThemeParentBackground(hwnd, hdc, &rcBorder); if (!IsWindowEnabled(hwnd)) nState = ETS_DISABLED; else if (SendMessage(hwnd, EM_GETOPTIONS, 0, 0) & ECO_READONLY) nState = ETS_READONLY; else nState = ETS_NORMAL; DrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL); CloseThemeData(hTheme); ReleaseDC(hwnd, hdc); return 0; } } return ret; case WM_NCCALCSIZE: { ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS *)lParam; if (ru->hasUglyBorder && IsThemeActive()) { HANDLE hTheme = OpenThemeData(hwnd, L"EDIT"); if (hTheme) { RECT rcClient = {0}; HDC hdc = GetDC(GetParent(hwnd)); if (GetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK) { ru->rect.left = rcClient.left - ncsParam->rgrc[0].left; ru->rect.top = rcClient.top - ncsParam->rgrc[0].top; ru->rect.right = ncsParam->rgrc[0].right - rcClient.right; ru->rect.bottom = ncsParam->rgrc[0].bottom - rcClient.bottom; ncsParam->rgrc[0] = rcClient; CloseThemeData(hTheme); ReleaseDC(GetParent(hwnd), hdc); return WVR_REDRAW; } ReleaseDC(GetParent(hwnd), hdc); CloseThemeData(hTheme); } } } return ret; case WM_ENABLE: RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME); break; case WM_GETDLGCODE: return mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam) & ~DLGC_HASSETSEL; case WM_NCDESTROY: ret = mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); { mir_cslock lck(csRich); List_Remove(&sListInt, idx); } mir_free(ru); return ret; } return mir_callNextSubclass(hwnd, RichUtil_Proc, msg, wParam, lParam); }