8

私は最善を尽くしましたが、ここで何が起こったのか理解できません。Delphi 4 では問題なく動作しました。Delphi 2009 にアップグレードした後、これが本来の動作なのか、それとも問題なのかわかりません。

これは、Delphi 2009 のデザイン モードで私のプログラムのメニューがどのように見えるかです。

ここに画像の説明を入力

メイン メニューとファイル サブメニューのすべての単語には、1 文字に下線が引かれていることに注意してください。このようになっているはずです。この下線付きの文字はアクセラレータ キーと呼ばれ、Windows アプリケーションの標準であるため、Alt キーとその文字を使用して、マウスではなくキーボードでメニュー項目とサブメニュー項目をすばやく選択できます。

アイテムのキャプションの一部として「&」文字を使用すると、この方法で取得できます。例: Save &As...

アプリケーションを実行し、マウスを使用して [ファイル] メニューを開くと、次のようになります。

ここに画像の説明を入力

メイン メニューでは文字に下線が引かれますが、ファイル メニューでは下線が引かれません。

代わりに、Alt-F キーを使用して [ファイル] サブメニューを開くと、次のように正しく表示されます。

ここに画像の説明を入力

すべてのアクセラレータ キーの文字には適切に下線が引かれています。

AutoHotKeys オプションを試してみましたが、それは問題ではありません。

誰かが以前にこの問題に遭遇したことがありますか? 私が知らない2番目の画像の例は正しい動作ですか? または、見逃した可能性のあるオプションやコーディングの間違いはありますか?


2009 年 11 月 (1 年後): mghie はこの問題の根源に到達し、問題を解決したようです。以下の彼の受け入れられた回答を参照してください。

4

4 に答える 4

7

Alt キーを押したままにしない限り、これらのアクセラレータを通常非表示にする標準の Windows 設定 (表示プロパティの下) があります。これで、Alt+F10 でメニューを開くと表示される理由が説明できます。もしかしてそれが原因?

[編集]: いいえ、そうではありません。試してみたところ、メニュー項目を持つ単純な TForm にアクセラレータが表示されますが、TImageList を追加して単一のメニュー項目の ImageIndex を設定するか、単に OwnerDraw を true に設定するとすぐに、アクセラレータの下線が消えます。これは本当に VCL のバグだと思います。

ところで、これは Windows XP です。

回避策:

Windows XP 64 で Delphi 2009 を使用してこれをデバッグしましたが、アクセラレータが見つからない根本的な原因は、Windows がフラグを設定WM_DRAWITEMしてメッセージを送信することであると思われます。ODS_NOACCELしたがって、これは VCL のバグではなく、VCL が回避できない Windows の問題であると言えます。

ただし、独自のコードで回避できます。メッセージを VCL に渡す前にフラグをリセットするだけで済みます。ウィンドウ プロシージャをオーバーライドする

protected
  procedure WndProc(var Message: TMessage); override;

そのようです:

procedure TYourForm.WndProc(var Message: TMessage);
const
  ODS_NOACCEL = $100;
var
  pDIS: PDrawItemStruct;
  ShowAccel: BOOL;
begin
  if (Message.Msg = WM_DRAWITEM) then begin
    pDIS := PDrawItemStruct(Message.LParam);
    if (pDIS^.CtlType = ODT_MENU)
      and SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @ShowAccel, 0)
    then begin
      if ShowAccel then
        pDIS^.itemState := pDIS^.itemState and not ODS_NOACCEL;
    end;
  end;
  inherited;
end;

これはデモンストレーション コードのみです。メッセージを受信SystemParametersInfo()するたびに呼び出すのではなくWM_DRAWITEM、プログラムの開始時に 1 回呼び出してから、プログラムがメッセージを受信するたびに呼び出す必要がありWM_SETTINGCHANGEます。

于 2008-11-11T07:57:44.860 に答える
6

これは、Windows 2000 で導入された「機能」です。

古い新しいもの: Windows がデフォルトでキーボード アクセラレータを非表示にし、四角形をフォーカスするのはなぜですか?

Delphi 4 は、この Windows 機能をサポートしていないようです。

2000 および XP のメニューにアクセラレータ キーを表示するには、デスクトップの何もない場所を右クリックし、[プロパティ] を選択して [外観] タブをクリックし、[効果] で [ Alt キーを押すまでキーボード ナビゲーションに下線付きの文字を表示しない] のチェックを外します。[OK] を 2 回クリックします。

Vistaでのやり方がわかりません。

于 2008-11-11T08:00:00.690 に答える
1

Vista のメモ帳と同じ動作をするので、Delphi が生成したバグではないと思います。また、Delphi自体でも...
あなたの質問の前に注意を払っていなかったことを告白しなければなりません。ご指摘ありがとうございます。

于 2008-11-11T07:50:03.300 に答える
0

ジム・マッキースが上で(正しく)述べたように、これは「設計による」動作です。メニューがキーボードアクションによってトリガーされた場合はアクセラレータが表示されますが、マウスによってトリガーされた場合は意図的にアクセラレータは表示されません。

XPで常にアクセラレータを表示するように構成しましたが、そのオプションを変更して簡単にテストすると、メニューにも下線が表示されないことが確認されます(Visual Studioは期待どおりに応答し、マウスを使用すると下線は表示されません)。ただし、Microsoft Officeはこの設定を無視し、常に下線を表示します。したがって、Delphiでのメニューの描画方法にバグがあるように見えます(私自身、Delphiの経験はありません)。

Vistaのオプションも見つかりました:http ://www.vistax64.com/vista-general/42125-always-show-menu-underline-keyboard-accelerators.html

これは、新しいEase of Access Centerでオンにできます([コントロールパネル]に移動し、[Ease of Access]をクリックしてから、[Ease of Access Center]をクリックします)。[アクセスのしやすさ]センターで、[キーボードを使いやすくする]をクリックし、一番下にある[キーボードショートカットとアクセスキーに下線を付ける]チェックボックスをオンにします。

さらに調査を行っているときに、Delphiフォーラムでこの関連するバグを見つけました:http: //qc.codegear.com/wc/qcmain.aspx? d = 37403

あなたの場合、子ウィンドウ(描画されたメニュー)が親ウィンドウからWM_UIUPDATESTATEメッセージを取得していないか、処理していないようです。これがアクセラレータによる再描画の原因です。

于 2008-12-17T02:01:12.907 に答える