Как да „затворите при външно щракване“ за TPanel (като TCombo) в Delphi

Искам да имитирам функцията за списък на TComBo, която се затваря, когато потребителят щракне „извън“ списъка, но за друг компонент (TPanel). В Delphi XE2. Някаква идея ?


person philnext    schedule 19.09.2012    source източник
comment
възможен дубликат на Имитиране на външно кликване върху изскачащо меню   -  person Rob Kennedy    schedule 19.09.2012
comment
възможен дубликат на Как да улавям щракванията на мишката извън формуляра (като с Code Insight в Delphi)   -  person Rob Kennedy    schedule 19.09.2012


Отговори (1)


Ако приемем, че вашият панел е фокусиран (както „прочетох“ от въпроса ви), тогава отговорете на съобщението CM_CANCELMODE, което се изпраща до всички фокусирани прозорци.

type
  TPanel = class(Vcl.ExtCtrls.TPanel)
  private
    procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
  end;

  ...

{ TPanel }

procedure TPanel.CMCancelMode(var Message: TCMCancelMode);
begin
  inherited;
  if Message.Sender <> Self then
    Hide;
end;

Когато самият панел не е фокусиран, напр. детски контрол е, тогава това няма да работи. В този случай бихте могли да проследите всички щраквания на мишката (например чрез използване на манипулатор TApplicationEvents.OnMessage) и да изчислите дали щракването е било в границите на вашия панел:

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
  if Panel1.Visible and
      (Msg.message >= WM_LBUTTONDOWN) and (Msg.message <= WM_MBUTTONDBLCLK) and
      not PtInRect(Panel1.ClientRect, Panel1.ScreenToClient(Msg.pt)) then
    Panel1.Hide;
end;

Но това все още няма да успее, когато щракването е било - например - в списъка на комбинирано поле, което принадлежи на панела, но е частично разгънато извън него. Не знам как да дестилирам панела от тази информация за кликване.

person NGLN    schedule 19.09.2012
comment
Затваряне == видимо := невярно; - person philnext; 19.09.2012
comment
Това е как да откриете, че дадено меню изчезва, но това е така, защото менютата влизат в специален режим, който операционната система знае да отмени. Как панелът трябва да каже на ОС, че е в режим на меню, така че ОС да знае да изпрати съобщението по-късно? - person Rob Kennedy; 19.09.2012
comment
@RobKennedy CM_CANCELMODE се изпраща от VCL до всеки прозорец, който има фокус. Редактирах отговора си, за да изясня, че панелът трябва да бъде фокусиран по някакъв начин. В противен случай това наистина няма да работи. - person NGLN; 19.09.2012
comment
Панелът може да бъде фокусиран чрез настройка на „TabControl“, но ако след това фокусът се превключи към контрола, която е родител на панела, панелът вече не получава режим на отмяна. - person Sertac Akyuz; 20.09.2012
comment
Може би един от най-полезните отговори, които съм намирал от известно време :D - person Jerry Dodge; 05.08.2016