SDK Index Previous page Next page

Explorer-Style カスタムコモンダイアログ


はじめに

今回は、コモンダイアログをカスタマイズする方法を紹介します。コモンダイアログをカスタマイズするには、テンプレートファイルを書き換えてダイアログ全体を書き換える方法と、コモンダイアログに独自のダイアログを追加する方法があります。
今回は、後者の方法を説明します。これはExplorer-Styleのカスタムダイアログというようです(どうExplorerなのかはよくわかりませんが)。ただ、この方法はもしかするとIE4をインストールしていないと使えないかもしれません。詳しく知っている方は教えてください。
サンプルプログラムはここです。今回から、VC6.0になったので以前のVCでは読み込めないかもしれません。ただ、たぶん構造は変わっていないと思うので読めなかったときでもワークスペースとプロジェクトファイルの中のバージョンをテキストエディターで書き換えれば読み込めると思います。このサンプルを実行すると、ファイルを開くダイアログが次のようにカスタマイズされます。(Buttonを押してもなにも起こりません。)

esccd image

プログラム

まずは、プログラムをみてください。強調表示になっているところが重要なところです。

#include <windows.h>
#include <commdlg.h>
#include <dlgs.h>
#include "resource.h"

HANDLE         Instance;

//フックプロシージャ
UINT CALLBACK OFNHookProc(HWND hdlg, UINT msg, WPARAM wParam,LPARAM lParam)
{
    switch(msg){
        case WM_INITDIALOG:
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam)){
                case IDC_BUTTON1:
                    //ここでボタンが押されたときの処理をする。
                    return TRUE;
            }
            break;

    }
    return FALSE;
}

int CustomFileOpenDialog(HWND hWnd)
{
    char file_name[MAX_PATH];
    int result;
    OPENFILENAME open_file_name;

    file_name[0]='\0';
    ZeroMemory(&open_file_name, sizeof(open_file_name));
    open_file_name.lStructSize = sizeof(open_file_name);
    open_file_name.hwndOwner = hWnd;
    open_file_name.hInstance = Instance;
    open_file_name.lpstrFilter = "files(*.*)\0*.*\0";
    open_file_name.nFilterIndex = 0;
    open_file_name.lpstrFile = file_name;
    open_file_name.nMaxFile = sizeof(file_name);
    open_file_name.lpstrFileTitle = NULL;
    open_file_name.nMaxFileTitle = 0;
    open_file_name.lpstrTitle = "Select file";
    open_file_name.Flags = OFN_FILEMUSTEXIST |
                           OFN_HIDEREADONLY |
                           OFN_PATHMUSTEXIST|
                           OFN_SHOWHELP |
                           OFN_EXPLORER |       //Explorer Style
                           OFN_ENABLESIZING |   //サイズを変更できるようにする
                           OFN_ENABLEHOOK |     //フックプロシージャを使う
                           OFN_ENABLETEMPLATE;  //ダイアログをカスタムする
    open_file_name.lpfnHook = OFNHookProc;   //フックプロシージャのアドレス
    open_file_name.lpTemplateName = MAKEINTRESOURCE(IDD_CUSTOM);
                                                  //追加するダイアログリソース
    result = GetOpenFileName(&open_file_name);
    
    return  result;
}

int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
          LPSTR lpszCmd, int nCmdShow)
{

    Instance = hInstance;

    CustomFileOpenDialog(NULL);

    return  0;
}
このプログラムでは、ファイルオープンダイアログをカスタマイズしています。ファイルオープンダイアログの関数GetOpenFileNameについては説明しないので各自で調べておいてください。

1 OPENFILENAME構造体

まずは、OPENFILENAME構造体open_file_nameのFlagsメンバをみてください。普通にファイルを開くときにはこのメンバは、

OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_SHOWHELP

のようになると思いますが、カスタムダイアログを使う場合にはさらに

OFN_EXPLORER、OFN_ENABLESIZING、OFN_ENABLEHOOK、OFN_ENABLETEMPLATE

の4つのフラグを指定します。

OFN_EXPLORERはExplorer-Styleのカスタムダイアログを使うときに指定します。

OFN_ENABLESIZINGはダイアログのサイズを変更できるようにするときに指定します。このフラグは、OFN_ENABLEHOOKをつけないときには勝手につきますがOFN_ENABLEHOOKをつけるときには、このフラグを指定しないとサイズ変更が出来なくなります。

OFN_ENABLEHOOKはフックプロシージャを使うことを指定します。このフックプロシージャにはダイアログからのメッセージが送られてきます。OFN_EXPLORERフラグをつけているときには、独自に追加したコントロールからのメッセージのみ送られてきます。

OFN_ENABLETEMPLATEはOFN_EXPLORERのあるときには、ダイアログをカスタマイズするためにダイアログリソースを使うことを示し、OFN_EXPLORERのないときには新しく作ったダイアログテンプレートを使うことを示します。

Explorer-Styleでカスタマイズする場合には4つともつけておけばいいです。

つぎに、lpfnHookとlpTemplateNameメンバをみてください。このメンバにはそれぞれ、フックプロシージャのアドレスと、追加するダイアログリソース識別子を指定します。ダイアログリソースの作り方は後で説明します。このプログラムでは、リソース名をIDD_CUSTOMとしています。

2 フックプロシージャ

フックプロシージャOFNHookProcをみてください。この関数に、ダイアログからのメッセージが送られてきます。OFN_EXPLORERフラグをつけているときにはこの関数には、WM_INITDIALOGメッセージ、自分で追加したコントロールのメッセージ、標準のコントロールやユーザーの操作によって送られるWM_NOTIFYメッセージの3種のメッセージ送られてきます。この関数が0を返した場合デフォルトプロシージャはそのメッセージを処理しますが、0以外を返したときにはそのメッセージを処理しません。つまり、自分で処理をしたときには0以外を返せばいいわけです。

WM_INITDIALOGは、追加するダイアログが初期化されるときに送られてきます。この時lParamにはOPENFILENAME構造体のアドレスが入っています。このメッセージを処理した後で、デフォルトプロシージャはダイアログに独自のダイアログのためのスペースを作るために標準のコントロールを移動させます。それが終わったときにはCDN_INITDONE通知メッセージが送られてきます。

自分で追加したコントロールからのメッセージは、WM_COMMANDメッセージとして送られてくるので、普通のダイアログプロシージャのように処理します。

WM_NOTIFYメッセージは、標準のコントロールやユーザーの操作によるさまざまな通知メッセージが送られたときに送られてきます。lParamにはOFNOTIFY構造体のアドレスが入っていてこれを調べると通知メッセージの種類がわかります。この構造体の説明はここでは省略します。通知メッセージとしては、

CDN_INITDONE          ダイアログ配置が終わったことを知らせます。
CDN_FILEOK            OKボタンが押されたことを知らせます。
CDN_FOLDERCHANGE      開いているフォルダが変わったことを知らせます。
CDN_HELP              HELPボタンが押されたことを知らせます。
CDN_SELCHANGE         別のファイルが選ばれたことを知らせます。
CDN_SHAREVIOLATION    共有違反が発生したことを知らせます。
CDN_TYPECHANGE        ファイルの種類が変更されたことを知らせます。
また、ダイアログの状態を知るためには次のようなメッセージを送ります。それぞれのメッセージについては各自で調べてください(今回こればっか、手抜きだというのがばれてしまう)。
CDM_GETFILEPATH       選択されているファイルのパス(フォルダ名+ファイル名)を取得します。
CDM_GETSPEC           選択されているファイルのファイル名だけを取得します。
CDM_GETFOLDERPATH     現在のフォルダのパスを取得します。
CDM_GETFOLDERIDLIST   現在のフォルダのItem-ID-Listを取得します。
CDM_HIDECONTROL       指定したコントロールを隠します。
CDM_SETCONTROLTEXT    指定したコントロールにテキストを設定します。
CDM_SETDEFEXT         表示するファイルの拡張子を設定します。

3 ダイアログリソース

最後に、ダイアログリソースを作ります。ダイアログリソースはダイアログエディタで作りますが、そのスタイルをチャイルド、境界線なし、兄弟ウインドウをクリップ、可視、3D、コントロールして、それ以外のスタイルはオフにします。ダイアログのIDはIDD_CUSTOMです。
次に、追加するコントロールの位置を決めるために、スタティックコントロールを作ってそのIDを0x45fにします。デフォルトプロシージャは、このスタティックコントロールを中心としてそれぞれのコントロールをダイアログに追加します。すなわち、スタティックコントロールよりも上にあるものは、ダイアログの上、下にあるものは下、左にあるものは左側、右にあるものは右側にそれぞれ追加されていきます。このコントロールのIDは本当はstc32(dlgs.hというファイルで定義されている)としないといけないのですが、ダイアログエディターでstc32とすると勝手に別の数を割り当ててしまってコンパイル時に警告が出てしまうので、直接数値を入力します。
スタティックコントロールを作ったらそれを中心にしてコントロールを追加します。今回は、ダイアログの下にボタン(ID=IDC_BUTTON1)を追加します。

esccd image

ボタンの上にある四角がスタティックコントロールです。
この場合、ボタンはスタティックコントロールの下に位置するので、ダイアログの下側に追加されます。

おわりに

今回は、ファイルオープンダイアログをカスタマイズましたが、他のコモンダイアログでも同じようにしてカスタマイズできます。


to sdk prev next