如何显示一个像弹出菜单一样的窗口?

时间:2010-02-01 17:00:16

标签: delphi winapi popup

当显示窗口A时,我想显示另一个非模态弹出窗口B,但是:

  1. 由于窗口B成为前窗,我不希望窗口A变为非活动状态;
  2. 我希望当窗口B聚焦时,我只需点击一下就可以在窗口A上拉下一个组合框控件(通常你需要点击两次,一个用于将焦点移动到窗口A,第二个用于拉下组合框);
  3. 正如你所看到的,我想要的窗口B就像一个更有用的弹出窗口,就像一个弹出式菜单(当你希望它通过点击任何一个窗口时,它不像一般的非模态窗口那么障碍父窗口的其他部分)。

    我清楚我的问题了吗? 谢谢。

6 个答案:

答案 0 :(得分:8)

我发现“1”的最简单的解决方案是,一旦弹出窗体被激活(在WM_ACTIVATE处理程序中),就会向调用表单发送一个WM_NCACTIVATE,这样调用表单就会用活动的形式绘制其标题颜色。你必须在弹出窗体中有一个调用表单的引用才能实现这个目的。

对于“2”,您可以在同一个WM_ACTIVATE处理程序中释放弹出窗体,这不会占用调用表单的点击次数。

所以......像这样应该转到弹出窗体;

type
  TForm2 = class(TForm)
    [..]
  private
    FOwner: TForm;
    procedure WmActivate(var Msg: TWMActivate); message WM_ACTIVATE;
  public
    constructor Create(AOwner: TComponent); override;

[...]
constructor TForm2.Create(AOwner: TComponent);
begin
  if not (AOwner is TForm) then
    raise Exception.Create('Owner should be TForm');
  FOwner := TForm(AOwner);
  inherited;
end;

procedure TForm2.WmActivate(var Msg: TWMActivate);
begin
  SendMessage(FOwner.Handle, WM_NCACTIVATE, Ord(Msg.Active <> WA_INACTIVE), 0);
  inherited;
  if Msg.Active = WA_INACTIVE then
    Release;
end;

并提供调用表单作为弹出窗体的所有者;

procedure TForm1.Button1Click(Sender: TObject);
var
  PopForm: TForm2;
begin
  PopForm := TForm2.Create(Self);
  [..]

<小时/> FWIW,我同意loursonwinnyUlrich。 IMO弹出窗体似乎比较复杂。虽然在SpTBXFormPopupMenu的情况下,您必须安装两个库,TB2KSpTBXLib。至少浏览消息来源可能暗示可能涉及的内容。

答案 1 :(得分:2)

为了防止窗口获得焦点,您必须指定WS_EX_NOACTIVATE扩展窗口样式(Windows 2000及更高版本)或句柄WM_MOUSEACTIVATE并返回MA_NOACTIVATE

答案 2 :(得分:0)

我可以用它来不失焦点:

SetWindowPos(Form2.Handle, HWND_TOP, 0, 0, 0, 0,
  SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);

第二部分我不太了解。

答案 3 :(得分:0)

来自spTBXLib的SpTBXFormPopupMenu完成了这项工作。

转到http://www.silverpointdevelopment.com/sptbxlib/index.htm并查找“表单弹出窗口”

关键似乎是容器'popuped'必须继承TPopupMenu。但是处理非常复杂,您可以在代码中自己看到它。我的建议是按原样使用它,因为Robert Lee做得很好。

答案 4 :(得分:0)

我自己在这里找到了解决方案。谢谢大家!:

Keep Window Inactive In Appearance Even When Activated

答案 5 :(得分:-1)

我发现了一个几乎完全符合我想要的东西:TAdvStickyPopupMenu