[英]How to change looks of a disabled button and edit control?
已启用
残障人士
当我禁用按钮(使用BS_BITMAP样式标志创建)时,它会改变外观(请参见上图),编辑控件也会发生同样的情况。
禁用后如何使控件不变?
我可以通过对控件进行子类化来实现,但是有没有更简单的方法?
如果可能的话,我不想仅仅为此子类化控件。
您无需为此子类化控件即可,尽管我会说它会更干净。 设置BS_OWNERDRAW
样式并处理WM_DRAWITEM
消息的替代方法。 这意味着您要接管所有图形,但这没关系,因为您始终不希望它看起来像普通按钮。
我完全同意Jonathan Potter的观点 ,即无法向用户指示哪些按钮已启用,哪些按钮未启用,这是非常糟糕的UI设计。 有多种方法可以做到这一点,但不这样做是不可行的选择。 幸运的是,使用WM_DRAWITEM
很容易,因为它告诉您按钮的当前状态。
因此,使WM_DRAWITEM
消息处理程序看起来像这样(在父窗口的窗口过程中):
case WM_DRAWITEM:
{
const DRAWITEMSTRUCT* pDIS = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
// See if this is the button we want to paint.
// You can either check the control ID, like I've done here,
// or check against the window handle (pDIS->hwndItem).
if (pDIS->CtlID == 1)
{
// Load the bitmap.
const HBITMAP hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
// Draw the bitmap to the button.
bool isEnabled = (pDIS->itemState & ODS_DISABLED) == 0;
DrawState(pDIS->hDC,
nullptr,
nullptr,
reinterpret_cast<LPARAM>(hBmp),
0, 0, 0, 0, 0,
DST_BITMAP | (isEnabled ? DSS_NORMAL : DSS_DISABLED));
// Delete the bitmap.
DeleteObject(hBmp);
// Draw the focus rectangle, if applicable.
if ((pDIS->itemState & ODS_FOCUS) && ((pDIS->itemState & ODS_NOFOCUSRECT) == 0))
{
DrawFocusRect(pDIS->hDC, &pDIS->rcItem);
}
// Indicate that we handled this message.
return TRUE;
}
break;
}
当然,您可以通过一次加载位图并将其缓存在全局对象中来进一步优化此代码,而不是每次按钮需要绘制时都加载并销毁它。
请注意,我使用了DrawState
函数 ,该函数可以以“正常”( DSS_NORMAL
)或“禁用”( DSS_DISABLED
)状态绘制位图。 这大大简化了代码,并使我们能够轻松地处理禁用状态,但不幸的是,结果看起来有点难看。 这是因为DrawState
函数会在应用除正常效果之外的任何效果之前将位图转换为单色。
您可能不喜欢这种效果,因此您需要做其他事情。 例如,使用两个单独的图像,一个用于启用状态,另一个用于禁用状态,然后绘制适当的图像。 或将正常的彩色图像转换为灰度 ,然后将其绘制为禁用状态。
而且,如果自定义绘图代码运行得太慢,则可以通过检查pDIS->itemAction
的值并仅重新绘制必要的部分来进一步优化它。
然后,一旦您认为所有功能都经过完善和高效,不可避免的错误报告将开始出现。例如,不支持键盘加速器。 然后,一旦添加了对这些功能的支持,就需要在用户界面中进行说明。 对于已经包含文本的位图,这将是困难的; 带下划线的字母的唯一方法是自己绘制文本。 这一切都证明所有者抽取是太多的工作。 只是让Windows以正常方式绘制控件,不要仅仅因为某些设计师认为它“看起来很酷”就为您的用户破坏了一切。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.