?
Solved

CBuilder 5 messages and custom components

Posted on 2000-05-06
9
Medium Priority
?
417 Views
Last Modified: 2008-02-20
Hi i need to access the CM_MOUSEENTER and CM_MOUSELEAVE messages in this cusomised button.

The idea is to change the glyph of the button as you move your mouse ovvr the button.

This is some of the basic code so far but it doesn't work. It is suppose to change the caption of the button it self.

Can anybody help ?
===========================================
.h file:
===========================================
//---------------------------------------------------------------------------

#ifndef UltBitBtnH
#define UltBitBtnH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TUltBitBtn : public TBitBtn
{
private:
   Graphics::TBitmap* FOffGlyph;
   Graphics::TBitmap* FOnGlyph;
      MESSAGE void __fastcall CMMouseEnter(Messages::TWMMouse &Message);
      MESSAGE void __fastcall CMMouseLeave(Messages::TWMMouse &Message);
   BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(CM_MOUSEENTER, TWMMouse, CMMouseEnter)
      MESSAGE_HANDLER(CM_MOUSELEAVE, TWMMouse, CMMouseLeave)
   END_MESSAGE_MAP(TControl)

protected:
public:
   __fastcall TUltBitBtn(TComponent* Owner);
   __fastcall ~TUltBitBtn();
__published:
};
//---------------------------------------------------------------------------
#endif

===========================================
.cpp file:
===========================================
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UltBitBtn.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TUltBitBtn *)
{
   new TUltBitBtn(NULL);
}
//---------------------------------------------------------------------------
__fastcall TUltBitBtn::TUltBitBtn(TComponent* Owner)
   : TBitBtn(Owner)
{
   FOffGlyph = new Graphics::TBitmap();
   FOnGlyph = new Graphics::TBitmap();
}

//---------------------------------------------------------------------------
__fastcall TUltBitBtn::~TUltBitBtn()
{
   delete FOffGlyph;
   delete FOnGlyph;
}

//---------------------------------------------------------------------------
namespace Ultbitbtn
{
   void __fastcall PACKAGE Register()
   {
      TComponentClass classes[1] = {__classid(TUltBitBtn)};
      RegisterComponents("Own", classes, 0);
   }
}
//---------------------------------------------------------------------------
// Message handlers
MESSAGE void __fastcall TUltBitBtn::CMMouseEnter(Messages::TWMMouse &Message)
{
   Caption = "Enter";
   Invalidate();
}

MESSAGE void __fastcall TUltBitBtn::CMMouseLeave(Messages::TWMMouse &Message)
{
   Caption = "Leave";
   Invalidate();
}

//---------------------------------------------------------------------------
0
Comment
Question by:Alien_SM
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 3
9 Comments
 
LVL 14

Accepted Solution

by:
AlexVirochovsky earned 800 total points
ID: 2784336
>>access the CM_MOUSEENTER and CM_MOUSELEAVE messages in this cusomised button.


This can be done via a subclass procedure
        or by creating a descendant of the target control and
        augmenting the WndProc() method (or via a message map).
(code for Label, you can easy change it to Button):
 // in header...
     Controls::TWndMethod OldLabelWP;
     void __fastcall NewLabelWP(TMessage &Msg);

 // in source...
 __fastcall TForm1::TForm1(TComponent *Owner)
     : TForm(Owner)
 {
     OldLabelWP = Label1->WindowProc;
     Label1->WindowProc = NewLabelWP;
 }

 void __fastcall TForm1::NewLabelWP(TMessage &Msg)
 {
     switch (Msg.Msg)
     {
         case CM_MOUSEENTER:
         {
            // mouse cursor has entered control
            //you code
            break;
         }
         case CM_MOUSELEAVE:
         {
            // mouse cursor has left control
            //you code
            break;
         }
         case WM_DESTROY:
         {
            Label1->WindowProc = OldLabelWP;
            break;
         }
     }
     OldLabelWP(Msg);
 }

....
I hope, it helps. Alex
0
 

Author Comment

by:Alien_SM
ID: 2786408
I can't get this to work with a inheritance from TBitBtn do u know why??

I tried what you suggested an ovverided wndproc and also the method you posted but nothing.

I then went and inherited from a TSpeedButton and that worked fine.

Why can't i use TBitBtn ?? I thought maybee only Components that inherits from TGraphicControl can fire CM_MOUSELEAVE and CM_MOUSEENTER.

any idea cause i need this to work with TBitBtn ??
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2788744
It is very strange, next code i get from
some project (not mine!):

//in header...
Controls::TWndMethod OldBitBtnWP;
void __fastcall NewBitBtnWP(TMessage &Msg);

