1

使用此处提供的示例如何为 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 事件不会在任何停靠的表单上获取,从而导致关闭按钮停止工作。

4

1 回答 1

1

问题是,您正在设置DockSite页面控件的属性(尽管问题中没有提到)。设置 DockSite 时,当鼠标左键按下时会创建一个拖动对象,然后鼠标被该对象捕获(这样做是为了能够自动拖出表单)。因此,正是这个对象处理鼠标消息,直到释放捕获,这WM_LBUTTONUPTDragObject.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;
于 2011-12-02T22:21:17.607 回答