AppendMenu не работает, когда ModalPopupMode = pmAuto - PullRequest
0 голосов
/ 14 декабря 2010

В 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 «файлов»:

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 Ответ

4 голосов
/ 14 декабря 2010

Конструктор - это не то место, где можно манипулировать дескриптором окна формы.Дескриптор элемента управления может быть воссоздан в течение срока жизни формы.

Вы должны использовать дескриптор окна только после того, как знаете, что форма имеет дескриптор окна.Переопределите метод CreateWnd вашей формы и поместите туда код AppendMenu.Этот метод вызывается после создания дескриптора формы, каждый каждый раз, когда создается дескриптор формы, поэтому вы можете видеть, что он вызывался несколько раз для одной и той же формы.Некоторые свойства вашей формы, вероятно, изменяются во время ее создания модально, и это вызывает повторное создание окна.Фактически, ваша команда AppendMenu может усугубить проблему, заставив форму создать свое окно до того, как она будет готова.(Чтение свойства Handle заставляет дескриптор существовать, если его там еще нет.)

...