Delphi 附录菜单没有';当ModalPopupMode=pmAuto时不工作

Delphi 附录菜单没有';当ModalPopupMode=pmAuto时不工作,delphi,forms,popup,modal-dialog,Delphi,Forms,Popup,Modal Dialog,在Delphi中,我使用以下行(和其他行几乎相同)向表单的系统菜单添加项: AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, cSetScreenResolution1024x768, PChar('1024x768')); 这是一个类的一部分,所有其他表单都从该类继承而来,大多数情况下它都可以正常工作,但我注意到,当表单以模态模式打开时,自定义菜单项并不存在。当以无模式模式打开同一表单时,它工作正常。我花了一些时间来找

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

AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, cSetScreenResolution1024x768,  PChar('1024x768'));
这是一个类的一部分,所有其他表单都从该类继承而来,大多数情况下它都可以正常工作,但我注意到,当表单以模态模式打开时,自定义菜单项并不存在。当以无模式模式打开同一表单时,它工作正常。我花了一些时间来找出原因,我发现如果ModalPopupMode=pmAuto我会得到这个错误。当它为pmNone时,一切正常

有人能解释为什么会这样吗?也许会就如何解决这个问题给出建议?我使用ModalPopupMode=pmAuto来修复其他问题,因此将其恢复为pmNone不是一个好的选择

要复制,只需使用两种形式制作一个小项目。在第一个窗体上放置两个按钮,一个用于以模式打开第二个窗体,一个用于以非模式打开它。将此行放入第二个窗体的“创建”:

AppendMenu(GetSystemMenu(Self.Handle, False), MF_BYPOSITION, 10000,  PChar('1024x768'));
现在它将按预期工作。现在,将应用程序ModalPopupMode设置为pmAuto,并观察在以模态方式打开表单时,系统菜单上的额外菜单项已消失

或者(可能更方便)复制这5个“文件”:

项目1.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.
单元1.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.
单元1.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
单元2.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.
单元2.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

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


只有在知道窗体具有窗口句柄后,才应使用窗口句柄。重写表单的
CreateWnd
方法,并将
AppendMenu
代码放在那里。该方法在创建表单句柄后调用,每次创建表单句柄时都会调用,因此您可能会看到对同一表单多次调用该方法。在以模式创建窗体时,窗体的某些属性可能正在更改,这会导致重新创建窗口。实际上,您的
AppendMenu
命令可能会在窗体准备就绪之前强制窗体创建其窗口,从而加剧问题。(读取
句柄
属性会强制句柄存在(如果它不存在)。

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


只有在知道窗体具有窗口句柄后,才应使用窗口句柄。重写表单的
CreateWnd
方法,并将
AppendMenu
代码放在那里。该方法在创建表单句柄后调用,每次创建表单句柄时都会调用,因此您可能会看到对同一表单多次调用该方法。在以模式创建窗体时,窗体的某些属性可能正在更改,这会导致重新创建窗口。实际上,您的
AppendMenu
命令可能会在窗体准备就绪之前强制窗体创建其窗口,从而加剧问题。(读取
Handle
属性会强制该句柄存在(如果该句柄不存在)。

TCustomForm.showmodel
已接到调用
重新创建
,具体取决于表单的“PopupMode”和应用程序的“ModalPopupMode”。谢谢。我没有意识到这一点。还感谢Sertac。
TCustomForm.showmodel
已接到一个调用
recreatedwnd
,具体取决于表单的“PopupMode”和应用程序的“ModalPopupMode”。谢谢。我没有意识到这一点。也谢谢塞塔克。