//in source...
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//subclass the BitBtn
OldBitBtnWP = BitBtn1->WindowProc;
BitBtn1->WindowProc = NewBitBtnWP;
}

void __fastcall TForm1::NewBitBtnWP(TMessage &Msg)
{
if (Msg.Msg == CM_MOUSELEAVE)
BitBtn1->Glyph = Image1->Picture->Bitmap;
if (Msg.Msg == CM_MOUSEENTER)
BitBtn1->Glyph = Image2->Picture->Bitmap;

OldBitBtnWP(Msg);
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
//restore the BitBtn's original window procedure
BitBtn1->WindowProc = OldBitBtnWP;
}
It is very close to my code!
If it is not helps, reject my reply.
Alex
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 3

Expert Comment

by:shenqw
ID: 2789049
hi Alien_SM
  The TBitBtn has no CM_MOUSEENTER,CM_MOUSELEAVE messages, why TSpeedButton has the two messages,you can see the source code of Delphi's code of TSpeedButton and you will know why.

procedure TSpeedButton.UpdateTracking;
var
  P: TPoint;
begin
  if FFlat then
  begin
    if Enabled then
    begin
      GetCursorPos(P);
      FMouseInControl := not (FindDragTarget(P, True) = Self);
      if FMouseInControl then
        Perform(CM_MOUSELEAVE, 0, 0)
      else
        Perform(CM_MOUSEENTER, 0, 0);
    end;
  end;
end;


Good Luck!
shenqw
0
 
LVL 3

Expert Comment

by:shenqw
ID: 2789210
Sorry, I'am wrong! :(

In D5,I had test your code ,it works fine. I'll try in BCB later. Sorry!
0
 

Author Comment

by:Alien_SM
ID: 2789628
The tihing is Alec i tried the last code you posted exactly like you showed me and for some reson it didn't work.

here is the code
===================================
header
===================================
class PACKAGE TUltBitBtn : public TSpeedButton
{
private:
   Graphics::TBitmap* FOffGlyph;
   Graphics::TBitmap* FOnGlyph;

   Controls::TWndMethod OldWinProc;
   void __fastcall NewWinProc(TMessage &Msg);
protected:
public:
   __fastcall TUltBitBtn(TComponent* Owner);
   __fastcall ~TUltBitBtn();
__published:
};

===================================
cpp file
===================================
static inline void ValidCtrCheck(TUltBitBtn *)
{
   new TUltBitBtn(NULL);
}
//---------------------------------------------------------------------------
__fastcall TUltBitBtn::TUltBitBtn(TComponent* Owner)
   : TSpeedButton(Owner)
{
   FOffGlyph = new Graphics::TBitmap();
   FOnGlyph = new Graphics::TBitmap();
   OldWinProc = WindowProc;
   WindowProc = NewWinProc;

}

//---------------------------------------------------------------------------
__fastcall TUltBitBtn::~TUltBitBtn()
{
   delete FOffGlyph;
   delete FOnGlyph;
   WindowProc = OldWinProc;
}

//---------------------------------------------------------------------------
namespace Ultbitbtn
{
   void __fastcall PACKAGE Register()
   {
      TComponentClass classes[1] = {__classid(TUltBitBtn)};
      RegisterComponents("Own", classes, 0);
   }
}
//---------------------------------------------------------------------------
// Message handlers
void __fastcall TUltBitBtn::NewWinProc(TMessage &Msg)
{
   switch (Msg.Msg)
   {
      case CM_MOUSEENTER:
      {
         // mouse cursor has entered control
         MessageDlg("Enter", mtInformation , TMsgDlgButtons() << mbYes , 0);
         break;
      }
      case CM_MOUSELEAVE:
      {
         // mouse cursor has left control
         MessageDlg("Leave", mtInformation , TMsgDlgButtons() << mbYes , 0);
         break;
      }
      case WM_DESTROY:
      {
         WindowProc = OldWinProc;
         break;
      }
   }
   OldWinProc(Msg);
}


===================================
===================================
now like i said this code works fine with Tspeedbutton and i can see why also . But why can't it work with Tbitbtn
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2789987
Sorry, i have'n idea, why it is not work.
0
 
LVL 3

Expert Comment

by:shenqw
ID: 2790754
hi Alien_SM
  I had tried in BCB5, Your code also works fine. but there maybe a bug.when i add my component into the package dclusr50.bpk,It doesn't work(I mean that when i run the app,it raise a exception before the mainform be shown).
So i put it in my own package,It works.

Oh,My god,BCB5.  :(
0
 

Author Comment

by:Alien_SM
ID: 2790935
Tnks for the help Alex

As I said I got the stuph to work with a speedbutton as an ansestor ill try again l8r with a bitbtn.
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question