←HSPハック トップへ

ファイルを開く/保存ダイアログをカスタマイズする

かっこいい多機能ダイアログにカスタマイズします。

最終更新:2017/11/14

初版:2017/11/14




はじめに


標準のファイルを開く/保存ダイアログをカスタマイズして、多機能にする方法を紹介します。

仕組みは、実行ファイルにダイアログリソースを追加して、GetOpenFileNameで一緒に表示してもらいます。
表示の仕方は2つあり、標準のダイアログに自作ダイアログをくっつけて表示する方法と、標準ダイアログの代わりに自作ダイアログを表示させるかがありますが、今回は前者の方を説明します。
Sample
※ちょくと氏のhscallbk.dllが必要です。

標準のダイアログを作る


 手を加えないといけないので、HSPの「dialog」命令は使えません。
なので難しくなりますが、GetOpenFileNameとGetSaveFileName命令を使います。

まずサンプルを見てください。
#include "user32.as"
#uselib "comdlg32.dll"
#func GetOpenFileName "GetOpenFileNameA" sptr
#func GetSaveFileName "GetSaveFileNameA" sptr
#define OFN_ALLOWMULTISELECT 0x00000200
#define OFN_CREATEPROMPT 0x00002000
#define OFN_DONTADDTORECENT 0x02000000
#define OFN_ENABLEHOOK 0x00000020
#define OFN_ENABLEINCLUDENOTIFY 0x00400000
#define OFN_ENABLESIZING 0x00800000
#define OFN_ENABLETEMPLATE 0x00000040
#define OFN_ENABLETEMPLATEHANDLE 0x00000080
#define OFN_EXPLORER 0x00080000
#define OFN_EXTENSIONDIFFERENT 0x00000400
#define OFN_EX_NOPLACESBAR 0x00000001
#define OFN_FILEMUSTEXIST 0x00001000
#define OFN_FORCESHOWHIDDEN 0x10000000
#define OFN_HIDEREADONLY 0x00000004
#define OFN_LONGNAMES 0x00200000
#define OFN_NOCHANGEDIR 0x00000008
#define OFN_NODEREFERENCELINKS 0x00100000
#define OFN_NOLONGNAMES 0x00040000
#define OFN_NONETWORKBUTTON 0x00020000
#define OFN_NOREADONLYRETURN 0x00008000
#define OFN_NOTESTFILECREATE 0x00010000
#define OFN_NOVALIDATE 0x00000100
#define OFN_OVERWRITEPROMPT 0x00000002
#define OFN_PATHMUSTEXIST 0x00000800
#define OFN_READONLY 0x00000001
#define OFN_SHAREAWARE 0x00004000
#define OFN_SHAREFALLTHROUGH 0x00000002
#define OFN_SHARENOWARN 0x00000001
#define OFN_SHAREWARN 0x00000000
#define OFN_SHOWHELP 0x00000010
#define WM_COMMAND 0x0111 
#define WM_GETTEXT 0x000D

    sdim lpstrFilter, 512
    
    //フィルター文字列を作成
        nFilterIndex=0
        lpstrFilter=""
        filter = "Text Document(*.txt;*.text)\n*.txt;*.text\nRich Text Format(*.rtf)\n*.rtf"
        i1=0:i2=0
        repeat
            getstr s, filter, i1
            if strsize==0:break
            i1+=strsize
            poke lpstrFilter, i2, s
            i2+=strsize+1
        loop
        
    lpstrInitialDir=dirinfo(0x10005)    //初期のディレクトリ
    lpstrTitle="標準のコモンダイアログ" //ダイアログのタイトル
    lpstrFile="*.txt"                   //初期のファイル名
    
    dim ofn, 19//OPENFILENAME構造体
    ofn(0) = 76                      //lStructSize
    ofn(1) = hwnd                    //hwndOwner
    ofn(2) = 0                       //hInstance
    ofn(3) = varptr(lpstrFilter)     //lpstrFilter
    ofn(6) = nFilterIndex            //nFilterIndex
    ofn(7) = varptr(lpstrFile)       //lpstrFile
    ofn(8) = 2048                    //nMaxFile
    ofn(11) = varptr(lpstrInitialDir)//lpstrInitialDir
    ofn(12) = varptr(lpstrTitle)     //lpstrTitle
    ofn(13) = OFN_ENABLESIZING|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_EXPLORER//Flags
    ofn(17) = 0                      //lpfnHook
    ofn(18) = 0                      //lpTemplateName
    GetOpenFileName varptr(ofn)//ファイルを開く
    
    getstr s, lpstrFile, 0//結果を抽出
    mes s
stop

OPENFILENAME構造体に必要な情報を格納していきます。
lStructSizeは、構造体のサイズで、76を必ず指定します。
hwndOwnerは、オーナーウィンドウのウィンドウハンドルです。
Flagsは、ダイアログの初期化に使われるフラグを指定します。

これを元にして、ダイアログをカスタマイズしていきます。

カスタマイズしたダイアログを作る


まずサンプルを見てください。
太字のところが重要なところです。
※このサンプルを実行する前にダイアログを含むリソースを用意しておいてください。
※実行ファイルにしてダイアログを含むリソースを埋め込まなければダイアログは表示されません。
#include "user32.as"
#uselib "comdlg32.dll"
#func GetOpenFileName "GetOpenFileNameA" sptr
#func GetSaveFileName "GetSaveFileNameA" sptr
#define OFN_ALLOWMULTISELECT 0x00000200
#define OFN_CREATEPROMPT 0x00002000
#define OFN_DONTADDTORECENT 0x02000000
#define OFN_ENABLEHOOK 0x00000020
#define OFN_ENABLEINCLUDENOTIFY 0x00400000
#define OFN_ENABLESIZING 0x00800000
#define OFN_ENABLETEMPLATE 0x00000040
#define OFN_ENABLETEMPLATEHANDLE 0x00000080
#define OFN_EXPLORER 0x00080000
#define OFN_EXTENSIONDIFFERENT 0x00000400
#define OFN_EX_NOPLACESBAR 0x00000001
#define OFN_FILEMUSTEXIST 0x00001000
#define OFN_FORCESHOWHIDDEN 0x10000000
#define OFN_HIDEREADONLY 0x00000004
#define OFN_LONGNAMES 0x00200000
#define OFN_NOCHANGEDIR 0x00000008
#define OFN_NODEREFERENCELINKS 0x00100000
#define OFN_NOLONGNAMES 0x00040000
#define OFN_NONETWORKBUTTON 0x00020000
#define OFN_NOREADONLYRETURN 0x00008000
#define OFN_NOTESTFILECREATE 0x00010000
#define OFN_NOVALIDATE 0x00000100
#define OFN_OVERWRITEPROMPT 0x00000002
#define OFN_PATHMUSTEXIST 0x00000800
#define OFN_READONLY 0x00000001
#define OFN_SHAREAWARE 0x00004000
#define OFN_SHAREFALLTHROUGH 0x00000002
#define OFN_SHARENOWARN 0x00000001
#define OFN_SHAREWARN 0x00000000
#define OFN_SHOWHELP 0x00000010
#define WM_COMMAND 0x0111
#define WM_GETTEXT 0x000D
#packopt runtime "runtime.hrt"
#include "hscallbk.as"
#uselib ""
#func _OFNHookProc "" int,int,int,int
setcallbk OFNHookProc,_OFNHookProc,*MyOFNHookProc
    sdim lpstrFilter, 512
    
    //フィルター文字列を作成
        nFilterIndex=0
        lpstrFilter=""
        filter = "Text Document(*.txt;*.text)\n*.txt;*.text\nRich Text Format(*.rtf)\n*.rtf"
        i1=0:i2=0
        repeat
            getstr s, filter, i1
            if strsize==0:break
            i1+=strsize
            poke lpstrFilter, i2, s
            i2+=strsize+1
        loop
        
    lpstrInitialDir=dirinfo(0x10005)    //初期のディレクトリ
    lpstrTitle="カスタマイズしたコモンダイアログ"//ダイアログのタイトル
    lpstrFile="*.txt"                   //初期のファイル名
    
    dim ofn, 19//OPENFILENAME構造体
    ofn(0) = 76                      //lStructSize
    ofn(1) = hwnd                    //hwndOwner
    ofn(2) = hinstance               //hInstance
    ofn(3) = varptr(lpstrFilter)     //lpstrFilter
    ofn(6) = nFilterIndex            //nFilterIndex
    ofn(7) = varptr(lpstrFile)       //lpstrFile
    ofn(8) = 2048                    //nMaxFile
    ofn(11) = varptr(lpstrInitialDir)//lpstrInitialDir
    ofn(12) = varptr(lpstrTitle)     //lpstrTitle
    ofn(13) = OFN_ENABLESIZING|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_EXPLORER|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE//Flags
    ofn(17) = varptr(OFNHookProc)    //lpfnHook
    ofn(18) = 1                      //lpTemplateName
    GetOpenFileName varptr(ofn)//ファイルを開く
    
    getstr s, lpstrFile, 0//結果を抽出
    mes s
stop
*MyOFNHookProc
    _hwnd=callbkarg(0)
    msg=callbkarg(1)
    wp=callbkarg(2)
    lp=callbkarg(3)
    switch msg
    swend
return 0

■解説

7 #packopt runtime "runtime.hrt"
実行ファイルにリソースを埋め込みます。 "runtime.hrt"のところにダイアログリソースを含むランタイムファイル名を指定します。

#func _OFNHookProc "" int,int,int,int
ウィンドウプロシージャのコールバックを登録するための定義です。

setcallbk OFNHookProc,_OFNHookProc,*MyOFNHookProc
ウィンドウプロシージャのコールバックを登録します。
これを登録することで、ダイアログからウィンドウメッセージを受け取ることが出来ます。

OPENFILENAME構造体のFlags
OFN_ENABLESIZING|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_EXPLORERに、OFN_ENABLEHOOK|OFN_ENABLETEMPLATEを加えることによって、独自にダイアログを追加できるようにしています。

■各フラグの説明 OFN_ENABLESIZING
 サイズを変更する事を有効にします

OFN_OVERWRITEPROMPT
 上書きをする可能性があることを報告させます。

OFN_HIDEREADONLY
 読み取り専用チェックボックスもしくはドロップダウンメニューを非表示にします。

OFN_FILEMUSTEXIST
 無効なファイルは開けないようにします。

OFN_EXPLORER
 共通のエクスプローラースタイルのダイアログを使います。

OFN_ENABLETEMPLATE
 リソース内のテンプレートダイアログを使うことを有効にします。

OFN_ENABLEHOOK
 フックプロシージャを使うことを有効にします。FlagsにOFN_EXPLORERを付けている時は独自に追加したダイアログから、付けていない時はファイルを開く/保存ダイアログからウィンドウメッセージが来ます。

OPENFILENAME構造体のlpfnHook
フックプロシージャへのアドレスを指定します。 FlagsにOFN_EXPLORERを付けている時は独自に追加したダイアログから、付けていない時はファイルを開く/保存ダイアログからウィンドウメッセージが来ます。
OFN_ENABLEHOOKフラグが立っているときに有効です。
OPENFILENAME構造体のlpTemplateName
ダイアログのもとになる、ダイアログリソースIDを指定します。
OFN_ENABLEHOOKフラグが立っているときに有効です。
hInstanceに、ダイアログリソースを含むモジュールのハンドルを指定する必要があります。

カスタマイズしたダイアログを作るためのリソースを作成する


 ファイルを開く/保存ダイアログにダイアログを貼り付けるためのリソースを作ります。
※「ResEdit」等のリソースエディタを用意しておいてください。

まず、HSPのエディタ等が入っているフォルダの中にある「hsprt」ファイルを「runtime」フォルダにコピーしてください。(上書き確認があった場合、別の名前でコピーしてください。)
そのコピーしたファイルの拡張子を[.exe]にしてから編集します。(編集が終わったら拡張子を[.hrt]にしてください。)

リソースID1のダイアログを作成し、そのダイアログのウィンドウスタイルを以下のように設定してください。
3DLookTRUE
BorderNone
Clip ChildrenTRUE
Clip SiblingTRUE
StyleChild
System MenuFALSE
Title BarFALSE

そのダイアログの中に、ID 1119のスタティックテキストを貼り付け、Captionを空にします。(コントロールのサイズが自動で変わる場合があるので、変わった時はは元の大きさに戻してください。)
そのスタティックテキストが、ファイルを開く/保存ダイアログの表示する時のコントロール配置の基礎になります。
スタティックテキストの上にあるものは、ファイルを開く/保存ダイアログの一番上に、下は一番下、左は一番左、右は一番右、とスタティックテキストを中心にそれぞれ自動的に配置されます。
なので、そこを意識してコントロールを配置すれば大丈夫です。




[前へ] [戻る] [次へ]

(C)2019 inonote / 無断転載禁止