298 lines
8.3 KiB
C++
298 lines
8.3 KiB
C++
#include "stdafx.h"
|
|
#include "CListControl.h"
|
|
#include "CListControlHeaderImpl.h"
|
|
#include "CListControl-Cells.h"
|
|
#include "PaintUtils.h"
|
|
#include "GDIUtils.h"
|
|
#include <vsstyle.h>
|
|
|
|
LONG CListCell::AccRole() {
|
|
return ROLE_SYSTEM_LISTITEM;
|
|
}
|
|
|
|
void RenderCheckbox( HTHEME theme, CDCHandle dc, CRect rcCheckBox, unsigned stateFlags, bool bRadio ) {
|
|
|
|
const int part = bRadio ? BP_RADIOBUTTON : BP_CHECKBOX;
|
|
|
|
const bool bDisabled = (stateFlags & CListCell::cellState_disabled) != 0;
|
|
const bool bPressed = (stateFlags & CListCell::cellState_pressed ) != 0;
|
|
const bool bHot = ( stateFlags & CListCell::cellState_hot ) != 0;
|
|
|
|
if (theme != NULL && IsThemePartDefined(theme, part, 0)) {
|
|
int state = 0;
|
|
if (bDisabled) {
|
|
state = bPressed ? CBS_CHECKEDDISABLED : CBS_DISABLED;
|
|
} else if ( bHot ) {
|
|
state = bPressed ? CBS_CHECKEDHOT : CBS_HOT;
|
|
} else {
|
|
state = bPressed ? CBS_CHECKEDNORMAL : CBS_NORMAL;
|
|
}
|
|
|
|
CSize size;
|
|
if (SUCCEEDED(GetThemePartSize(theme, dc, part, state, rcCheckBox, TS_TRUE, &size))) {
|
|
if (size.cx <= rcCheckBox.Width() && size.cy <= rcCheckBox.Height()) {
|
|
CRect rc = rcCheckBox;
|
|
rc.left += ( rc.Width() - size.cx ) / 2;
|
|
rc.top += ( rc.Height() - size.cy ) / 2;
|
|
rc.right = rc.left + size.cx;
|
|
rc.bottom = rc.top + size.cy;
|
|
DrawThemeBackground(theme, dc, part, state, rc, &rc);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
int stateEx = bRadio ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK;
|
|
if ( bPressed ) stateEx |= DFCS_CHECKED;
|
|
if ( bDisabled ) stateEx |= DFCS_INACTIVE;
|
|
else if ( bHot ) stateEx |= DFCS_HOT;
|
|
DrawFrameControl(dc, rcCheckBox, DFC_BUTTON, stateEx);
|
|
}
|
|
|
|
void RenderButton( HTHEME theme, CDCHandle dc, CRect rcButton, CRect rcUpdate, uint32_t cellState ) {
|
|
|
|
const int part = BP_PUSHBUTTON;
|
|
|
|
enum {
|
|
stNormal = PBS_NORMAL,
|
|
stHot = PBS_HOT,
|
|
stDisabled = PBS_DISABLED,
|
|
stPressed = PBS_PRESSED,
|
|
};
|
|
|
|
int state = 0;
|
|
if (cellState & CListCell::cellState_disabled) state = stDisabled;
|
|
if ( cellState & CListCell::cellState_pressed ) state = stPressed;
|
|
else if ( cellState & CListCell::cellState_hot ) state = stHot;
|
|
else state = stNormal;
|
|
|
|
CRect rcClient = rcButton;
|
|
|
|
if (theme != NULL && IsThemePartDefined(theme, part, 0)) {
|
|
DrawThemeBackground(theme, dc, part, state, rcClient, &rcUpdate);
|
|
} else {
|
|
int stateEx = DFCS_BUTTONPUSH;
|
|
switch (state) {
|
|
case stPressed: stateEx |= DFCS_PUSHED; break;
|
|
case stDisabled: stateEx |= DFCS_INACTIVE; break;
|
|
}
|
|
DrawFrameControl(dc, rcClient, DFC_BUTTON, stateEx);
|
|
}
|
|
}
|
|
|
|
bool CListCell::ApplyTextStyle( LOGFONT & font, double scale, uint32_t ) {
|
|
if ( scale != 1.0 ) {
|
|
font.lfHeight = pfc::rint32( font.lfHeight * scale );
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CListCell_Text::DrawContent( DrawContentArg_t const & arg ) {
|
|
const auto fgWas = arg.dc.GetTextColor();
|
|
CDCHandle dc = arg.dc;
|
|
if (arg.cellState & cellState_disabled) {
|
|
dc.SetTextColor(GetSysColor(COLOR_GRAYTEXT));
|
|
}
|
|
|
|
|
|
CRect clip = arg.rcText;
|
|
|
|
const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat);
|
|
dc.DrawText( arg.text, (int)wcslen(arg.text), clip, format | DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER );
|
|
|
|
dc.SetTextColor(fgWas);
|
|
}
|
|
|
|
void CListCell_TextColors::DrawContent( DrawContentArg_t const & arg ) {
|
|
CDCHandle dc = arg.dc;
|
|
|
|
CRect clip = arg.rcText;
|
|
|
|
const uint32_t fgWas = dc.GetTextColor();
|
|
|
|
const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat);
|
|
const t_uint32 bk = dc.GetBkColor();
|
|
const t_uint32 fg = fgWas;
|
|
const t_uint32 hl = (arg.allowColors ? arg.colorHighlight : fg);
|
|
const t_uint32 colors[3] = { PaintUtils::BlendColor(bk, fg, 33), fg, hl };
|
|
|
|
PaintUtils::TextOutColorsEx(dc, arg.text, clip, format, colors);
|
|
|
|
dc.SetTextColor(fgWas);
|
|
}
|
|
|
|
void CListCell_MultiText::DrawContent( DrawContentArg_t const & arg ) {
|
|
CDCHandle dc = arg.dc;
|
|
|
|
const int textLen = (int) wcslen( arg.text );
|
|
|
|
CRect clip = arg.rcText;
|
|
|
|
const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat) | DT_NOPREFIX | DT_VCENTER ;
|
|
|
|
CRect rcDraw = clip;
|
|
dc.DrawText(arg.text, textLen, rcDraw, format | DT_CALCRECT);
|
|
auto txSize = rcDraw.Size();
|
|
rcDraw = clip;
|
|
if ( txSize.cy < rcDraw.Height() ) {
|
|
int sub = rcDraw.Height() - txSize.cy;
|
|
rcDraw.top += sub/2;
|
|
rcDraw.bottom = rcDraw.top + txSize.cy;
|
|
}
|
|
dc.DrawText(arg.text, textLen, rcDraw, format);
|
|
}
|
|
|
|
bool CListCell_Hyperlink::ApplyTextStyle( LOGFONT & font, double scale, uint32_t state ) {
|
|
bool rv = __super::ApplyTextStyle(font, scale, state);
|
|
|
|
if ( state & cellState_hot ) {
|
|
font.lfUnderline = TRUE;
|
|
rv = true;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
HCURSOR CListCell_Hyperlink::HotCursor() {
|
|
return LoadCursor(NULL, IDC_HAND);
|
|
}
|
|
|
|
LONG CListCell_Hyperlink::AccRole() {
|
|
return ROLE_SYSTEM_LINK;
|
|
}
|
|
|
|
void CListCell_Hyperlink::DrawContent( DrawContentArg_t const & arg ) {
|
|
|
|
CDCHandle dc = arg.dc;
|
|
|
|
const uint32_t fgWas = dc.GetTextColor();
|
|
|
|
const t_uint32 format = PaintUtils::DrawText_TranslateHeaderAlignment(arg.hdrFormat);
|
|
if (arg.allowColors) dc.SetTextColor( arg.colorHighlight );
|
|
const t_uint32 bk = dc.GetBkColor();
|
|
|
|
CRect rc = arg.rcText;
|
|
dc.DrawText(arg.text, (int) wcslen(arg.text), rc, format | DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER );
|
|
|
|
dc.SetTextColor(fgWas);
|
|
}
|
|
|
|
LONG CListCell_Button::AccRole() {
|
|
return ROLE_SYSTEM_PUSHBUTTON;
|
|
}
|
|
|
|
void CListCell_Button::DrawContent( DrawContentArg_t const & arg ) {
|
|
|
|
CDCHandle dc = arg.dc;
|
|
|
|
const bool bPressed = (arg.cellState & cellState_pressed) != 0;
|
|
const bool bHot = (arg.cellState & cellState_hot) != 0;
|
|
|
|
|
|
if ( !m_lite || bHot || bPressed ) {
|
|
RenderButton( arg.theme, dc, arg.rcHot, arg.rcHot, arg.cellState );
|
|
}
|
|
|
|
CRect clip = arg.rcText;
|
|
|
|
dc.DrawText(arg.text, (int) wcslen(arg.text), clip, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_CENTER);
|
|
}
|
|
|
|
bool CListCell_ButtonGlyph::ApplyTextStyle( LOGFONT & font, double scale, uint32_t state ) {
|
|
return __super::ApplyTextStyle(font, scale * 1.3, state);
|
|
}
|
|
|
|
static CRect CheckBoxRect(CRect rc) {
|
|
if (rc.Width() > rc.Height()) {
|
|
rc.right = rc.left + rc.Height();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
LONG CListCell_Checkbox::AccRole() {
|
|
return m_radio ? ROLE_SYSTEM_RADIOBUTTON : ROLE_SYSTEM_CHECKBUTTON;
|
|
}
|
|
|
|
CRect CListCell_Checkbox::HotRect( CRect rc ) {
|
|
return CheckBoxRect( rc );
|
|
}
|
|
|
|
void CListCell_Checkbox::DrawContent( DrawContentArg_t const & arg ) {
|
|
|
|
CDCHandle dc = arg.dc;
|
|
|
|
const bool bPressed = (arg.cellState & cellState_pressed) != 0;
|
|
const bool bHot = (arg.cellState & cellState_hot) != 0;
|
|
|
|
|
|
CRect clip = arg.rcText;
|
|
|
|
const uint32_t fgWas = dc.GetTextColor();
|
|
|
|
if (arg.subItemRect.Width() > arg.subItemRect.Height() ) {
|
|
CRect rcCheckbox = arg.subItemRect;
|
|
rcCheckbox.right = rcCheckbox.left + rcCheckbox.Height();
|
|
RenderCheckbox(arg.theme, dc, rcCheckbox, arg.cellState, m_radio );
|
|
CRect rcText = arg.subItemRect;
|
|
rcText.left = rcCheckbox.right;
|
|
if (arg.cellState & cellState_disabled) {
|
|
dc.SetTextColor(GetSysColor(COLOR_GRAYTEXT));
|
|
}
|
|
dc.DrawText(arg.text, (int) wcslen(arg.text), rcText, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT);
|
|
} else {
|
|
RenderCheckbox(arg.theme, dc, arg.subItemRect, arg.cellState, m_radio );
|
|
}
|
|
|
|
dc.SetTextColor(fgWas);
|
|
}
|
|
|
|
void CListCell_Text_FixedColor::DrawContent(DrawContentArg_t const & arg) {
|
|
if (arg.allowColors) {
|
|
SetTextColorScope scope(arg.dc, m_col);
|
|
__super::DrawContent(arg);
|
|
} else {
|
|
__super::DrawContent(arg);
|
|
}
|
|
}
|
|
|
|
void CListCell_Combo::DrawContent(DrawContentArg_t const & arg) {
|
|
CDCHandle dc = arg.dc;
|
|
|
|
const bool bDisabled = (arg.cellState & CListCell::cellState_disabled) != 0;
|
|
const bool bPressed = (arg.cellState & cellState_pressed) != 0;
|
|
const bool bHot = (arg.cellState & cellState_hot) != 0;
|
|
|
|
const int part = CP_DROPDOWNBUTTONRIGHT;
|
|
|
|
const HTHEME theme = arg.theme;
|
|
|
|
if (theme != NULL && IsThemePartDefined(theme, part, 0)) {
|
|
int state = CBXSR_NORMAL;
|
|
if (bDisabled) {
|
|
state = CBXSR_DISABLED;
|
|
} else if (bPressed) {
|
|
state = CBXSR_PRESSED;
|
|
} else if (bHot) {
|
|
state = CBXSR_HOT;
|
|
}
|
|
|
|
CSize size;
|
|
CRect rcCombo = arg.subItemRect;
|
|
CRect rcText = arg.rcText;
|
|
int w = rcCombo.Height()*3/4;
|
|
if (w < rcCombo.Width()) {
|
|
rcCombo.left = rcCombo.right - w;
|
|
DrawThemeBackground(theme, dc, part, state, rcCombo, &rcCombo);
|
|
if (rcCombo.left < rcText.right ) rcText.right = rcCombo.left;
|
|
}
|
|
|
|
DrawContentArg_t arg2 = arg;
|
|
arg2.rcText = rcText;
|
|
PFC_SINGLETON(CListCell_Text).DrawContent(arg2);
|
|
}
|
|
}
|
|
|
|
LONG CListCell_Combo::AccRole() {
|
|
return ROLE_SYSTEM_DROPLIST;
|
|
} |