ホーム >プログラム >Delphi 6 ローテクTips

メニューの高さを取得

メインメニューの高さを知りたいと思いました。
というのもウィンドウの幅を狭めるとメニューが二階建てになったりするので、その状態であるかどうかを判定したかったのです。


参考サイト


GetMenuBarInfo

GetSystemMetrics(SM_CYMENU)でいけると思ったのですが、これは一行の時の高さしか返してくれず、今現在のメニューの高さを返してくれるわけではありませんでした。
さてどうしたものかと思っていたところ、GetMenuBarInfoというAPIがあるのを知りました。
そのものずばりメニューバーの高さが取得できるAPIのようです。

ところがどうやっても、なんとしてもDelphi 6ではエラーが返ってきてしまいます。
色々試行錯誤した結果tagMENUBARINFOを書き換えてみたらいけました。

type
  { Menubar information }
  {$EXTERNALSYM PMenuBarInfo}
  PMenuBarInfo = ^TMenuBarInfo;
  {$EXTERNALSYM tagMENUBARINFO}
  tagMENUBARINFO = packed record
    cbSize: DWORD;
    rcBar: TRect;        { rect of bar, popup, item }
    hMenu: HMENU;        { real menu handle of bar, popup }
    hwndMenu: HWND;      { hwnd of item submenu if one }
{    fBarFocused:1: BOOL;} { bar, popup has the focus }
{    fFocused:1: BOOL; }  { item has the focus }
    FocusedBits: BYTE;
  end;
  {$EXTERNALSYM TMenuBarInfo}
  TMenuBarInfo = tagMENUBARINFO;

{$EXTERNALSYM GetMenuBarInfo}
function GetMenuBarInfo(hend: HWND; idObject, idItem: Longint; var pmbi: TMenuBarInfo): BOOL; stdcall;

これがオリジナル。

type
  {$EXTERNALSYM tagMENUBARINFO}
  tagMENUBARINFO = {packed} record
    cbSize:      DWORD;
    rcBar:       TRect;  { rect of bar, popup, item }
    hMenu:       HMENU;  { real menu handle of bar, popup }
    hwndMenu:    HWND;   { hwnd of item submenu if one }
//    fBarFocused: Boolean;{ bar, popup has the focus }
//    fFocused:    Boolean;{ item has the focus }
    FocusedBits: BYTE;
  end;
  {$EXTERNALSYM TMenuBarInfo}
  TMenuBarInfo = tagMENUBARINFO;
  {$EXTERNALSYM PMenuBarInfo}
  PMenuBarInfo = ^TMenuBarInfo;

function GetMenuBarInfo(hend: HWND; idObject, idItem: Longint; var pmbi: TMenuBarInfo): BOOL; stdcall external 'user32.dll';

そしてこれが書き換えたものです。
tagMENUBARINFO = packed recordpacked を削りました。それだけです。
後は GetMenuBarInfo も再宣言しておきます。
これをしないと

'変数実パラメータと変数仮パラメータとは同一の型でなければなりません'

というエラーが出てコンパイルできません。
そしてこれをGetMenuBarInfoを使うユニットの中に書きます。
Windows.pasに書かれているオリジナルよりもこちらを優先させるわけです。

procedure TForm1.Button1Click(Sender: TObject);
var
  lr_Info: TMenuBarInfo;
begin
  FillChar(lr_Info, SizeOf(lr_Info), 0);
  lr_Info.cbSize := SizeOf(lr_Info);
  if (GetMenuBarInfo(Self.Handle, Longint(OBJID_MENU), 0, lr_Info)) then begin
    myDebug.gpcDebugAdd(lr_Info.rcBar);
  end else begin
    Beep;
  end;
end;

これでメインメニューのメニューバーのRectが取得できます。
他にも第2引数の値や第3引数の値に応じて色々なメニューの状態やRectが取得できるようです。
ちなみに第2引数の定数はLongintでキャストしないとコンパイルの時に

'定数式が範囲を越えました'

という警告が出ます。


第2引数にOBJID_MENUを指定した場合

GetMenuBarInfo APIの第2引数のidObjectにOBJID_MENUを指定した場合の第3引数のidItemの各値の結果は以下のようになります。


第2引数にOBJID_SYSTEMを指定した場合

GetMenuBarInfo APIの第2引数のidObjectにOBJID_SYSTEMを指定した場合の第3引数のidItemの各値の結果は以下のようになります。