简体   繁体   English

如何更改禁用按钮的外观和编辑控件?

[英]How to change looks of a disabled button and edit control?

Enabled 已启用
已启用

Disabled 残障人士
残障人士

When I disable a button ( Created with BS_BITMAP style flag ) it changes its look (Please see the above images), same thing happens with edit controls. 当我禁用按钮(使用BS_BITMAP样式标志创建)时,它会改变外观(请参见上图),编辑控件也会发生同样的情况。

How do I make the controls not change when disabled ? 禁用后如何使控件不变?
I can do that by subclassing the control, but is there an easier way ? 我可以通过对控件进行子类化来实现,但是有没有更简单的方法?
I don't want to subclass the controls just for that, if possible. 如果可能的话,我不想仅仅为此子类化控件。

You do not need to subclass the control in order to do this, although I'd say it would be much cleaner. 您无需为此子类化控件即可,尽管我会说它会更干净。 The alternative to set the BS_OWNERDRAW style and handle the WM_DRAWITEM message . 设置BS_OWNERDRAW样式并处理WM_DRAWITEM消息的替代方法。 That means you're taking over all drawing, but that's okay since you don't want it to look like a normal button anyway. 这意味着您要接管所有图形,但这没关系,因为您始终不希望它看起来像普通按钮。

I could not agree more with Jonathan Potter's observation that it is extremely bad UI design to fail to indicate to the user which buttons are enabled and which ones are not. 我完全同意Jonathan Potter的观点 ,即无法向用户指示哪些按钮已启用,哪些按钮未启用,这是非常糟糕的UI设计。 There are multiple ways to do this, but not doing it is not a viable option. 有多种方法可以做到这一点,但这样做是不可行的选择。 Fortunately, it is easy to do with WM_DRAWITEM , since it tells you the button's current state. 幸运的是,使用WM_DRAWITEM很容易,因为它告诉您按钮的当前状态。

So make the WM_DRAWITEM message handler look like this (in the parent window's window procedure): 因此,使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;
}

Naturally, you could optimize this code further by loading the bitmap a single time and caching it in a global object, rather than loading and destroying it each time the button needs painting. 当然,您可以通过一次加载位图并将其缓存在全局对象中来进一步优化此代码,而不是每次按钮需要绘制时都加载并销毁它。

Note that I've used the DrawState function , which can draw bitmaps either in a "normal" ( DSS_NORMAL ) or "disabled" ( DSS_DISABLED ) state. 请注意,我使用了DrawState函数 ,该函数可以以“正常”( DSS_NORMAL )或“禁用”( DSS_DISABLED )状态绘制位图。 That simplifies the code considerably, and allows us to easily handle the disabled state, but unfortunately the result looks a little bit ugly. 这大大简化了代码,并使我们能够轻松地处理禁用状态,但不幸的是,结果看起来有点难看。 That's because the DrawState function converts the bitmap to monochrome before applying any effects other than normal. 这是因为DrawState函数会在应用除正常效果之外的任何效果之前将位图转换为单色。

You probably don't like that effect, so you'll need to do something else. 您可能不喜欢这种效果,因此您需要做其他事情。 For example, use two separate images, one for the enabled state and the other for the disabled state, and draw the appropriate one. 例如,使用两个单独的图像,一个用于启用状态,另一个用于禁用状态,然后绘制适当的图像。 Or convert your normal color image into grayscale , then draw that for the disabled state. 将正常的彩色图像转换为灰度 ,然后将其绘制为禁用状态。

And if the custom-drawing code runs too slowly, you can optimize it even further by checking the value of pDIS->itemAction and only re-drawing the necessary portions. 而且,如果自定义绘图代码运行得太慢,则可以通过检查pDIS->itemAction的值并仅重新绘制必要的部分来进一步优化它。

Then, once you think you've got everything all polished and efficient, the inevitable bug reports will start to roll in. For example, keyboard accelerators are not supported. 然后,一旦您认为所有功能都经过完善和高效,不可避免的错误报告将开始出现。例如,不支持键盘加速器。 Then, once you add support for these, you'll need to indicate that in the UI. 然后,一旦添加了对这些功能的支持,就需要在用户界面中进行说明。 That will be difficult with a bitmap that already contains the text; 对于已经包含文本的位图,这将是困难的; the only way to draw a letter underlined is to draw the text yourself. 带下划线的字母的唯一方法是自己绘制文本。 This all proves that owner-draw is way too much work. 这一切都证明所有者抽取是太多的工作。 Just let Windows draw the controls the normal way, don't break everything for your users just because some designer thinks it "looks cool". 只是让Windows以正常方式绘制控件,不要仅仅因为某些设计师认为它“看起来很酷”就为您的用户破坏了一切。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更改编辑控件的文本? - How change edit control's text? 为什么我的编辑控件在我的win32 c ++应用程序中看起来很奇怪而不使用MFC? - Why my edit control looks odd in my win32 c++ application using no MFC? 是否可以在edit内更改编辑控件的背景颜色? - Is it possible to change a background color of an edit control inside edit? 如何在禁用的MFC CEdit控件中显示插入符号? - How to show caret in a disabled MFC CEdit control? 如何在C ++ Builder中通过单个函数更改10 Edit控件的颜色 - How Can Change color of 10 Edit control by single function in c++ builder 如何在MFC的“编辑控件”中更改下一个字符的放置位置? - How to change the position where next character will be place in the Edit Control from MFC? 如何在MFC应用程序中通过编辑控制框更改窗口句柄? - how would I change a window handles via edit control box in an mfc application? 有没有办法在编辑公共控件中添加我自己的按钮? - Is there a way to add my own button inside the edit common control? 是否可以在不影响其他行的情况下更改编辑控件的字体? - Is it possible to change font for an edit control without affecting the other lines? 是否可以更改只读编辑控件的背景颜色 - Is it possible to change the background color of a read only edit control
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM