user2200585
user2200585

Reputation: 283

Highlight TPanel on mouse move

I'm trying to make app to show some information, It'll create Panels runtime and place info on it, each panel will be flat as on picture, also app will use runtime themes, so i'd not be able to change panel bg color on mouse move, I tried to place info on TSpeedButton :v O.o it has wonderfull highlight function when it's flat while app is using runtime theme, but the main problem is that images and labels aren't moving when i move speedbutton and i need this much, they just stay there..

I tried to edit TCustomPanel.Paint to see if panel will look like highlighted button, adding code at the end:

PaintRect := ClientRect;
Details := StyleServices.GetElementDetails(ttbButtonHot);
StyleServices.DrawElement(Canvas.Handle, Details, PaintRect);

but with no success..

also it's pretty hard to link some custom code OnClick event at runtime, e.g:

ShowMessage('custom message on each panel');

I have not got any idea on how to do this, hope some one will give me advice or show me some example..

btw, panel will be created this way:

var
  P: TPanel;
begin
 P := TPanel.Create(Self);
 P.Left := 20;
 P.Top := 100;
 P.Width := 60;
 P.Height := 20;
 P.Visible := True;
 P.Parent := Self;
 @P.OnClick := @Showmessageproc; // somehow this way..
end;

App pic:

pic

If i do so:

procedure TMyPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  mEvnt: TTrackMouseEvent;
begin
  inherited;
  if not FMouseTracking then begin
    mEvnt.cbSize := SizeOf(mEvnt);
    mEvnt.dwFlags := TME_LEAVE;
    mEvnt.hwndTrack := Handle;
    TrackMouseEvent(mEvnt);
    FMouseTracking := True;
    showmessage('IN');
  end;
end;

procedure TMyPanel.WMMouseLeave(var Msg: TMessage);
begin
 if Msg.Msg = WM_MOUSELEAVE then showmessage('OUT');
  Msg.Result := 0;
  FMouseTracking := False;
  if Assigned(FOnMouseLeave) then
    FOnMouseLeave(Self);
end;

procedure G(Sender: TObject);
begin
showmessage('message');
end;

procedure TMainFrm.Button1Click(Sender: TObject);
var
  P: TMyPanel;
begin
 P := TMyPanel.Create(Self);
 P.Left := 20;
 I := I + 100;
 P.Top := I;
 P.Width := 200;
 P.Height := 80;
 P.Visible := True;
 P.Parent := Self;
 @P.OnClick := @g;
end;

when I move mouse on runtime created panel, 2 msgbox appears, IN and OUT, "mousemove" works fine but "mouse leave" bad, also the mainc question is still actual. the problem is that that I can't get canvas of created panel to draw on. the example above could be achieved more simple way:

 @P.OnMouseLeave := @onmouseleaveproc;
 @P.OnMouseMove  := @onmousemoveproc;

but with Canvas, everything is more difficult, somewhere i've read that canvas is protected in TCustomPanel.

Also there's another question: Is it possible to handle panel wich called e.g OnMouseMove ? because there maybe will be 30 of them (runtime created panels)

I've tried this way: (and it does not works)

type
  TMyPanel = class(TPanel)
  public
   constructor Create(AOwner: TComponent); override;
  private
  //  FMouseTracking: Boolean;
  //  FOnMouseLeave: TNotifyEvent;
    procedure CMMouseEnter(var msg: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;
  protected
  //  procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  published
  //  property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  end;

    constructor TMyPanel.Create(AOwner: TComponent);
    begin
      ControlStyle := ControlStyle - [csParentBackground] + [csOpaque];
      inherited;
    end;


    procedure TMyPanel.CMMouseEnter(var msg: TMessage);
    begin
      inherited;
      Color := clBlue;
      { Do Whatever }
    end;

    procedure TMyPanel.CMMouseLeave(var msg: TMessage);
    begin
      inherited;
      Color := clRed;
      { Do Whatever }
    end;

Simply, color does not changes. (color changes with themes OFF)

Upvotes: 0

Views: 3805

Answers (2)

lurker
lurker

Reputation: 58284

I created the following new component in Delphi and installed it. A new TColorPanel component showed up in a new MyComponents tab in the IDE. I then used this to put a TColorPanel on a new app and it responded properly to the mouse enter/leave events, changing the color as desired. I'm not sure how you made your app's panels as TMyPanel instead of standard TPanel. This is just how I tried it. I used your latest message handling code as-is.

unit ColorPanel;

interface

uses
  WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TColorPanel = class(TPanel)
  public
   constructor Create(AOwner: TComponent); override;
  private
    procedure CMMouseEnter(var msg: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;
  protected
  //  procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  published
  //  property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('MyComponents', [TColorPanel]);
end;

constructor TColorPanel.Create(AOwner: TComponent);
begin
  ControlStyle := ControlStyle - [csParentBackground] + [csOpaque];
  inherited;
end;

procedure TColorPanel.CMMouseEnter(var msg: TMessage);
begin
  inherited;
  Color := clBlue;
  { Do Whatever }
end;

procedure TColorPanel.CMMouseLeave(var msg: TMessage);
begin
  inherited;
  Color := clRed;
  { Do Whatever }
end;

end.

I'm not sure why yours isn't working, other than to determine how you declared your app's panels to be TMyPanel.

Upvotes: 0

lurker
lurker

Reputation: 58284

It's basically explained here for Delphi 6, but same concept I think. You want to define a custom windows message handler for your panel. This will give you basic mouse enter/exit capability. You can then play with setting TPanel properties from there to find something to your liking. For example, to mock a speed button, you might be able to just set the background color and change the border bevel accordingly. If that isn't adequate, you can write to the TPanel's Canvas directly (paint the behavior that you want to see) on mouse enter/exit to get the visual behavior you're after.

Upvotes: 1

Related Questions