Article

From:
To:
Mario
Subject:
Re: ActionClient image dissapears when associated Action->Enabled= false
Newsgroup:
borland.public.cppbuilder.vcl.components.using

Re: ActionClient image dissapears when associated Action->Enabled= false

Hi Mario,
   Unfortunately, TActionToolBar doesn't use the Win32 toolbar control 
as its backend, so many of the features (including custom disabled 
images)  that we're used to using with TToolBars aren't available for 
TActionToolBar.  The TCustomActionControl::DrawGlyph() method is 
actually responsible for drawing the toolbutton's glyph, and 
unfortunately it uses the very primitive DrawState() Win32 function to 
draw a disabled version of the glyph, which is why it looks so bad.

However, the good news is that the action-bar framework--though definitely rough around the edges--is flexible enough for customization.   To use custom disabled images, you need to do two things:
(1) You need to create a TCustomButtonControl descendant class in which you override the DrawGlyph() method to draw your own disabled glyphs. (TCustomButtonControl is a TCustomActionControl descendant.)
(2) You need to provide handlers for the TActionToolBar's OnGetControlClass and OnControlCreated events, in which you inform the TActionToolBar to create instances of your TCustomButtonControl descendant class (from Step 1) instead of the default TCustomButtonControl class.
Here's an example. For the first step, I've called the descendant class   TMyButtonControl, which provides a DisabledImages property that you can use to specify an extra image-list which contains the disabled glyphs...
class TMyButtonControl : public TCustomButtonControl { public:    __property TImageList* DisabledImages =      {read=DisabledImages_, write=DisabledImages_};
public:    __fastcall TMyButtonControl(TComponent* Owner) :      TCustomButtonControl(Owner) {}
protected:    virtual void __fastcall DrawGlyph(TPoint const& Location)      {        // if the action is enabled or there's no        // disabled image list specified...        if (Enabled || DisabledImages == NULL)        {          // have parent class do its default drawing          TCustomButtonControl::DrawGlyph(Location);        }        else // otherwise, draw custom disabled glyph...        {          TPoint GlyphPos(Location);          if (Down || IsChecked())          {            ++GlyphPos.x;            ++GlyphPos.x;          }
         // disabled small icon should be drawn          if (SmallIcon)          {            HIMAGELIST const hImageList =              reinterpret_cast<HIMAGELIST>                (DisabledImages->Handle);            ImageList_DrawEx(              hImageList, ActionClient->ImageIndex,              Canvas->Handle, GlyphPos.x, GlyphPos.y,              0, 0, clNone, clNone, ILD_TRANSPARENT              );          }          else // disabled large icon should be drawn          {            // TODO: draw a large icon (e.g., from another            // image list, or stretch-to-fit 32x32 by using            // an intermediate bitmap)          }        }      }
   virtual void __fastcall DrawText(TRect& ARect,      unsigned int& Flags, AnsiString Text)      {        Canvas->Brush->Style = bsClear;        if (Down || IsChecked())        {          OffsetRect(&ARect, 1, 1);        }        if (Enabled)        {          ::DrawText(Canvas->Handle, Text.c_str(),            Text.Length(), &ARect, Flags);        }        else // disabled text        {          if (!Selected)          {            OffsetRect(&ARect, 1, 1);            Canvas->Font->Color = (Color == clBtnFace) ?              clBtnHighlight : GetHighLightColor(Color);            ::DrawText(Canvas->Handle, Text.c_str(),              Text.Length(), &ARect, Flags);            OffsetRect(&ARect, -1, -1);          }          Canvas->Font->Color = (Color == clBtnFace) ?            clBtnShadow : GetShadowColor(Color);          ::DrawText(Canvas->Handle, Text.c_str(),            Text.Length(), &ARect, Flags);        }      }
private:    TImageList* DisabledImages_; };
Note that the DrawGlyph() method implemented here assumes that the indices (into the image-lists) for the normal and disabled glyphs are identical. Also notice that I had to provide an implementation of the DrawText() method due to a BCB bug (I was getting unresolved external errors).
For the second step, you use the action toolbar's OnGetControlClass event to tell the toolbar to use the descendant class...
void __fastcall TForm1::ActionToolBar1GetControlClass(    TCustomActionBar *Sender, TActionClient *AnItem,    TCustomActionControlClass &ControlClass) {    ControlClass = __classid(TMyButtonControl); }
And then use the OnControlCreated event to perform any initial modifications to each TMyButtonControl instance (here, to specify ImageList2 as the DisabledImages property)...
void __fastcall TForm1::ActionToolBar1ControlCreated(    TObject *Sender, TCustomActionControl *&Control) {    if (dynamic_cast<TMyButtonControl*>(Control) != NULL)    {      TMyButtonControl* MyButtonControl =        static_cast<TMyButtonControl*>(Control);      MyButtonControl->DisabledImages = ImageList2;    } }
Good luck, -- Damon (TeamB)
C++Builder Developer's Journal   http://bcbjournal.com BCB Commonly Asked Questions   http://bcbjournal.com/bcbcaq

Mario wrote:
> ActionBar displays images of ActionClients if associated Action is Enabled,
> but when Action becomes disabled, the image dissapears which isn't what I 
> need. I need different image (greyed) to appear instead.
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Thu, 28 Mar 2024 09:10:38 UTC
Copyright © 2009-2024
HREF Tools Corp.