2010-12-14 16 views
0

ModalPopupModeは、私は、フォームのシステムメニューにアイテムを追加するために(ほぼ同じ、など)、次の行を使用する場合AppendMenuが機能しない:デルファイ= pmAuto

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

これは、クラスの一部でありますほとんどの場合、うまく動作しますが、モーダルモードでフォームを開くと、カスタムメニューが表示されません。モードレスモードで同じフォームが開かれてもうまく動作します。私はしばらく時間を費やして、なぜそれを見つけましたか?ModalPopupMode = pmAutoこのエラーが発生します。それがの場合、の場合は問題なく動作します。

これはなぜ起こるのか説明できますか?そして、それを解決する方法について助言を与えるかもしれませんか?私はModalPopupMode = pmAutoを使って他の問題を修正していますので、pmNoneに戻すのは良い選択肢ではありません。

再現するには、2つのフォームで小さなプロジェクトを作成してください。最初のフォームに2つのボタンをドロップします.1つは2つ目のフォームをモーダルに開き、もう1つはモードレスにします。この行を2番目のフォームの作成に入れてください:

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.PA S

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 

答えて

4

コンストラクタは、フォームのウィンドウハンドルを操作するための場所ではありません。コントロールのハンドルは、フォームの有効期間中に再作成される可能性があります。

フォームハンドルがウィンドウハンドルであるを持っていることを確認した後でのみ、ウィンドウハンドルを使用してください。フォームのCreateWndメソッドをオーバーライドし、そこでAppendMenuコードを入力してください。このメソッドは、フォームのハンドルが作成された後に呼び出されます。それぞれフォームのハンドルが作成されるまでに時間がかかるため、同じフォームに対して複数回呼び出されることがあります。あなたのフォームの一部のプロパティは、おそらくモーダルで作成されている間に変更されているため、ウィンドウが再作成されています。実際には、あなたのAppendMenuコマンドは、準備が整う前にフォームを強制的に作成して問題を悪化させる可能性があります。

+1

'TCustomForm.ShowModal'は、フォームの 'PopupMode'とアプリケーションの 'ModalPopupMode'に応じて' RecreateWnd'を呼び出しています。 –

+0

ありがとうございます。私はこれを知らなかった。 Sertacにも感謝します。 –