【发布时间】:2011-07-16 16:52:23
【问题描述】:
我如何获得一个三态复选框来为不确定状态使用不同的位图?
我想将我的三态复选框使用的图像更改为使用不同的图像;这些控件是 Win98 风格的,并且此类复选框的不确定状态很难与禁用的复选框区分开来(这可能是他们为 WinXP 风格的控件更改此设置的原因,但由于我的项目中的其他细节,我不能使用这些) .
我使用的是 Visual C++ 2010,并且我在 VS 的资源编辑器中定义了一个 8x8 位图。位图的 ID 是IDB_INDET_CHECK。
我不完全确定这样的标准“技术”是什么;我才真正开始着手操作 Windows 控件和 MFC。
我的第一次尝试是创建一个派生自CButton 的类CTriButton,覆盖DrawItem 函数,并尝试自己绘制它。然后我使用SubclassDlgItem 将我窗口中的一个复选框变成了这个类(我想?)。这……有点作品?该复选框不再出现,如果我单击它应该在的位置,则会出现一个空的复选框框架,但没有其他任何反应(并且我的代码中的调试消息没有被发送)。
这里是相关代码,虽然我不确定任何是否正确。首先,来自我窗口的OnInitDialog 的代码。
BOOL CAffixFilterDlg::OnInitDialog() // CAffixFilterDlg is my CDialog-derived window
{
CDialog::OnInitDialog(); // call basic version
// subclass a CButton-derived control with CTriButton
if ( CBipedHead.SubclassDlgItem(IDC_HEAD, this) ) // CBipedHead is a CTriButton member of CAffixFilterDlg, IDC_HEAD is a checkbox
SetWindowLong(CBipedHead.m_hWnd, GWL_STYLE, CBipedHead.GetStyle() | BS_OWNERDRAW); // set the ownerdraw style
else // subclassing didn't work
_ERROR("Subclassing failed."); // I do not see this error message, so SubclassDlgItem worked?
// initialization continues, but is not relevant...
UpdateWindow();
Invalidate();
return TRUE;
}
接下来,我的自定义按钮 DrawItem 的代码。
void CTriButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
_DMESSAGE("Drawing TriButton"); // never see this message
CDC dc;
dc.Attach(lpDrawItemStruct->hDC); //Get device context object
int nWidth = GetSystemMetrics(SM_CXMENUCHECK);
int nMargin = ( nWidth - 8 ) / 2;
CRect textRt = lpDrawItemStruct->rcItem;
textRt.right = textRt.right - nWidth - nMargin;
CString text;
GetWindowText(text);
UINT textDrawState = DST_TEXT;
if ( lpDrawItemStruct->itemState & ODS_DISABLED )
textDrawState |= DSS_DISABLED;
dc.DrawState(CPoint(textRt.left, textRt.top), textRt.Size(), text, textDrawState, TRUE, 0, (CBrush*)NULL);
CRect rt = lpDrawItemStruct->rcItem; // initial rect is for entire button
rt.left = rt.right - nWidth; // set left margin
LONG center = ( rt.bottom + rt.top ) / 2;
rt.top = center - nWidth/2;
rt.bottom = center + nWidth/2;
UINT checkDrawState = DFCS_BUTTONCHECK;
if ( lpDrawItemStruct->itemState & ODS_DISABLED )
checkDrawState |= DFCS_INACTIVE;
if ( lpDrawItemStruct->itemState & ODS_CHECKED )
checkDrawState |= DFCS_CHECKED;
else if ( GetCheck() == BST_INDETERMINATE ) {
_VMESSAGE("Indeterminate; custom draw.");
CBitmap indet_check = CBitmap();
indet_check.LoadBitmap(IDB_INDET_CHECK);
CPoint pt = CPoint(rt.left + nMargin, rt.top + nMargin);
CSize sz = CSize(8, 8);
dc.DrawState(pt, sz, &indet_check, DST_BITMAP|DSS_NORMAL);
}
dc.DrawFrameControl(rt, DFC_BUTTON, checkDrawState);
}
【问题讨论】:
-
你在哪里启用了所有者绘制窗口样式?
-
你有什么问题?您在哪里将复选框设置为三样式或将按钮的状态设置为中间?
-
@paludarium:谢谢,这对一些人有帮助;我不知道这样做。我已经更新了我的代码,现在设置了 ownerdraw 样式;现在东西似乎根本没有被绘制,直到我点击它应该在的位置,然后我只得到一个空的复选框框。我的绘图代码似乎没有被调用(从未看到调试消息)。我的问题已经更新了。感谢您提到设置样式!
-
@Ajay:复选框是在 Visual Studio 的资源编辑器中设置的,包括它的三样式和默认状态。无论如何,感谢您的评论;我已经尝试重写我的问题以更清楚!
标签: c++ visual-studio-2010 checkbox mfc ownerdrawn