PerlでWindowsのDialogを使う
2025/10/05
Dialogだけ使いたい
  • プロのソフトウェアエンジニアではない場合、作成する多くのツール類はCUIで十分です。むしろ自動化等に活用する場合、GUIではなくCUIが必須です。

  • ではありますが、ツールの起点と言うか、入力データの選択はエクスプローラ的なDialogを使えたほうが便利なのは間違いありません。なので今回は「PerlからWindowsのDialogだけ使う方法」を調べてみました。(*1)

  • PerlでWindowsの共通Dialogを使用するには、Win32::GUIのインストールが必要です(標準モジュールではありません)。Strawberry Perlならば下記でインストールできます。
  • >cpan Win32::GUI
    

使いたいDialogは3種類
  • エクスプローラ風のDialogを使いたいケースは下記の3種類かと思います。
    • 入力ファイルを選ぶ(単数 or 複数)
    • 出力ファイル名を決める(新規 or 上書き)
    • 処理対象フォルダを選ぶ

  • Win32::GUIには、それぞれのケースに向いたDialogを利用するメソッドがあります。

GetOpenFileName()
  • 最初は入力ファイルを選択するGetOpenFileName()です。下記が使用例のコードです。9行目の`cd`に違和感あると思いますが、Windowsで引数無しのcdコマンドはカレントディレクトリの取得になります(*2)
  • #!perl -w
    use utf8; # スクリプト文字コードはutf8想定
    use Encode;
    use Win32::GUI;
    use strict;
    
    {
      # Openダイアログの初期ディレクトリ指定
        my $ini_dir_cp = `cd`; # Windowsディレクトリ名はcp932
        
      # Openダイアログでファイルリスト取得(@files_cpはcp932で戻る))
        my @files_cp = Win32::GUI::GetOpenFileName (
          # ダイアログタイトル(cp932)
            -title  => u8_cp('ファイル選択'),
          # ディレクトリ指定(cp932)
            -directory => $ini_dir_cp,
          # 複数ファイル選択Enable
            -multisel => 1,
          # 表示ファイルのフィルタ設定
            -filter => [
                         u8_cp('全て(*.*)')   =>'*.*',
                         u8_cp('zip(*.zip)')  =>'*.zip',
                         u8_cp('html(*.htm*)')=>'*.htm*'
                       ]
        );
        
      # ファイルリストを表示
        if (defined($files_cp[0])) {
            foreach my $file_cp (@files_cp) { print "[$file_cp]\n" }
        } else {
            print u8_cp("ファイル未選択.\n");
        }
    }
    
    # utf8→cp932変換
    sub u8_cp { return Encode::encode('cp932', join('',@_)) }
    # cp932→utf8変換
    sub cp_u8 { return Encode::decode('cp932', join('',@_)) }
    
  • 下記のようなDialogが表示されます。

  • Figure 1: GetOpenFileName() (クリックで拡大)

  • 注意点としては、Windowsの機能なので、データの受け渡しは、cp932(shift-jis)文字コードになります。

  • 単一ファイルを選択したときは、戻り値 $files_cp[0] にフルパスのファイル名が入ります。複数ファイルを選んだ際は、$files_cp[0] がフォルダパス、$files_cp[1]以降がファイル名です。

  • 下記が関数の引数/オプションになります。ドキュメントがフラットな構成のため抜粋しました。目がチカチカすると思いますが、今はブラウザの翻訳が使えるので安心ですね。-ownerが「所有者」に翻訳されるのは御愛嬌ということで。
  •  -owner => WINDOW
         Identifies the window that owns the dialog box.
     -title => STRING
         The title for the dialog
     -directory => STRING
         Specifies the initial directory
     -file => STRING
         Specifies a name that will appear on the dialog's edit field
     -filter => ARRAY REFERENCE
         Specifies an array containing pairs of filter strings.
         The first string in each pair is a display string that describes the filter
         (for example, "Text Files"), and the second string specifies the filter pattern
         (for example, "*.TXT"). To specify multiple filter patterns for a single display
         string, use a semicolon to separate the patterns (for example, "*.TXT;*.DOC;*.BAK").
         A pattern string can be a combination of valid filename characters and the
         asterisk (*) wildcard character. Do not include spaces in the pattern string.
     -defaultextension => STRING
         Contains the default extension. GetOpenFileName append this extension to the
         filename if the user fails to type an extension. This string can be any length,
         but only the first three characters are appended. The string should not contain a
         period (.).
     -defaultfilter => NUMBER
         Specifies the index of the currently selected filter in the File Types control.
         The first pair of strings has an index value of 0, the second pair 1, and so on.
     -createprompt => 0/1 (default 0)
         If the user specifies a file that does not exist, this flag causes the dialog box
         to prompt the user for permission to create the file. If the user chooses to create
         the file, the dialog box closes and the function returns the specified name; otherwise,
         the dialog box remains open. If you use this flag with the -multisel flag, the dialog
         box allows the user to specify only one nonexistent file.
     -multisel => 0/1 (default 0)
         Allow multiple file selection
         If the user selects more than one file then return filename with full path.
         If the user selects more than one file then return an array with the path
         to the current directory followed by the filenames of the selected files.
     -explorer => 0/1 (default 1)
         Explorer look.
     -extensiondifferent => 0/1 (default 0)
         Specifies that the user can typed a filename extension that differs from the extension
         specified by -defaultextension.
     -filemustexist => 0/1 (default 0)
         Specifies that the user can type only names of existing files in the File Name entry
         field. If this flag is specified and the user enters an invalid name, the dialog box
         procedure displays a warning in a message box.
     -hidereadonly => 0/1 (default 1)
         Hides the Read Only check box. If -hidereadonly is set to 0, the read only status is
         return only in array context as last value.
     -nochangedir => 0/1 (default 0)
         Restores the current directory to its original value if the user changed the directory
         while searching for files.
     -nodeferencelinks => 0/1 (default 0)
         Directs the dialog box to return the path and filename of the selected
         shortcut (.LNK) file. If this value is not given, the dialog box returns the
         path and filename of the file referenced by the shortcut.
     -nonetwork  => 0/1 (default 0)
         Hides and disables the Network button
     -noreadonlyreturn => 0/1 (default 0)
         Specifies that the returned file does not have the Read Only check box checked and is
         not in a write-protected directory.
     -pathmustexist => 0/1 (default 0)
         Specifies that the user can type only valid paths and filenames.
         If this flag is used and the user types an invalid path and filename in the File Name
         entry field, the dialog box function displays a warning in a message box.
     -readonly => 0/1 (default 0)
         Causes the Read Only check box to be checked initially when the dialog box is created.
    

GetSaveFileName()
  • 次は保存ファイル名を決めるDialogです。既存ファイル名を指定すると上書き確認のDialogを出してくれます。
  • #!perl -w
    use utf8; # スクリプト文字コードはutf8想定
    use Encode;
    use Win32::GUI;
    use strict;
    
    {
      # Saveダイアログの初期ディレクトリ指定
        my $ini_dir_cp = `cd`; # Windowsディレクトリ名はcp932
        
      # Saveダイアログでファイル名取得($file_cpはcp932で戻る)
        my $file_cp = Win32::GUI::GetSaveFileName (
          # ダイアログタイトル(cp932)
            -title  => u8_cp('保存ファイル名入力'),
          # ディレクトリ指定(cp932)
            -directory => $ini_dir_cp,
          # 表示ファイルのフィルタ設定
            -filter => [
                         u8_cp('全て(*.*)')    =>'*.*',
                         u8_cp('テキスト(*.txt)') =>'*.txt',
                         u8_cp('zip(*.zip)')  =>'*.zip'
                       ],
           # ファイル名のみ入力時の拡張子
             -defaultextension => 'txt'
        );
        
      # ファイル名を表示
        if (defined($file_cp)) {
            print "[$file_cp]\n";
        } else {
            print u8_cp("ファイル未決定.\n");
        }
    }
    
    # utf8→cp932変換
    sub u8_cp { return Encode::encode('cp932', join('',@_)) }
    # cp932→utf8変換
    sub cp_u8 { return Encode::decode('cp932', join('',@_)) }
    
  • 下記のようなDialogが表示されます。

  • Figure 2: GetSaveFileName() (クリックで拡大)

  • 下記が関数の引数/オプションになります。ドキュメントからの抜粋です。
  •  -owner => WINDOW
         Identifies the window that owns the dialog box.
     -title => STRING
         The title for the dialog
     -directory => STRING
         Specifies the initial directory
     -file => STRING
         Specifies a name that will appear on the dialog's edit field
     -filter => ARRAY REFERENCE
         Specifies an array containing pairs of filter strings.
         The first string in each pair is a display string that describes the filter
         (for example, "Text Files"), and the second string specifies the filter pattern
         (for example, "*.TXT"). To specify multiple filter patterns for a single display
         string, use a semicolon to separate the patterns (for example, "*.TXT;*.DOC;*.BAK").
         A pattern string can be a combination of valid filename characters and the asterisk (*)
         wildcard character. Do not include spaces in the pattern string.
     -defaultextension => STRING
         Contains the default extension. GetSaveFileName append this extension to the filename if the user
         fails to type an extension. This string can be any length, but only the first three characters are
         appended. The string should not contain a period (.).
     -defaultfilter => NUMBER
         Specifies the index of the currently selected filter in the File Types control.
         The first pair of strings has an index value of 0, the second pair 1, and so on.
     -createprompt => 0/1 (default 0)
         If the user specifies a file that does not exist, this flag causes the dialog box to prompt
         the user for permission to create the file. If the user chooses to create the file, the dialog box
         closes and the function returns the specified name; otherwise, the dialog box remains open.
         If you use this flag with the -multisel flag, the dialog box allows the user to specify
         only one nonexistent file.
     -explorer => 0/1 (default 1)
         Explorer look.
     -extensiondifferent => 0/1 (default 0)
         Specifies that the user can typed a filename extension that differs from the extension
         specified by -defaultextension.
     -filemustexist => 0/1 (default 0)
         Specifies that the user can type only names of existing files in the File Name entry field.
         If this flag is specified and the user enters an invalid name, the dialog box procedure displays
         a warning in a message box.
     -nochangedir => 0/1 (default 0)
         Restores the current directory to its original value if the user changed the directory
         while searching for files.
     -nodeferencelinks => 0/1 (default 0)
         Directs the dialog box to return the path and filename of the selected shortcut (.LNK) file.
         If this value is not given, the dialog box returns the path and filename of the file
         referenced by the shortcut.
     -nonetwork  => 0/1 (default 0)
         Hides and disables the Network button
     -noreadonlyreturn => 0/1 (default 0)
         Specifies that the returned file is not in a write-protected directory.
     -pathmustexist => 0/1 (default 1)
         Specifies that the user can type only valid paths and filenames.
         If this flag is used and the user types an invalid path and filename in the File Name
         entry field, the dialog box function displays a warning in a message box.
     -overwriteprompt => 0/1 (default 1)
         Generate a message box if the selected file already exists. The user must confirm8
         whether to overwrite the file.
    

BrowseForFolder()
  • 最後はフォルダの選択です。下記が使用例コードになります。
  • #!perl -w
    use utf8; # スクリプト文字コードはutf8想定
    use Encode;
    use Win32::GUI;
    use Win32::GUI qw(CSIDL_PERSONAL); # カレントユーザーのドキュメントフォルダ
    use strict;
    
    {
      # Saveダイアログの初期ディレクトリ指定
        my $ini_dir_cp = `cd`; # Windowsディレクトリ名はcp932
        
      # Browseダイアログでフォルダ名取得($file_cpはcp932で戻る)
        my $folder_cp = Win32::GUI::BrowseForFolder (
          # 初期フォルダ指定
            -directory => $ini_dir_cp,,
          # ダイアログに表示するタイトル(バーではなくWindowの上部)
            -title => u8_cp('出力フォルダの選択'),
          # ダイアログのrootディレクトリ指定(コンスタントはuseで引き出して使う)
            -root => CSIDL_PERSONAL,
          # フォルダ名を直接入力するフィールド表示
            -editbox => 1,
          # フォルダのみ選択を許す
            -folderonly => 1
        );
        
      # 選択フォルダ名を表示
        if (defined($folder_cp)) {
            print "[$folder_cp]\n";
        } else {
            print u8_cp("フォルダ未決定.\n");
        }
    }
    
    # utf8→cp932変換
    sub u8_cp { return Encode::encode('cp932', join('',@_)) }
    # cp932→utf8変換
    sub cp_u8 { return Encode::decode('cp932', join('',@_)) }
    
  • 下記のようなDialogが表示されます。

  • Figure 3: BrowseForFolder() (クリックで拡大)

  • Dialogのルートディレクトリには、-root オプションでCSIDL_PERSONAL(現ユーザのDocumentフォルダ) を設定しています。これはコード5行目のuse文で使用を宣言しています(つまりオンデマンド)。
  • use Win32::GUI qw(CSIDL_PERSONAL); # カレントユーザーのドキュメントフォルダ
    
  • 下記が関数の引数/オプションになります。ドキュメントからの抜粋です。
  •  -title => STRING
         the title for the dialog
     -computeronly => 0/1 (default 0)
         only enable computers to be selected
     -domainonly => 0/1 (default 0)
         only enable computers in the current domain or workgroup
     -driveonly => 0/1 (default 0)
         only enable drives to be selected
     -editbox => 0/1 (default 0)
         if 1, the dialog will include an edit field in which
         the user can type the name of an item
     -folderonly => 0/1 (default 0)
         only enable folders to be selected
     -includefiles => 0/1 (default 0)
         the list will include files as well folders
     -owner => WINDOW
         A Win32::GUI::Window or Win32::GUI::DialogBox object specifiying the
         owner window for the dialog box
     -printeronly => 0/1 (default 0)
         only enable printers to be selected
     -directory => PATH
         the default start directory for browsing
     -root => PATH or CONSTANT
         the root directory for browsing; this can be either a
         path or one of the following constants (minimum operating systems or
         Internet Explorer versions that support the constant are shown in
         square brackets. NT denotes Windows NT 4.0, Windows 2000, XP, etc.):
    
  • -root オプションで指定するCONSTANTには下記があります。サンプルのCSIDL_PERSONALのように宣言して使います。
  •       CSIDL_FLAG_CREATE (0x8000)
              [2000/ME] Combining this with any of the constants below
              will create the folder if it does not already exist.
          CSIDL_ADMINTOOLS (0x0030)
              [2000/ME] Administrative Tools directory for current user
          CSIDL_ALTSTARTUP (0x001d)
              [All] Non-localized Startup directory in the Start menu for current user
          CSIDL_APPDATA (0x001a)
              [IE4] Application data directory for current user
          CSIDL_BITBUCKET (0x000a)
              [All] Recycle Bin
          CSIDL_CDBURN_AREA (0x003b)
              [XP] Windows XP directory for files that will be burned to CD
          CSIDL_COMMON_ADMINTOOLS (0x002f)
              [2000/ME] Administrative Tools directory for all users
          CSIDL_COMMON_ALTSTARTUP (0x001e)
              [All] Non-localized Startup directory in the Start menu for all users
          CSIDL_COMMON_APPDATA (0x0023)
              [2000/ME] Application data directory for all users
          CSIDL_COMMON_DESKTOPDIRECTORY (0x0019)
              [NT] Desktop directory for all users
          CSIDL_COMMON_DOCUMENTS (0x002e)
              [IE4] My Documents directory for all users
          CSIDL_COMMON_FAVORITES (0x001f)
              [NT] Favorites directory for all users
          CSIDL_COMMON_MUSIC (0x0035)
              [XP] Music directory for all users
          CSIDL_COMMON_PICTURES (0x0036)
              [XP] Image directory for all users
          CSIDL_COMMON_PROGRAMS (0x0017)
              [NT] Start menu "Programs" directory for all users
          CSIDL_COMMON_STARTMENU (0x0016)
              [NT] Start menu root directory for all users
          CSIDL_COMMON_STARTUP (0x0018)
              [NT] Start menu Startup directory for all users
          CSIDL_COMMON_TEMPLATES (0x002d)
              [NT] Document templates directory for all users
          CSIDL_COMMON_VIDEO (0x0037)
              [XP] Video directory for all users
          CSIDL_CONTROLS (0x0003)
              [All] Control Panel applets
          CSIDL_COOKIES (0x0021)
              [All] Cookies directory
          CSIDL_DESKTOP (0x0000)
              [All] Namespace root
              (shown as "Desktop", but is parent to my computer, control panel, my documents, etc.)
          CSIDL_DESKTOPDIRECTORY (0x0010)
              [All] Desktop directory (for desktop icons, folders, etc.) for the current user
          CSIDL_DRIVES (0x0011)
              [All] My Computer (drives and mapped network drives)
          CSIDL_FAVORITES (0x0006)
              [All] Favorites directory for the current user
          CSIDL_FONTS (0x0014)
              [All] Fonts directory
          CSIDL_HISTORY (0x0022)
              [All] Internet Explorer history items for the current user
          CSIDL_INTERNET (0x0001)
              [All] Internet root
          CSIDL_INTERNET_CACHE (0x0020)
              [IE4] Temporary Internet Files directory for the current user
          CSIDL_LOCAL_APPDATA (0x001c)
              [2000/ME] Local (non-roaming) application data directory for the current user
          CSIDL_MYMUSIC (0x000d)
              [All] My Music directory for the current user
          CSIDL_MYPICTURES (0x0027)
              [2000/ME] Image directory for the current user
          CSIDL_MYVIDEO (0x000e)
              [XP] Video directory for the current user
          CSIDL_NETHOOD (0x0013)
              [All] My Network Places directory for the current user
          CSIDL_NETWORK (0x0012)
              [All] Root of network namespace (Network Neighbourhood)
          CSIDL_PERSONAL (0x0005)
              [All] My Documents directory for the current user
          CSIDL_PRINTERS (0x0004)
              [All] List of installed printers
          CSIDL_PRINTHOOD (0x001b)
              [All] Network printers directory for the current user
          CSIDL_PROFILE (0x0028)
              [2000/ME] The current user's profile directory
          CSIDL_PROFILES (0x003e)
              [XP] The directory that holds user profiles (see CSDIL_PROFILE)
          CSIDL_PROGRAM_FILES (0x0026)
              [2000/ME] Program Files directory
          CSIDL_PROGRAM_FILES_COMMON (0x002b)
              [2000] Directory for files that are used by several applications.
              Usually Program Files\Common
          CSIDL_PROGRAMS (0x0002)
              [All] Start menu "Programs" directory for the current user
          CSIDL_RECENT (0x0008)
              [All] Recent Documents directory for the current user
          CSIDL_SENDTO (0x0009)
              [All] "Send To" directory for the current user
          CSIDL_STARTMENU (0x000b)
              [All] Start Menu root for the current user
          CSIDL_STARTUP (0x0007)
              [All] Start Menu "Startup" folder for the current user
          CSIDL_SYSTEM (0x0025)
              [2000/ME] System directory. Usually \Windows\System32
          CSIDL_TEMPLATES (0x0015)
              [All] Document templates directory for the current user
          CSIDL_WINDOWS (0x0024)
              [2000/ME] Windows root directory, can also be accessed
              via the environment variables %windir% or %SYSTEMROOT%.
    

出力のGUI表示はstartコマンドでいける
  • ここまで入力だけGUI化として、Windowsの共通Dialogを使う話をしてきました。次は作ったファイルの内容を表示...画面出力したい場合ですが、よほど珍しいタイプのファイルでなければ、system関数で「作成したファイル名」をコマンドとして実行すれば良いです。するとファイルの拡張子に関連したアプリで開きます。

  • 例えば system("hoge.html"); ならば、拡張子htmlに関連付けされたブラウザが立ち上がります。

  • 通常system関数は起動したプロセスの終了を待ちますが、表示に使用したGUIアプリと作成ツールの実行プロセスを別にしたい場合、system関数でのコマンド記述時にstartを利用します(例: system("start hoge.html");)。
Notes
  • Dialogがアメリカ、Dialogueがイギリス系みたいです。ソフト用語ならアメリカ系採用です。
  • Cwd::cwdを使うと、階層文字を'/'から'\'へ変更する手間があります。
Copyright(C) 2025 Altmo
本HPについて