hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
小ワザ/ファイル保存ダイアログ - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

ファイル入出力|ファイル選択ダイアログ

HSP2.61

ファイル保存ダイアログ

ファイル選択ダイアログと説明の重なるものは説明を省いていますので、ファイル選択ダイアログも合わせて読むことをすすめます。 -- kz3

ファイル保存ダイアログを出すにはdialog命令を使います。
書式は以下のようになっています。

dialog "extension" , style , "type"
extension : 拡張子を表す文字列を指定します。
            ここに指定した拡張子のファイルがダイアログボックスに表示されます。
style     : ダイアログのスタイルを指定します。
            16でファイル選択ダイアログ、17でファイル保存ダイアログを表示します。
type      : extensionに対するファイルの種類を表す名前を指定します。
            ここに指定した名前が[ファイルの種類]コンボボックスに反映します。

では実際の使用例を示します。

  1
  2
  3
  4
  5
  6
 
 
 
 
 
 
     ; < HSP2.61 > <HSP3.0a>
    dialog "as" , 17 , "えいちえすぴいすくりぷと"
 
    if stat = 0 : end
    mes refstr
    stop

ファイル選択ダイアログと違うのはダイアログのファイル名に"extension"で指定した拡張子のワイルドカードを付加した文字列が設定されていることです。

これだけでも保存するファイル名の取得はできますがこの後に説明するいろいろな要求をかなえるためにはWin32APIのGetSaveFileName?()関数を使います。

選択可能な拡張子を増やす

説明はファイル選択ダイアログを参照してください。

  1
  2
  3
  4
  5
  6
 
 
 
 
 
 
    ; < HSP2.61 > < HSP3.0a>
    dialog "bmp;*.mag;*.jpg" , 17 , "画像ファイル"
    if stat = 0 : end
    title refstr
    picload refstr
    stop

保存名にユーザーデフォルトを用いる

HSP標準命令であるdialogを使った場合は"extension"に指定した文字列にワイルドカードを付加したものがデフォルトの保存名に設定される、というのは最初に説明しました。
ではこれをユーザーが任意に設定することは出来ないのでしょうか?
dialogを用いた場合は出来ません。これを解決するには直接dialogが呼び出しているWin32APIをプログラマが呼び出します。
ファイル保存ダイアログを用いて保存するファイル名を作成するにはGetSaveFileName?()関数を使います。(例によって関数のリファレンスはちょくとさんのところにあるので参照してください。)
ここではAPIの説明は省き、実際に呼び出してみることにします。APIの呼び出しにはllmodを使用しています。(省スペースのため、ファイル選択ダイアログの「選択可能なファイルの種類を増やす」と「デフォルト拡張子」も同時実装しています。)

filev2api_GetSFN[sp].as
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
!
 
 
 
 
    ; <HSP2.61>
    #include "llmod.as"
 
    #define BUFSIZE     260
    #define FILTERSIZE  512
 
    #define ALLTYPE     "ALL files (*.*)@*.*@"
    #define PICTURE     "画像ファイル (*.bmp;*.mag;*.jpg)@*.bmp;*.mag;*.jpg@"
    #define SOUND       "音楽ファイル (*.mid;*.mp3;*.wav)@*.mid;*.mp3;*.wav@"
    #define DOCUMENT    "文書ファイル (*.txt)@*.txt@"
 
    #define DEFSAVENAME exedir + "\\default.as"
 
    #define OFN_FILEMUSTEXIST   $00001000
    #define OFN_OVERWRITEPROMPT $00000002
 
    mref bmscr , 67
 
//  OEPNFILENAME構造体のサイズはバージョンによって小さくしなくても
//  Windows2000/XPに合わせても大丈夫かな?
//  大丈夫じゃないときは76バイトになるようにサイズ調整(19)
    dim  ofn          , 22
 
    sdim aplFilter    , FILTERSIZE+1
    sdim CustFilter   , FILTERSIZE+1
    sdim filepath     , BUFSIZE+1
    sdim filename     , BUFSIZE+1
    sdim DefExtension , BUFSIZE+1
 
    aplFilter   = PICTURE + SOUND + DOCUMENT
    CustFilter  = ALLTYPE
 
    // デフォルト拡張子にピリオドはいりません
    // hirokiさんに教えてもらいました。
    DefExtension = "dat"
 
    repeat
        await 0
        instr mutch , aplFilter , "@" , start
        if mutch = -1 : break
        poke aplFilter , start + mutch , $00
        start += mutch + 1
    loop
    start = 0
    repeat
        await 0
        instr mutch  ,CustFilter , "@" , start
        if mutch = -1 : break
        poke CustFilter , start + mutch , $00
        start += mutch + 1
    loop
 
//      Windows2000/XP
        ofn.0   = 88                ; lStructSize
 
//      Windows95,98,NT
//      ofn.0   = 76
 
        ofn.1   = bmscr.13          ; hwndOwner
        ofn.2   = bmscr.14          ; hInstance
getptr  ofn.3   , aplFilter         ; lpstrFilter
getptr  ofn.4   , CustFilter        ; lpstrCustomFilter
        ofn.5   = FILTERSIZE        ; nMaxCustFilter
        ofn.6   = 1                 ; nFilterIndex
getptr  ofn.7   , filepath          ; lpstrFile
        ofn.8   = BUFSIZE           ; nMaxFile
getptr  ofn.9   , filename          ; lpstrFileTitle
        ofn.10  = BUFSIZE           ; nMaxFileTitle
        ofn.11  = 0                 ; lpstrInitialDir
        ofn.12  = 0                 ; lpstrTitle
        ofn.13  = OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT
                                    ; Flags
    ;   ofn.14                      ; nFileOffset , nFileExtension
getptr  ofn.15  , DefExtension      ; lpstrDefExt
 
        filepath = DEFSAVENAME
 
getptr  prm     , ofn
 
    dllproc "GetSaveFileNameA" , prm , 1 , D_COMDLG
    if dllret = 0{
        dialog "失敗" , 0 , "終了確認" : end
    }
 
    title filepath
 
    stop

設定した保存名はlpstrFileメンバに指定したバッファに入ります(ファイル選択ダイアログも同様)が、ファイル保存ダイアログの[ファイル名]入力ボックスに設定される文字列はこのlpstrFileメンバに指定したパスのファイル名が設定されるのです。
つまりGetSaveFileName?()を呼び出す前に毎回デフォルトのファイル名(フルパス)で初期化すれば毎回デフォルトが入力されている状態になるという事です。

ここで注目して欲しいのはデフォルトを指定したとき、そのフルパスの示すフォルダの中が開かれているということです。
これは初期表示ディレクトリを指定した、と考える人もいると思います。
ということは?lpstrFileメンバに指定するバッファが・・・

filepath = "c:\windows\"

というディレクトリ名までなら[ファイル名]は空白で表示フォルダはwindowsフォルダなんじゃ・・・と思われるかも知れません(僕がこれを書いていて思いました。)がこれはエラーになります。
また存在しないディレクトリを含むフルパスを指定した場合は、そのままフルパス文字列が[ファイル名]に設定されています。
この辺りは実際にやってみるとどうなるかわかると思いますが、いずれも任意のディレクトリを開くとは違います・・・。

他にも注目したい点があります。
保存するファイル名に拡張子を指定しなかった場合はどうなるでしょうか?
この場合は現在選択されている[ファイルの種類]の拡張子のリストの最初のものが選ばれて連結されます。
では「すべてのファイル (*.*)」なんて場合はどうなるでしょう?
通常は拡張子のないファイル名が返されるだけですが、拡張子を省略した場合のデフォルトの拡張子もOPENFILENAME構造体で設定できます。

それがlpstrDefExt?メンバです。このメンバが示すバッファに拡張子を設定しておきます。

バッファへのポインタとバッファのサイズ:
関数や構造体のメンバのなかにはバッファへのポインタとバッファのサイズを指定するものと指定しないものとがあったりします。
この違いは何でしょう?
OPENFILENAME構造体ではlpstrFileメンバとnMaxFile?メンバ、lpstrFileTitle?メンバとnMaxFileTitle?がポインタとバッファサイズが対応していて、lpstrDefExt?メンバにはバッファサイズのメンバがありません。

これは関数が外部(関数外)から渡された(文字列)領域に対して書き込むか、それとも読み取るだけかの違いです。
文字列についてはヌル文字で終わるというルールがあるので(文字列を)読み取る処理はヌル文字だけを注意して領域のサイズは注意しなくていいのでサイズがいらないのです。
一方(文字列を)書き込む場合はオーバーフローしてはいけないので領域のサイズに注意しながら書き込む、場合によっては書込み領域のサイズよりも書き込むデータが大きい場合は書き込めませんというエラーを出します。

処理内容が書込みなのか読み取りなのか、これが分かるだけでも少し安心してスクリプトを書けますね?

任意のディレクトリを初期表示する

OPENFILENAME構造体のサイズについて

本家BBS.HSP3よりさくらさんからご指摘いただきましたのでさっそく補足。
OPENFILENAME構造体の最初のメンバlStructSize?はこの構造体のサイズを指定するものですが、OSによって指定するサイズが異なります。

  • Windows 2000/XPではメンバ数は23個で構造体サイズは88
  • それ以前ではメンバ数は20個で構造体サイズは76 を指定するとのこと。(ちょくとさんのページを参照しました。勉強不足でした。)

コメント

  • 書き途中なのでファイル選択ダイアログから貼り付けたままの説明があります。 -- kz3 2005-10-04 10:49:22 (火)
  • 余談・補足をコラム風に・・・。 -- kz3 2005-10-04 12:35:28 (火)
  • hsp2.61用とhsp3.0a用のスクリプトを載せました。 -- kz3 2005-10-08 10:35:26 (土)
  • すみません、hsp2.61雛形に修正漏れがありました。usrFilter -> CustFilter?です;;直しておきました;; -- kz3 2005-10-09 11:03:51 (日)
  • ページ内のスクリプトで変数名を一貫してないのはお許しください。まぁUPしなおせばいいだけなのですが・・・。今度追加するときについでにやっておこうと思ってます。 -- kz3 2005-10-09 11:38:14 (日)
  • HSP3に移植するときの注意。HSP3では文字列の代入でバッファの拡張が必要になったときに自動でバッファを再確保します。この時、元のアドレスとは違うメモリアドレスに領域が確保されるのでアドレスが変化します。
    OPENFILENAME構造体の初期化あとに、フィルタ文字列に対してバッファを拡張させるような操作をした場合━━━
    例えばユーザーがフィルタ文字列をカスタマイズできるシステムを用意して一時バッファに格納させ、アプリケーション側で用意したバッファに代入させた時など
    ━━━は再度OPENFILENAME構造体のポインタを格納しているメンバを正しく設定しなおす必要がでてきます。 -- kz3 2005-10-09 12:53:21 (日)
  • hirokiさんが無事解決することを願って、ダイアログ関係のスクリプトにOSの記述を付加していく予定です。改めてちょくとさん、さくらさんありがとうございます。
    自分の未熟さを痛感! -- kz3 2005-10-09 14:33:37 (日)
  • そもそもこのXP/2000に拡張されたメンバが意味するのはプレースバーの有無です。(今のところ。)こんなものなくても、対して困りません。(本音)76でも困らないんです!! -- kz3 2005-10-09 14:49:22 (日)
  • defext = ".dat" のところのピリオドは必要ないようです。ピリオドが2つ付いてしまう。 -- hiroki? 2005-10-10 08:47:28 (月)
  • お、そうなんですか!ありがとうございます! -- kz3 2005-10-10 11:42:10 (月)
  • あはっ本当だ(//ー//) -- kz3 2005-10-10 11:43:19 (月)
  • usrFilter -> CustFilter? , defext -> DefExtension? , コメントいろいろ付加版UP。
    全てのスクリプトで変数名の統一は大変なので中止・・・。まぁサンプルから加工するときは自分の好きな名前に変えられるしね^^; -- kz3 2005-10-10 12:04:36 (月)
  • ・・・っていうか構造体76バイトにしてもプレースバーが出る。汗。 -- kz3 2005-10-10 12:06:23 (月)
  • filename filepath どう違うの? こっち ofn.9 =0 にしてる -- hiroki? 2005-10-10 14:08:04 (月)
  • filepathはフルパスで、filename(lpstrFileTitle?メンバ)はファイル名だけが入ります。 -- kz3 2005-10-10 14:45:24 (月)
  • つまりこれをやっとくとgetpathなどでファイル名を切り出さなくてもいいってことですね。 -- kz3 2005-10-10 14:46:21 (月)
  • 納得しました。#deffuncで新規命令作ってますか、合っている所で文法エラーになって困ってます。 -- hiroki? 2005-10-10 16:38:25 (月)
  • #deffunc の外で#funcを定義したから文法エラーになったことが判明しました。 -- hiroki? 2005-10-10 17:12:47 (月)
  • スクリプトを終わらさずにfilepathにファイルを指定してGetSaveFileNameAを実行するとデフォルト拡張子にならず、filepathの拡張子になってしまう -- hiroki? 2005-10-10 18:01:01 (月)
  • それは恐らく[ファイルの種類]が何か拡張子を持つようになっていませんか?デフォルトが効くのは「*.*」の拡張子の特定できない場合に拡張子を省略したときです。 -- kz3 2005-10-10 21:44:45 (月)
  • そうでした ごめんなさい。 -- hiroki? 2005-10-11 07:50:21 (火)

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2007-04-08 (日) 02:47:53 (2436d)