Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Componente que se oculte al hacer click fuera de él. (https://www.clubdelphi.com/foros/showthread.php?t=88286)

pacopenin 14-05-2015 16:30:42

Componente que se oculte al hacer click fuera de él.
 
Buenas tardes.

Llevo buscando desde hace algún tiempo un componente o código, que permita que un TPanel (o similar) se oculte al hacer click fuera de él. Cuando digo fuera me refiero a que puedo hacer click en cualquier parte de la aplicación, así que no se sobre que componente lo haré. No he encontrado nada que me resulte efectivo 100%.

Espero vuestros consejos y gracias de antemano.

Casimiro Notevi 14-05-2015 17:36:13

Pero eso te corresponde a ti decidirlo, puedes crear un procedimiento al que asignes como evento onlick a todos los componentes, incluido el formulario, menos al panel.

pacopenin 14-05-2015 17:54:16

Gracias por la idea Casimiro, pero necesito una solución global. No se lo que puede haber fuera del panel. Ese panel puede aparecer en cualquier momento y necesito que se oculte al hacer click en cualquier punto de la pantalla fuera de él. Debería funcionar como un popup menú.

Casimiro Notevi 14-05-2015 17:58:11

Ah, vale, entonces ese panel lo abres sobre otro transparente que ocupe por completo la pantalla, así, pulses donde pulses, estarás haciéndolo sobre ese otro panel transparente.

Neftali [Germán.Estévez] 14-05-2015 18:09:37

Sólo se me ocurre que utilices un Edit (por ejemplo) dentro del panel y aproveches el evento OnExit del Edit para ocultar el panel.
Das pocos detalles más, de la aplicación, de lo que habrá en el TPanel, de cuando y cómo lo vas a visualizar,... así que no se si esto cuadra con lo que necesitas...

Este ejemplo ilustra lo que quiero decir

Es la solución que se me ocurre para que no tengas que tocar nada el resto de componentes del form ni de la aplicación.
Lo único es que al visualizar el panel, debes pasar el foco al Edit.
Revisa el código del ejemplo.

pacopenin 14-05-2015 18:55:53

Gracias a los dos por las ideas aportadas.
La verdad es que en Lazarus hay unos componentes llamados Luicontrols (LuiPack) que tienen uno llamado dropdownmanager que hace exactamente eso con cualquier elemento visual y funciona muy bien. Desgraciadamente mis conocimientos no dan para adaptarlo a Delphi, a pesar de ser poco código. https://code.google.com/p/luipack/so...ownmanager.pas
Imagino que tiene que haber forma de interceptar de algún modo el evento click a nivel global y saber si está (por coordenadas) dentro o fuera del panel.
A ver si me explico. La aplicación genera unos mensajes (alertas) que aparecen en pantalla dentro de un panel. Dicho panel tiene un botón de cerrar, pero me han pedido que funcione como el previsualizador de imagenes de las webs, que al dar click fuera de ellas se cierran.
El concepto es bastante sencillo, pero no acierto a dar con algo que funcione como deseo.
Probaré lo que comentais.

ecfisa 14-05-2015 19:02:54

Hola pacopenin.

Otra opción es :

Formulario en que se encuentra el Panel,
Código Delphi [-]
unit Unit2;

interface

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

type
  TPanel = class(ExtCtrls.TPanel)
  private
    FInPanel: Boolean;
    procedure MouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
    procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
  public
    property InPanel: Boolean read FInPanel write FInPanel;
  end;

  TForm2 = class(TForm)
    Panel1: TPanel;
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
  public
  end;

var
  Form2: TForm2;

implementation {$R *.dfm}

procedure TPanel.MouseEnter(var Msg: TMessage);
begin
  FInPanel := True;
end;

procedure TPanel.MouseLeave(var Msg: TMessage);
begin
  FInPanel := False;
end;

procedure TForm2.MouseLeave(var Msg: TMessage);
begin
  Panel1.InPanel := False;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  Form2 := nil;
end;

end.

Formulario principal,
Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    procedure MouseEvent(var Msg: tagMsg; var Handled: Boolean);
  public
  end;

var
  Form1: TForm1;

implementation  {$R *.dfm}

uses ExtCtrls, Unit2, Unit3;

procedure TForm1.MouseEvent(var Msg: tagMsg; var Handled: Boolean);
begin
  if (Msg.message = WM_LBUTTONDOWN) then
    if Assigned(Form2) then
      Form2.Panel1.Visible := Form2.Panel1.InPanel;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := MouseEvent;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form3.Show; {otro formulario para la prueba }
  if not Assigned(Form2) then
    Form2:= TForm2.Create(Self);
  Form2.Show;
end;

end.
Me apego a lo que solicitas en tu mensaje "hacer click en cualquier parte de la aplicación". En el ejemplo, el panel será visible nuevamente cuando se destruya y cree el formulario que lo contiene.

Saludos :)

