[トップ][編集][ノート][編集履歴][一覧][最近の更新][->English]

ツールバーにドロップダウンメニュー表示

ツールバーにドロップダウンメニュー表示


HSP3.0で動作確認

スクリプト

; <<<< HSP 3.0 サンプル >>>>
;
;   ツールバーボタンにドロップダウンメニューを表示
;

    #uselib "comctl32.dll"
    #func InitCommonControls "InitCommonControls"

    #uselib "user32.dll"
    #func CreatePopupMenu  "CreatePopupMenu"
    #func TrackPopupMenuEx "TrackPopupMenuEx" int,int,int,int,int,int
    #func AppendMenu       "AppendMenuA"      int,int,int,sptr
    #func DestroyMenu      "DestroyMenu"      int
    #func ClientToScreen   "ClientToScreen"   int,int

    #define WM_COMMAND          0x0111
    #define WM_NOTIFY           0x004E

    #define TBN_DROPDOWN        -710

    #define TB_BUTTONSTRUCTSIZE 0x041E
    #define TB_ADDBITMAP        0x0413
    #define TB_AUTOSIZE         0x0421
    #define TB_ADDBUTTONS       0x0414
    #define TB_SETEXTENDEDSTYLE 0x0454
    #define TB_GETRECT          0x0433

    #define TBSTYLE_EX_DRAWDDARROWS 1

    screen 0, 300, 200
    oncmd  gosub *OnCommand, WM_COMMAND
    oncmd  gosub *OnNotify,  WM_NOTIFY
    onexit gosub *OnClose

    ; ==== ツールバー ====

    ; コモンコントロールライブラリの初期化
    InitCommonControls

    ; ツールバー作成
    winobj "ToolbarWindow32","",0,$50000801,0,0
    hTool = objinfo_hwnd(stat)

    sendmsg hTool, TB_BUTTONSTRUCTSIZE, 20, 0
    sendmsg hTool, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS

    tbadd(0) = -1        ; HINST_COMMCTRL
    tbadd(1) = 0         ; IDB_STD_SMALL_COLOR
    sendmsg hTool, TB_ADDBITMAP, 0, varptr(tbadd)

    tbb( 0) =  6, 1, ($8<<8)|0x04, 0, 0  ;「新規作成」ボタン
    tbb( 5) =  7, 2, 0x04, 0, 0          ;「開く」ボタン
    tbb(10) =  8, 3, 0x04, 0, 0          ;「保存」ボタン
    tbb(15) =  0, 0, 1<<8, 0, 0          ;「セパレータ」ボタン
    tbb(20) =  0, 4, 0x04, 0, 0          ;「切り取り」ボタン
    tbb(25) =  1, 5, 0x04, 0, 0          ;「コピー」ボタン
    tbb(30) =  2, 6, 0x04, 0, 0          ;「貼り付け」ボタン
    tbb(35) =  0, 0, 1<<8, 0, 0          ;「セパレータ」ボタン
    tbb(40) =  3, 7, 0x04, 0, 0          ;「アンドゥ」ボタン
    tbb(45) = 12, 8, 0x04, 0, 0          ;「検索」ボタン
    sendmsg hTool, TB_ADDBUTTONS, 10, varptr(tbb)

    sendmsg hTool, TB_AUTOSIZE, 0, 0

    ; ドロップダウンボタン用のメニュー作成
    CreatePopupMenu : hmenu = stat
    AppendMenu hmenu,    0, 101, "新規1"
    AppendMenu hmenu,    0, 102, "新規2"
    AppendMenu hmenu, $800,   0, ""     ; 区切り線
    AppendMenu hmenu,    0, 104, "ファイルから..."

    stop

*OnCommand
    itemId = wParam & $FFFF
    dialog "コマンドID:"+itemId
    return

*OnNotify
    dupptr nmhdr, lParam, 12
    if (nmhdr(0) == hTool) & (nmhdr(2) == TBN_DROPDOWN) {
        gosub *OnToolDropDown
    }
    return

