Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to capture clicks outside my customform?

Status
Not open for further replies.

Nordlund

Programmer
Jul 17, 2001
458
SE
Hi.
How do I capture mouseclicks outside my newly created TCustomForm? It should work like the TCombobox dropdownwindow and be closed whenever you click anywhere.

Se code below:

Code:
unit RgListUnit;

interface

uses
 StdCtrls, Dialogs, ExtCtrls, Forms, Graphics, Types,
 Windows, Classes, Messages, Controls, WinProcs;

type
  TRgScreenPanel = class(TCustomForm)
  private
    clListbox: TListbox;
  protected
  public
    constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
    destructor Destroy; override;
  end;

implementation

{ TRgScreenPanel }

constructor TRgScreenPanel.CreateNew(AOwner: TComponent; Dummy: Integer);
begin
  inherited CreateNew(AOwner, Dummy);
  BorderStyle := bsNone;

  clListbox := TListbox.Create(self);
  clListbox.Align := alClient;
  clListbox.Parent := self;

  clListbox.Items.Text := 'One'+#13#10+'Two'+#13#10+'Three';
end;

destructor TRgScreenPanel.Destroy;
begin
  clListbox.Free;
  inherited;
end;

end.

I run show the form like this (not tested):
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
  p: TPoint;
  clScreenPanel: TRgScreenPanel;
begin
  p := ClientToScreen(Point(Button1.Left, Button1.Top+Button1.Height));
  clScreenPanel := TRgScreenPanel.CreateNew(nil);
  with clScreenPanel do
  begin
    Top := P.Y;
    Left := P.X;
    Show;
    repeat
      Application.HandleMessage;
    until not clScreenPanel.Visible;
    Free;
  end;
end;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
cant you do something like
until not clScreenPanel.focused;
or until not clScreenPanel.active;

this maynot be the correct code just a guide :)

Aaron Taylor
John Mutch Electronics
 
Hi.
No, it does'nt work.
Somewhere between the Form's "create" until the "until" the opened form is being deactivated, and therefore being closed.

But thanks for the tip, aaronjme. I will follow this up... :)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
What exactly are you trying to do?

If you are trying to close a form with any mouse click you need to track the mouse (like intercepting OnMouseDown or something) and I can't see tracking code in your forms).

The other problem is the mouse scope. You can capture the mouse, but I'm not sure it is going to work with clicks outside the mother form; probably you'll need to intercept the focus events too.

buho (A).

 
Ok. This is what i'm trying to accomplish:

I have a bunch of Drag and Drop objects added on a TScrollbox. The dragged objects are just a plain rectangle with a button drawn in it. When I click the button, a Listbox should popup above all forms, and the focus will be set on this listbox. If I click outside this listbox, the application should close the listbox and you should be able to work along normal.

To explain it simple, the popup window should work just like the dropdown portion of a combobox.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Try this code:

Code:
procedure TFMain.btnLaunchClick(Sender: TObject);
  var
    f : TFPopup;
  begin
    f := TFPopup.Create(Self);
    f.Show;
  end;

Code:
unit OCFPopup;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TFPopup = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormDeactivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FOldOnDeactivate : TNotifyEvent;  // Buffer
    //
    procedure AppOnDeactivate(Sender : TObject);
  end;

var
  FPopup: TFPopup;

implementation

{$R *.dfm}

// Added Methods - Application Event
procedure TFPopup.AppOnDeactivate(Sender : TObject);
  begin
    {This event is fired when the applicaton losses focus.
    Ie: the app is minimized or another app kicks in.}
    Close;
  end;

// Form Events
procedure TFPopup.FormCreate(Sender: TObject);
  begin
    {Save and change}
    FOldOndeactivate := Application.OnDeactivate;
    Application.OnDeactivate := AppOnDeactivate;
  end;

procedure TFPopup.FormClose(Sender: TObject; var Action: TCloseAction);
  begin
    {Set old mannager}
    Application.OnDeactivate := FOldOnDeactivate;
    {Free form}
    Action := caFree;
  end;

procedure TFPopup.FormDeactivate(Sender: TObject);
  begin
    {This event is fired if another form IN THIS APP gets the focus.
    Ie: main form is clicked.}
    Close;
  end;

procedure TFPopup.FormMouseDown(Sender: TObject;
                                Button: TMouseButton;
                                Shift: TShiftState;
                                X, Y: Integer);
  begin
    {This event is fired when THIS form is clicked.}
    Close;
  end;

end.

buho (A).
 
I have solved my problem.
I use TCustomForm.Ondeactivate and TApplication.Ondeactivate to check when my popup window is being deactivated.

Case solved, and solution posted... As always...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Detailed exaplne. (Not runnable. I have only copied the important stuff)...

The Form
Code:
type
  TFormResult = (frNone, frOK, frCancel);
  TSinglePopupForm = class(TCustomForm)
  private
    AE: TApplicationEvents;
    LB: TListBox;
    procedure OnFormDeactivate(Sender: TObject);
    procedure OnListboxClick(Sender: TObject);
    ...
  public
    constructor CreateNew(AOwner: TComponent); reintroduce;
    ...
  end;

...
...
...
constructor TSinglePopupForm.CreateNew(AOwner: TComponent);
var
  nIdx: Integer;
begin
  inherited CreateNew(AOwner);
  FFormResult := frNone;
  AE := TApplicationEvents.Create(self);
  AE.OnDeactivate := OnFormDeactivate;
  OnDeactivate := OnFormDeactivate;
  FormStyle := fsStayOnTop;
  BorderStyle := bsNone;

  LB := TListBox.Create(self);
  LB.Align := alClient;
  LB.OnClick := OnListboxClick;
  LB.Parent := self;
  LB.AutoComplete := true;
end;

procedure TSinglePopupForm.OnFormDeactivate(Sender: TObject);
begin
  FFormResult := frCancel;
end;

procedure TSinglePopupForm.OnListboxClick(Sender: TObject);
begin
  FFormResult := frOK;
end;

The request:
Code:
function SelectItem(nX, nY, nWidth: Integer; Items: TStrings; var s: String): Boolean;
var
  spf: TSinglePopupForm;
begin
  Result := False;
  spf := TSinglePopupForm.CreateNew(nil);
  try
    spf.Font.Name := 'Tahoma';
    spf.FillItems(Items, s);
    spf.Left := nX;
    spf.Top := nY;
    spf.Width := nWidth;
    spf.SetHeight;
    spf.Show;
    repeat
      Application.HandleMessage;
    until spf.FormResult in [frOK, frCancel];
  finally
    if spf.FormResult = frOK then
    begin
      Result := true;
      s := spf.GetSelectedItem;
    end;
    spf.Free;
  end;
end;


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top