当ModalPopupMode = pmAuto时,AppendMenu不起作用

时间:2010-12-14 13:02:00

标签: delphi forms popup modal-dialog

在Delphi中,我使用以下行(以及其他几乎相同的行)将项添加到表单的系统菜单中:

AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, cSetScreenResolution1024x768,  PChar('1024x768'));

这是所有其他表单继承的类的一部分,并且它在大多数情况下都可以正常工作,但我注意到当在模式模式下打开表单时,自定义菜单项不存在。当在无模式模式下打开相同的表单时,它可以正常工作。我花了一些时间搞清楚原因,并且我发现如果 ModalPopupMode = pmAuto 我收到此错误。当它 pmNone 时,一切正常。

任何人都能解释为什么会这样吗?也许就如何解决它提出建议?我使用ModalPopupMode = pmAuto来修复其他问题,所以它不是将其恢复为pmNone的好方法。

要重现,只需创建一个包含两个表单的小项目。在第一个表单上放下两个按钮,一个按模式打开第二个表单,一个打开它无模式。将此行放入第二个表单的create:

AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, 10000,  PChar('1024x768'));

它现在可以按预期工作。现在将应用程序ModalPopupMode设置为pmAuto,并观察模式打开表单时系统菜单上的额外menuitem已消失。

或者(也许更方便?)复制这5个“文件”:

PROJECT1.DPR

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.ModalPopupMode := pmAuto;
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

UNIT1.PAS

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(nil) do
  try
    ShowModal;
  finally
    Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  with TForm2.Create(Application.Mainform) do
  begin
    show;
  end;
end;

end.

UNIT1.DFM

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 337
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 8
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Modal'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 8
    Top = 39
    Width = 75
    Height = 25
    Caption = 'Modeless'
    TabOrder = 1
    OnClick = Button2Click
  end
end

UNIT2.PAS

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
  AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, 10000,  PChar('Test'));
end;

end.

UNIT2.DFM

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 337
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
end

1 个答案:

答案 0 :(得分:4)

构造函数不是操作窗体窗口句柄的地方。控件的句柄可能会在表单的生命周期内重新创建。

在您知道具有窗口句柄的表单后,您应该只使用窗口句柄。覆盖表单的CreateWnd方法,并将AppendMenu代码放在那里。在创建表单句柄后调用该方法,每个时间创建表单的句柄,因此您可能会看到它为同一表单多次调用。表单的某些属性可能在以模态方式创建时发生变化,这导致窗口重新创建。实际上,您的AppendMenu命令可能会通过强制表单在其准备好之前创建窗口来加剧问题。 (阅读Handle属性会强制句柄存在,如果它还没有存在的话。)