ecfisa 14-05-2015 19:37:44

Hola de nuevo.

Solo para decirte que el procedimiento,
Código Delphi [-]
procedure TForm2.MouseLeave(var Msg: TMessage);
si bién no afecta, no es necesario. Me quedó de una prueba anterior :o, lo podes quitar.

Saludos :)

pacopenin 14-05-2015 19:41:52

Hola ecfisa. Creo que lo que aportas puede servirme.
La aplicación es un form principal y las distintas opciones (clientes, articulos, facturas, etc) se abren en distintos tabs, por lo que los mensajes se generan en ese formulario y el panel en cuestión está también es él. Dentro de cada tab está "incrustado" el form correspondiente a clientes, artículos, facturas ...etc. por eso es imposible saber donde se hace click ya que depende del tab en el que estemos.



ecfisa 14-05-2015 19:58:39

Hola pacopepin.
Cita:

Empezado por pacopenin (Mensaje 492169)
Hola ecfisa. Creo que lo que aportas puede servirme.
La aplicación es un form principal y las distintas opciones (clientes, articulos, facturas, etc) se abren en distintos tabs, por lo que los mensajes se generan en ese formulario y el panel en cuestión está también es él. Dentro de cada tab está "incrustado" el form correspondiente a clientes, artículos, facturas ...etc. por eso es imposible saber donde se hace click ya que depende del tab en el que estemos.

Si, eso fué mas o menos lo que entendí. Por eso el código del ejemplo oculta el panel cuando se hace click sobre cualquier componente de la aplicación, exceptuando los realizados sobre la barra de título de los forms.

Anque no está en el ejemplo, podes hacer visible el panel desde cualquier form que incluya a form2, ej.:
Código Delphi [-]
procedure TForm1.btnShowPanelClick(Sender: TObject);
begin
  if Assigned(Form2) then
    Form2.Panel1.Visible := True;
end;

Saludos :)

Edito: Creo que en versiones posteriores a Delphi 7 ya están publicados los eventos OnMouseEnter y OnMouseLeave.

pacopenin 14-05-2015 20:19:50

Aparentemente funciona bien con la solución sugerida por ecfisa. Gracias a todos, :)^\||/

ecfisa 14-05-2015 21:11:47

Hola pacopepin.

Afinando un poco el lápiz podría quedar así:
Código Delphi [-]
unit uPanelHide;

interface

uses Messages, Classes, Controls, ExtCtrls;
type
  TPanel = class(ExtCtrls.TPanel)
  private
    FInPanel: Boolean;
    procedure MouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
    procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
  public
    property InPanel: Boolean read FInPanel;
  end;

implementation

procedure TPanel.MouseEnter(var Msg: TMessage);
begin
  FInPanel := True;
end;

procedure TPanel.MouseLeave(var Msg: TMessage);
begin
  FInPanel := False;
end;

end.

Form donde se quiere usar:
Código Delphi [-]
unit Unit2;

interface

uses
  Windows, Messages, ..., ExtCtrls, uPanelHide;

type
  TForm2 = class(TForm)
    Panel1: TPanel;
...

form principal:
Código Delphi [-]
...
procedure TForm1.MouseEvent(var Msg: tagMsg; var Handled: Boolean);
begin
  if ( Msg.message = WM_LBUTTONDOWN ) or ( Msg.message = WM_RBUTTONDOWN ) then
  begin
    if Assigned(Form2) then
      with Form2.Panel1 do Visible := InPanel;
    //...
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := MouseEvent;
end;

Saludos :)

elrayo76 15-05-2015 16:19:19

Lo que dice ecfisa puede servirle al amigo. Igualmente aclaro que lo que quiere hacer es algo asi como los popups que cuando se presiona en cualquier parte de la aplicación con el mouse se oculta, si es que esta visible.

Lo que pide no es algo aro de hacer, tendre que buscar el mi cajon de cosas pasadas y ver si encuentro algo que he realizado hace un tiempo para algo similar.

Saludos,
El Rayo


La franja horaria es GMT +2. Ahora son las 10:20:46.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi