CButton派生类中先调用基类DrawItem再自定义绘制的问题
问题原因及解决方法
问题根源:CButton类的
DrawItem成员函数,当按钮带有BS_OWNERDRAW样式时,基类实现本身不会执行标准绘制逻辑——因为OWNERDRAW模式下,系统默认将绘制控制权完全交给子类。你在DrawItem内部临时修改样式的操作,无法改变基类DrawItem的执行逻辑(函数调用时的状态已确定),而且ModifyStyle还可能触发窗口消息干扰当前绘制流程。正确实现方式:直接调用系统API绘制标准按钮外观,再叠加自定义内容,无需修改按钮样式。示例代码如下:
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // 1. 绘制标准按钮外观 UINT uStyle = DFCS_BUTTONPUSH; if ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0) uStyle |= DFCS_PUSHED; if ((lpDrawItemStruct->itemState & ODS_DISABLED) != 0) uStyle |= DFCS_INACTIVE; // 绘制按钮边框和背景 ::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle); // 绘制按钮文本(保留标准文本逻辑) CString strText; GetWindowText(strText); if (!strText.IsEmpty()) { UINT uFormat = DT_CENTER | DT_VCENTER | DT_SINGLELINE; if ((lpDrawItemStruct->itemState & ODS_DISABLED) != 0) uFormat |= DT_GRAYTEXT; // 调整文本区域,避开按钮边框 RECT rcText = lpDrawItemStruct->rcItem; ::InflateRect(&rcText, -4, -4); ::DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(), &rcText, uFormat); } // 2. 绘制自定义内容,示例:按钮右上角添加红色小标记 RECT rcCustom = { lpDrawItemStruct->rcItem.right - 10, lpDrawItemStruct->rcItem.top + 5, lpDrawItemStruct->rcItem.right - 5, lpDrawItemStruct->rcItem.top + 10 }; ::FillRect(lpDrawItemStruct->hDC, &rcCustom, (HBRUSH)::GetStockObject(RED_BRUSH)); }
- 补充说明:如果想最大化复用CButton的内部逻辑,也可以通过获取按钮状态后,调用系统消息让原生控件完成绘制,但上述
DrawFrameControl的方式更直接可控,且避免了样式修改带来的潜在问题。
内容的提问来源于stack exchange,提问作者Tom Tom
相关产品推荐
相关产品推荐

