Как «закрыть по внешнему клику» для TPanel (например, TCombo) в Delphi

Я хочу имитировать функцию списка TComBo, которая закрывается, когда пользователь щелкает «вне» списка, но для другого компонента (TPanel). В Делфи 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