简体   繁体   中英

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.

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 . 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. 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.

So make the WM_DRAWITEM message handler look like this (in the parent window's window procedure):

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. 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.

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.

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".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM