プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

MFCのダイアログでツールバーを表示する。

この記事は2019年02月03日に投稿しました。

f:id:paveway:20190914064630j:plain

目次

  1. はじめに
  2. MFCのダイアログでツールバーを表示する
  3. おわりに

かんたん Visual C++ [改訂2版] (プログラミングの教科書)

かんたん Visual C++ [改訂2版] (プログラミングの教科書)

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用しているMFCのダイアログでツールバーを表示する方法についてです。

目次へ

2. MFCのダイアログでツールバーを表示する

MFCのダイアログでツールバーを表示する方法ですが、ウィザード等ではできないようです。
そのため自力でコーディングする必要があります。

以下が、MFCのダイアログでツールバーを表示する手順です。

  1. ダイアログクラスのOnInitDailog関数等で、ツールバーを生成します。
  2. ツールバーに表示するイメージとボタンのサイズを設定します。 設定しない場合、デフォルトでは16x15ピクセルになります 。
  3. ツールバーに、ボタンで表示するイメージを設定します。 ボタンが有効時と無効時のイメージを設定できます。
    無効時は有効時のイメージと同じでも構いません。
  4. ツールバーにボタンを設定します。 今回はボタンと区切り線を設定しました。
    その他チェックボックなども設定できるようですが、今回は省略します。
  5. ツールバーのサイズを設定します。 サイズを設定しないと、サイズ0で表示されません。
  6. ツールバーのボタンが押下された時のイベントハンドラを追加します。
    今回はON_COMMAND_RANGEマクロで、ツールバーの各ボタンイベントを1つのイベントハンドラで処理するようにしました。
    ON_COMMANDマクロで、ツールバーの各ボタン毎にイベントハンドラを追加してもよいです。

実装例

Resource.h
// ツールバーボタンのイメージのリソースID
// (値は実装によるため、省略します)
#define IDB_TOOLBAR_IMAGE_A            (XXX)
#define IDB_TOOLBAR_IMAGE_B            (XXX)
#define IDB_TOOLBAR_IMAGE_C            (XXX)

#define IDB_TOOLBAR_IMAGE_DISABLED_A   (XXX)
#define IDB_TOOLBAR_IMAGE_DISABLED_B   (XXX)
#define IDB_TOOLBAR_IMAGE_DISABLED_C   (XXX)
SampleDlg.h
class CSampleDlg : public CDialgEx
{

...

protected:
    // 初期化時に呼出されます。
    virtual BOOL OnInitDialog();

DECLARE_MESSAGE_MAP()
public:
    // ツールバーのボタンが押下された時に呼出されるイベントハンドラ
    afx_msg void OnToolBarButtonPressed(UINT nID);

private:
    // ツールバー
    CToolBar m_toolBar;
    // ボタンが有効時のイメージリスト
    CImageList m_imageList;
    // ボタンが無効時のイメージリスト
    CImageList m_disabledImageList;

...

}
SampleDlg.cpp
// ツールバーのボタンイベントIDの基準値
#define ID_TOOLBAR_BUTTON              (WM_USER + 100)

// ツールバーのボタンイベントID
#define ID_TOOLBAR_BUTTON_A            (ID_TOOLBAR_BUTTON + 0)
#define ID_TOOLBAR_BUTTON_B            (ID_TOOLBAR_BUTTON + 1)
#define ID_TOOLBAR_BUTTON_C            (ID_TOOLBAR_BUTTON + 2)

// ツールバーのボタン数
#define TOOLBAR_BUTTON_NUM             (3)

// ツールバーのボタンに表示するイメージの幅(ピクセル)
#define TOOLBAR_IMAGE_WIDTH            (32)
// ツールバーのボタンに表示するイメージの高さ(ピクセル)
#define TOOLBAR_IMAGE_HEIGHT           (32)
// ツールバーのボタンに表示するイメージの幅方向のマージン(ピクセル)
// マージを取らないとクラッシュします。
// 幅方向、縦方向のマージンの値は、Widowsの指定値です。
#define TOOLBAR_IMAGE_MARGIN_WIDTH     (7)
// ツールバーのボタンに表示するイメージの高さ方向のマージン(ピクセル)
#define TOOLBAR_IMAGE_MARGIN_HEIGHT    (6)

// ツールバーのイメージのマスク値
#define TOOLBAR_IMAGE_MASK             RGB(0, 0, 0)

// ツールバーイメージのインデックス
#define TOOLBAR_IMAGE_INDEX_A          (0)
#define TOOLBAR_IMAGE_INDEX_B          (1)
#define TOOLBAR_IMAGE_INDEX_C          (2)

/**
 * 初期化時に呼出されます。
 *
 * @return 処理結果 TRUE:正常/FALSE:失敗
 */
BOOL CSampleDlg::OnInitDialog()
{
    // 親クラスの関数を呼び出します。
    CDialogEx::OnInitDialog();

    ...

    // 1. ツールバーを生成します。
    if (!m_toolBar.Create(this))
    {
        // ツールバーが生成できない場合、終了します。
        return FALSE;
    }

    // 2. ツールバーのイメージとボタンのサイズを設定します。
    SIZE sizeImage;
    ZeroMemory(&sizeImage, sizeof(sizeImage));
    sizeImage.cx = TOOLBAR_IMAGE_WIDTH;
    sizeImage.cy = TOOLBAR_IMAGE_HEIGHT;
    SIZE sizeButton;
    ZeroMemory(&sizeButton, sizeof(sizeButton));
    sizeButton.cx = sizeImage.cx + TOOLBAR_IMAGE_MARGIN_WIDTH;
    sizeButton.cy = sizeImage.cy + TOOLBAR_IMAGE_MARGIN_HEIGHT;
    m_toolBar.SetSizes(sizeButton, sizeImage);

    // 3. ツールバーのボタンが有効な場合に表示するイメージを設定します。
    CBitmap bitmapA;
    bitmapA.LoadBitmap(IDB_TOOLBAR_IMAGE_A);
    CBitmap bitmapB;
    bitmapB.LoadBitmap(IDB_TOOLBAR_IMAGE_B);
    CBitmap bitmapC;
    bitmapC.LoadBitmap(IDB_TOOLBAR_IMAGE_C);

    // ビットマップは8bit(256色)を想定しているため、Create関数の第3引数は"ILC_COLOR8"としています。
    // ビットマップの色数により、第3引数の設定値は変更して下さい。
    m_imageList.Create(TOOLBAR_IMAGE_WIDTH, TOOLBAR_IMAGE_HEIGHT, ILC_COLOR8, TOOLBAR_BUTTON_NUM, TOOLBAR_BUTTON_NUM);
    m_imageList.Add(&bitmapEnableA, TOOLBAR_IMAGE_MASK);
    m_imageList.Add(&bitmapEnableB, TOOLBAR_IMAGE_MASK);
    m_imageList.Add(&bitmapEnableC, TOOLBAR_IMAGE_MASK);
    m_toolBar.SetImageList(&m_imageList);

    // ツールバーのボタンが無効な場合に表示するイメージを設定します。
    // イメージは有効な場合のイメージを流用しても構いません。
    CBitmap bitmapDisbleA;
    bitmapDisbleA.LoadBitmap(IDB_TOOLBAR_IMAGE_DISABLED_A);
    CBitmap bitmapDisbleB;
    bitmapDisbleB.LoadBitmap(IDB_TOOLBAR_IMAGE_DISABLED_B);
    CBitmap bitmapDisbleC;
    bitmapDisbleC.LoadBitmap(IDB_TOOLBAR_IMAGE_DISABLED_C);

    // ビットマップは8bit(256色)を想定しているため、Create関数の第3引数は"ILC_COLOR8"としています。
    // ビットマップの色数により、第3引数の設定値は変更して下さい。
    m_disabledImageList.Create(TOOLBAR_IMAGE_WIDTH, TOOLBAR_IMAGE_HEIGHT, ILC_COLOR8, TOOLBAR_BUTTON_NUM, TOOLBAR_BUTTON_NUM);
    m_disabledImageList.Add(&bitmapDisbleA, TOOLBAR_IMAGE_MASK);
    m_disabledImageList.Add(&bitmapDisbleB, TOOLBAR_IMAGE_MASK);
    m_disabledImageList.Add(&bitmapDisbleC, TOOLBAR_IMAGE_MASK);
    m_toolBar.SetDisabledImageList(&m_disalbedImageList);

    // 4. ツールバーのボタンを設定します。
    //    SetButtons関数の第2引数に項目数を設定します。
    //    (例ではボタン数+区切り線の数を設定しています)
    m_toolBar.SetButtons(NULL, TOOLBAR_BUTTON_NUM + 1);

    // ツールバーの各ボタンを設定します。
    // SetButtons関数で指定した項目数分設定する必要があります。
    // 第1引数:ボタンのインデックス(0起算の通し番号)
    // 第2引数:イベントハンドラで識別されるID
    //        区切り線の場合、ダミー値の-1を設定しています。
    // 第3引数:ボタンの種類
    //         TBBS_BUTTON    : ボタン
    //         TBBS_SEPARATOR : 区切り線
    // 第4引数:イメージのインデックス
    //        ボタンとイメージを紐づけます。
    //        そのためSetImageList/SetDisabledImageListで設定したイメージのインデックスを合わせます。
    //        区切り線の場合、ダミー値の-1を設定しています。
    m_toolBar.SetButtonInfo(0, ID_TOOLBAR_BUTTON_A, TBBS_BUTTON,    TOOLBAR_IMAGE_INDEX_A);
    m_toolBar.SetButtonInfo(1, ID_TOOLBAR_BUTTON_B, TBBS_BUTTON,    TOOLBAR_IMAGE_INDEX_B);
    m_toolBar.SetButtonInfo(2, -1,                  TBBS_SEPARATOR, -1);
    m_toolBar.SetButtonInfo(3, ID_TOOLBAR_BUTTON_C, TBBS_BUTTON,    TOOLBAR_IMAGE_INDEX_C);

    // 5. ツールバーのサイズを設定します。
    //    サイズを設定しないとサイズ0となり、表示されません。
    //    幅はダイアログの幅、高さはイメージの高さにします。
    CRect dlgRect;
    GetClientRect(dlgRect);

    CSIZE toolBarSize;
    toolBarSize = m_toolBar.CalcFixedLayout(FALSE, TRUE);
    m_toolBar.MoveWindow(0, 0, dlgRect.Width(), toolBarSize.cy);

    ...
}

// 6. イベントハンドラを設定します。
//    ウィザードが使えないため、手動で設定して下さい。
BEGIN_MESSAGE_MA(CSampleDlg, CDialogEx)
    // 第1引数:イベントハンドラが処理する開始ID
    // 第2引数:イベントハンドラが処理する終了ID
    ON_COMMAND_RANGE(ID_TOOLBAR_BUTTON, ID_TOOLBAR_BUTTON + TOOLBAR_ITEM_NUM - 1, &CSampleDlg::OnToolBarButtonPressed)
END_MESSAGE_MAP()

/**
 * @brief ツールバーのボタンが押下された時に呼出されます。
 *
 * @param [in] nID ボタンのイベントID
 */
void CSampleDlg::OnToolBarButtonPressed(UINT nID)
{
    // ボタンのイベントIDにより処理を振り分けます。
    switch (nID)
    {
    case ID_TOOLBAR_BUTTON_A:
        // ボタンAが押下された場合
        AfxMessageBox(_T("ツールバーのボタンAが押下されました。"));
        break;

    case ID_TOOLBAR_BUTTON_B:
        // ボタンBが押下された場合
        AfxMessageBox(_T("ツールバーのボタンBが押下されました。"));
        break;

    case ID_TOOLBAR_BUTTON_C:
        // ボタンCが押下された場合
        AfxMessageBox(_T("ツールバーのボタンCが押下されました。"));
        break;

    default:
        // 上記以外、何もしません。
        break;
    }
}

目次へ

3. おわりに

ダイアログにツールバーを表示する方法は他にもあります。
しかし今回の要件で動的にツールバーの数が変わるため、ImageListを使った方法で実装しました。

ダイアログの場合、標準ではツールバーは表示されないため全てコードで書くことになります。

ITエンジニアの無料カウンセリング【ポテパンフリーランス】

標準講座MFC6.0―Visual C++による効率的なWindowsプログラミング (Programmer’s SELECTION)

標準講座MFC6.0―Visual C++による効率的なWindowsプログラミング (Programmer’s SELECTION)

  • 作者: ハーバートシルト,田中正造,Herbert Schildt,コスモワークス
  • 出版社/メーカー: 翔泳社
  • 発売日: 1999/04/01
  • メディア: 単行本
  • 購入: 11人 クリック: 39回
  • この商品を含むブログ (4件) を見る

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