Link to home
Start Free TrialLog in
Avatar of sprinken
sprinken

asked on

PopupPanel component

I want to create a Delphi component, a panel behaving like a popup menu, better said a popup menu which can contain any kind and number of controls;
How can I trap the mouse messages or other system commands in order to hide my component when receiving them?

Or do you know any Delphi component like this?
Avatar of Mike Littlewood
Mike Littlewood
Flag of United Kingdom of Great Britain and Northern Ireland image

You would have to create your own message handler and assign it to the application.

Application.OnMessage := AppMessages

procedure TForm1.AppMessages(var Msg: TMsg; var Handled: Boolean);
begin
  // check which messages are to be processed
  case msg.message of
    // just handle mouse events.
    WM_MOUSEFIRST..WM_MOUSELAST: begin

      // DO SOMETHING

    end;
  end;
end;
Avatar of sprinken
sprinken

ASKER

Ok. But I want to create a component, not to create this message handler for every program. If the AppMessages procedure is a private procedure of my component, how can I get the handle of the application in the constructor method in order to assign to its OnMessage property my message handler?

I created the component, but it works only inside my application. It does nothing when I click outside my application.

Here's the code of my application:

//--------------------------------------------------------------------
unit nrPanel1;

interface

uses forms,windows,messages,
  SysUtils, Classes, Controls, ExtCtrls;

type
  TnrPanel1 = class(TPanel)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    procedure AppMessage(var Msg: tagMSG; var Handled: Boolean);
    destructor Destroy; override;
  published
    { Published declarations }
  end;

procedure Register;

implementation
procedure tnrpanel1.AppMessage(var Msg: tagMSG; var Handled: Boolean);
begin
    if Msg.Message=WM_LBUTTONDOWN then Hide;
end;

constructor TnrPanel1.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  application.OnMessage:=AppMessage;
end;

destructor Tnrpanel1.Destroy;
begin
  application.OnMessage:=nil;
  inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('Samples', [TnrPanel1]);
end;

end.

What should I do?
Avatar of Eddie Shipman
You have to have OnMouseMove handler and use the mouse pos to determine if the cursor
is, indeed, inside your control's ClientRect.
But the procedure assigned to OnMouseMove is called only when the mouse is moved over my component, and I want it to be called when the mouse move outside the application too. Beside this, what if I know the mouse pos if my component doesn't receive a message when the user clicks the desktop, for ex.
Then use a TTimer and the CursorPos function to get the current cursorpos and check with
PtInRect to see if it's in your ClientRect.

I have done this before on a TShape, let me see if I can find the code.
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is what I needed Slick, but I have one more question. Is there any way to create the components on MenuForm at designtime? If no, do you know how I can implement the OnEnter/OnExit events to a panel. In my application i will use more MenuForms and I think it's easier to create the components at design time.

Thanks,
Sprinken
???
Not so sure about how to do that and make it as a design time component? I am rather busy now with some projects and others, as I said, , I was hoping you would get ideas to help you implement your menu thing,  Maybe in a few days I can find time to mess with it
Ok. Thanks for help
It does not seem that you can have any sort of TForm or TFrame as any kind of "Component" that you can add to the VCL component palette and use at design time.
I took some time to try and add the OnEnter and OnExit events to a TCustomControl (parent of TPanel), I added them, , but they DO NOT have the same functionality that is needed for this kind of thing. . .
Then I will create every FormMenu in my application as a component descendant of TFormMenu. Thanks again Slick. I appreciate your help
I just remembered something you might try , ,
I recall that you can reassign a TControl to a new Parent,, So you might have several regular TPanels on your form, and design them in your Design time, but have them all a NOT visible, as you would normally do, , then In your form's OnCreate event or a button click, you would create a single TFormMenu, and then assign the FormMenu1 as the parent of all of the TPanels

MenuForm1 := TMenuForm.Create(Application);
Panel1.Parent := MenuForm1;
Panel2.Parent := MenuForm1;

// then to show your MenuForm1 -

Panel1.Hide; // Only needed if this was set to visible in a MenuForm1 Show before
MenuForm1.ClientHeight := Panel2.Height;
MenuForm1.ClientWidth := Panel2.Width;
Panel2.Show; // show the panel you need to see
MenuForm1.Left := Left + 100;
MenuForm1.Top := Top + 100;
MenuForm1.Visible := True;

= = = = =
I do not have time to try this now, but I think it may work
OH
you may also need to re-position

Panel1.Parent := MenuForm1;
Panel1.Top := 0;
Panel1.Left := 0;
This is an alternative I was thinking to, but now I will implement it. Thanks Slick.