Board index » cppbuilder » Cool Bar help

Cool Bar help

We are using C++ Builder 5.0 and have been unable to create a floating
button panel using the Cool Bar component. Is there anyone on the list who
can create a simple one form project which has a Cool Bar with a button on
it? If anyone could zip up a project like that and email it to us we would
be very thankfull.

Thank You
Patrick Mikula
patr...@marketwarrior.com
Austin Financial Group

 

Re:Cool Bar help


Hi Patrick --

Quote
> We are using C++ Builder 5.0 and have been unable to create a
> floating button panel using the Cool Bar component.

You've got two things working against you here:  (1) the VCL drag/dock
mechnism isn't well-suited for buttons, and (2) the TCoolBar component
class is a weak wrapper around the rebar common control.  So, to make
this work, you'll need to subclass the CoolBar instance (e.g.,
CoolBar1), manually handle the RBN_BEGINDRAG and RBN_ENDDRAG rebar
notification messages, manually rendern a tracking rectangle, and then
use the TControl::ManualFloat() member function.

The RBN_BEGINDRAG notification message is sent when the user drag a
CoolBand (i.e., via the gripper).  In response to this message, you need
to determine which CoolBand is being dragged, and then set a
'is_dragging' flag so that in your CoolBar's OnMouseMove event handler,
you can render a tracking rectangle.  Likewise, in response to the
RBN_ENDDRAG notification message, which is sent when the user finishes
dragging a CoolBand, you need to remove the tracking rectangle, then
clear the 'is_dragging' flag, and then call the ManualFloat() member
function if the cursor is outside of the CoolBar itself.  Again, to get
at these messages, you'll need to subclass the CoolBar (or derive a new
class and augment the WndProc() or Dispatch() member function).

So, first set the DragKind property of all banded controls (i.e., all
your buttons) to dkDock.  Then, work through the following example...

// in header...
private:          
   HDC hScreenDC_;       // handle to the screen's DC
   bool is_dragging_;    // 'is dragging' flag
   bool first_rect_;     // 'first draw' flag
   POINT PDrag_;         // the cursor position at drag start
   RECT RDragBand_;      // the rectangle of the dragged band
   TCoolBand* DragBand_; // a pointer to the dragged band

   // original window procedure
   Controls::TWndMethod OldCoolBarWP;
   // subclass procedure
   void __fastcall NewCoolBarWP(TMessage& AMsg);

// in source...
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner),
   hScreenDC_(NULL),
   is_dragging_(false),
   first_rect_(false),
   DragBand_(NULL)
{
   // subclass CoolBar1
   OldCoolBarWP = CoolBar1->WindowProc;
   CoolBar1->WindowProc = NewCoolBarWP;

Quote
}

void __fastcall TForm1::NewCoolBarWP(TMessage& AMsg)
{
   switch (AMsg.Msg)
   {
      // for all notification messages...
      case CN_NOTIFY:
      {
         LPNMREBAR lpnmr = reinterpret_cast<LPNMREBAR>(AMsg.LParam);
         // in response to RBN_BEGINDRAG...
         if (lpnmr->hdr.code == RBN_BEGINDRAG &&
             lpnmr->dwMask & RBNM_ID)
         {
            // grab a pointer to the TCoolBand that's being dragged
            DragBand_ = reinterpret_cast<TCoolBand*>(lpnmr->wID);
            // get its bounding rectangle
            SNDMSG(CoolBar1->Handle, RB_GETRECT, DragBand_->Index,
                   reinterpret_cast<LPARAM>(&RDragBand_));
            // map the rectangle to screen coordinates
            MapWindowPoints(
               CoolBar1->Handle, HWND_DESKTOP,
               reinterpret_cast<LPPOINT>(&RDragBand_), 2
               );

            // store the position of the mouse cursor
            const DWORD dwMouse = GetMessagePos();
            PDrag_ = Point(LOWORD(dwMouse), HIWORD(dwMouse));

            // set the flags
            is_dragging_ = true;
            first_rect_ = true;
         }
         // in response to RBN_ENDDRAG...        
         else if (lpnmr->hdr.code == RBN_ENDDRAG)
         {
            if (hScreenDC_)
            {
               // clean up
               DrawFocusRect(hScreenDC_, &RDragBand_);
               ReleaseDC(NULL, hScreenDC_);
               hScreenDC_ = NULL;
               is_dragging_ = false;

               // restore screen updates
               SNDMSG(CoolBar1->Handle, WM_SETREDRAW, true, 0);

               // un-dock the control
               CoolBar1->Controls[DragBand_->Index]->
                  ManualFloat(RDragBand_);
            }
         }
         break;
      }
      case WM_DESTROY:
      {
         CoolBar1->WindowProc = OldCoolBarWP;
         // if only recreating...
         if (!CoolBar1->ComponentState.Contains(csDestroying))
         {
            // reinstate the instance subclass
            OldCoolBarWP(AMsg);
            OldCoolBarWP = CoolBar1->WindowProc;
            CoolBar1->WindowProc = NewCoolBarWP;
            return;
         }
      }
   }
   OldCoolBarWP(AMsg);

Quote
}

void __fastcall TForm1::CoolBar1MouseMove(TObject *Sender,
   TShiftState Shift, int X, int Y)
{
   if (is_dragging_)
   {
      POINT PMouse = {X, Y};
      RECT RCoolBar = CoolBar1->ClientRect;
      if (!PtInRect(&RCoolBar, PMouse))
      {
         PMouse = CoolBar1->ClientToScreen(PMouse);
         const int dX = PMouse.x - PDrag_.x;
         const int dY = PMouse.y - PDrag_.y;

         // suspend screen updates
         SNDMSG(CoolBar1->Handle, WM_SETREDRAW, false, 0);

         // grab a handle to the screen DC
         hScreenDC_ = GetDC(NULL);
         if (!first_rect_)
         {
            // erase the tracking rectangle
            DrawFocusRect(hScreenDC_, &RDragBand_);
         }
         OffsetRect(&RDragBand_, dX, dY);
         // render the tracking rectangle
         DrawFocusRect(hScreenDC_, &RDragBand_);
         first_rect_ = false;

         // update the stored cursor position
         memcpy(&PDrag_, &PMouse, sizeof(POINT));
      }
      else
      {
         if (hScreenDC_)
         {
            // clean up
            DrawFocusRect(hScreenDC_, &RDragBand_);
            ReleaseDC(NULL, hScreenDC_);
            hScreenDC_ = NULL;
            first_rect_ = true;
            is_dragging_ = false;                                    

            // restore screen updates, then update            
            SNDMSG(CoolBar1->Handle, WM_SETREDRAW, true, 0);
            CoolBar1->Invalidate();
         }
      }
   }  

Quote
}

Good luck!

--
Damon Chandler (TeamB - C++Builder)
- http://homepages.go.com/~damonchandler/vcl_faq.zip
- http://bcbcaq.freeservers.com

Re:Cool Bar help


Try de ControlBar component (TControlBar). Hope it will suit your needs.

Greetings,
Julio

Other Threads