Отрисованные владельцем события TPageControl OnMouse не запускаются при закреплении формы как вкладки - PullRequest
1 голос
/ 03 декабря 2011

Используя приведенный здесь пример Как реализовать кнопку закрытия для TTabsheet из TPageControl в сочетании с установкой родительского элемента формы для листа вкладки с соответствующим заголовком Я смог взять свой контроль страницы с формами, прикрепленными какTTabSheet и добавьте кнопку закрытия и изображение из списка изображений, как вы видите в современных веб-браузерах.

Когда я изменяю

procedure TMainfrm.SOTest(Sender: TObject);
var
  ATab: TTabSheet;
  AForm: TMyForm;
begin
  { Tabbed }
  ATab:= TTabSheet.Create(MainPageControl);
  ATab.PageControl := MainPageControl;
  MainPageControl.ActivePage := ATab;
  AForm:= TMyForm.Create(ATab);
  AForm.Show;
  ATab.Caption := AForm.Caption;
end;

на

procedure TMainfrm.SOTest(Sender: TObject);
var
  AForm: TMyForm;
begin
  AForm:= TMyForm.Create(Application);
  AForm.Show;
  AForm.DragKind := dkDock;
  AForm.DragMode := dmAutomatic;
  AForm.ManualDock(MainPageControl,MainPageControl,alClient);
  AForm.Caption := 'StackOverFlow';
end;

События OnMouse не обрабатываются никакими закрепленными формами, поэтому кнопка закрытия перестает работать.

1 Ответ

1 голос
/ 03 декабря 2011

Проблема в том, что вы устанавливаете свойство DockSite элемента управления страницы (хотя оно не упоминается в вопросе). Когда установлен DockSite, при перетаскивании левой кнопки мыши создается объект перетаскивания, а затем этот объект захватывает мышь (это делается для того, чтобы можно было автоматически перетаскивать форму). Таким образом, именно этот объект обрабатывает сообщения мыши до тех пор, пока захват не будет освобожден, что делается в случае WM_LBUTTONUP в TDragObject.WndProc.

Переопределение WndProc, получение нового класса, размещение обработчика сообщений и т. Д. Не будут работать, поскольку элемент управления страницей не доставляет никаких сообщений мыши, пока мышь захватывается объектом перетаскивания. Даже использование Application.OnMessage в лучшем случае будет неуклюжим, поскольку Msg.hwnd будет указывать на другое окно при каждом щелчке мыши.

То, что вы можете сделать, например, так или иначе подклассить элемент управления страницы, чтобы иметь возможность перехватывать WM_LBUTTONDOWN, выполнить там тест и освободить захват, если щелчок находится на кнопке вкладки. Очень грязный быстрый пример, основанный на связанном вопросе:

type
  TPageControl = class(comctrls.TPageControl)
  private
    procedure WmLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN;
  end;

  TMainfrm = class(TForm)
  ..

procedure TPageControl.WmLButtonDown(var Msg: TWMLButtonDown);
var
  I: Integer;
begin
  inherited;                     // mouse will be captured here
  for I := 0 to Length(Mainfrm.FCloseButtonsRect) - 1 do
  begin
    if PtInRect(Mainfrm.FCloseButtonsRect[I], SmallPointToPoint(Msg.Pos)) then
    begin
      ReleaseCapture;            // and released here 
      Break;
    end;
  end;
end;
...