*OnToolDropDown
    dupptr nmtoolbar, lParam, 44
    itemId = nmtoolbar(3)
    if itemId == 1 {
        dim rc, 4
        sendmsg hTool, TB_GETRECT, itemId, varptr(rc)
        pt = rc(0), rc(3)
        ClientToScreen hTool, varptr(pt)
        TrackPopupMenuEx hmenu, 0, pt(0), pt(1), hwnd, 0
    }
    return

*OnClose
    if hmenu : DestroyMenu hmenu
    end

解説

ツールバー(ドロップダウンメニュー無し)については次のリンクを参照。

ショートカットメニューについては次のリンクを参照。

ここでは、ツールバーボタンの横に付けられるアローボタン(ドロップダウンメニューを表示するボタン)について解説。

まず、アローボタンつきのツールバーを作成するには、comctl.dllのバージョンが4.71以上でなければならないので、あしからず。

アローボタン付きツールバーを作成するには、ツールバーが TBSTYLE_EX_DRAWDDARROWS 拡張スタイルを持っていなければいけないのですが、拡張スタイルの設定は TB_SETEXTENDEDSTYLE メッセージを使わなくてはいけません。一般的に使われるような CreateWindowEx 呼び出し時の拡張スタイルパラメータでの指定はできませんし、SetWindowLong 等で書き換えてもダメです。

上のスクリプトの

sendmsg hTool, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS

となっている部分が拡張スタイル設定にあたります。

ツールボタンにアローボタンを付けるには、ボタンを追加する際に、 TBBUTTON 構造体の fsStyle メンバに BTNS_DROPDOWN フラグ(8) を指定する必要があります。(BTNS_DROPDOWN は TBSTYLE_DROPDOWN と書かれていることもあります。) 上のスクリプトでは、最初のボタンだけにアローボタンを付けるようにしています。

tbb( 0)  =  6, 1, ($8<<8)|0x04, 0, 0      ;「新規作成」ボタン

の「($8<<8)」の部分が、 BTNS_DROPDOWN スタイルの設定です。

以上で、アローボタンつきのツールボタンが表示されます。次に、アローボタンが押されたときの処理について解説しましょう。

このアローボタンが押されると、 WM_NOTIFY メッセージが送られてきます。このときの通知コードは TBN_DROPDOWN (-710) となっています。lParam パラメータは NMTOOLBAR 構造体のアドレスです。上のスクリプトでは、nmtoolbar という変数に割り当てています。HSP3では dupptr 命令が追加されて、任意アドレスを変数に割り当てることができるようになったので、便利です。

typedef struct tagNMTOOLBAR {
  NMHDR hdr;         // => nmtoolbar(0)〜nmtoolbar(2)
  int iItem;         // => nmtoolbar(3)
  TBBUTTON tbButton; // => nmtoolbar(4)〜nmtoolbar(8)
  int cchText;       // => nmtoolbar(9)
  LPTSTR pszText;    // => nmtoolbar(10)
  RECT rcButton;     // => nmtoolbar(11)〜nmtoolbar(14) (新しく追加されたメンバ)
} NMTOOLBAR;

iItem メンバ(この場合は nmtoolbar(3))にアイテムIDが格納されているので、複数のアローボタンを表示させている場合には、これによってどのメニューを表示させるかを決定できます。

アイテムIDが決定できたら、ドロップダウンメニューを表示させるわけですが、どこに表示させるかを決める必要がありますね。これには、まず、TB_GETRECT メッセージでボタンの領域を取得します。この領域はクライアント座標で表されたものなので、領域の左下の点の座標 (rc(0), rc(3)) を、ClientToScreen 関数を使ってスクリーン座標に変換しています。

メニューを表示する座標が分かったら、あとは TrackPopupMenuEx でメニューを表示するだけです。メニューアイテムが選択されると WM_COMMAND を受け取ります。