fc2ブログ

夕暮ログ

C#やJavascript、最近はAndroidなんかも好きなtinqのブログ。「夕暮れログ」

Windows7とC#でコモンダイアログを簡単に拡張する

ソフトなどを作っていると、ファイルを開くダイアログや保存ダイアログに独自の機能をくっつけたくなる場合がよくあります。
身近なところではメモ帳あたりです。

文字コードが選択できるようになっています。

しかし、同じことをC#でやろうとするとかなりの苦労を強いられます。
標準の機能は基本的に助けてくれないので、ほぼすべてをAPIを叩いて行うことになります。
その際にはフックやらダイアログテンプレートやらC#ではなかなかなじめない方々がずらっと揃い、C/C++でだいぶWinAPIに慣れている人でないと完成にはいたらないでしょう。
(かくいう私もWinAPI、とくにShellやダイアログの方面にはうといのでたぶん作れません。勉強したい。)

そこで使えるのがWindows API CodePackです。
これはWindows7のタスクバー、ジャンプリスト、その他もろもろをC#やVB.NETから操作できるようにするためのライブラリです。
マイクロソフトが無料で配っています。

残念ながらWindows7以降のみ対応ということになっています。XPの買い替えが進むことを期待したいですが、XPではどうにか代替機能を考えておきましょう・・・

使い方


Windows API Code Pack for Microsoft .NET Framework 概要のページのWindows API Code Pack for .NET Framework (英語)に行き、ダウンロードしてきます。
現在の最新版は1.1です。
適当な場所に解凍したら、VisualStudioのソリューションエクスプローラから参照の追加を行います。

解凍したフォルダのbinariesの中にいくつかDLLが入っています。使うものを選択して追加します。
コモンダイアログに必要なのは

  • Microsoft.WindowsAPICodePack.dll

  • Microsoft.WindowsAPICodePack.Shell.dll


の二つです。まとめて選択してOKを押します。


Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialogがファイルを開くダイアログです。
普通のOpenFileDialogとものすごく違うということはありませんが、大量の機能が追加されています。

自分の好きなコントロールを追加する場合、CommonOpenFileDialog#Controlsから行います。
なぜだかは知りませんが、普通のコントロールは追加できません。(たぶんAPIの仕様)
追加するコントロールはMicrosoft.WindowsAPICodePack.Dialogs.Controls名前空間のものを使います。
基本的に必要そうなものは使えるのであんまり困らないでしょう。場所は自動で調整されます。
ちなみに、画像のプレビューを追加したい!と思いかけますがそもそもこのダイアログには右上のツールバーボタンからプレビュー表示ができるので不要だったりします。

簡単なサンプルです。
文字コードを選択することができます。
/*
以下をファイルの先頭に追加してください。
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.WindowsAPICodePack.Dialogs.Controls;
*/

private void button1_Click(object sender, EventArgs e)
{
CommonOpenFileDialog open = new CommonOpenFileDialog();

//文字コードを選択するコンボボックス
CommonFileDialogComboBox charset = new CommonFileDialogComboBox();
//文字コード列挙
EncodingInfo[] encodes = Encoding.GetEncodings();
//デフォルトという項目追加
charset.Items.Add(new CommonFileDialogComboBoxItem("デフォルト"));
foreach (var item in Encoding.GetEncodings())
{
//エンコードの表示名を追加していく
charset.Items.Add(new CommonFileDialogComboBoxItem(item.DisplayName));
}
//「デフォルト」を選択
charset.SelectedIndex = 0;
//ダイアログに追加
open.Controls.Add(charset);

//表示。OKなら処理続行
if (open.ShowDialog() == CommonFileDialogResult.Ok)
{
//0ならデフォルト。それ以外なら列挙した文字コードが選択されている。
string moji = charset.SelectedIndex == 0 ? "デフォルト" : encodes[charset.SelectedIndex - 1].DisplayName;
//表示
MessageBox.Show( "選択されたファイルは" + open.FileName + "\n文字コードは" + moji + "です" );
}

}


このようになります。
むろん、こんなに文字コードを表示すると使いにくくてたまらないので、よく使うものだけ絞って表示することになりますが、サンプルなので。


ちなみに、使えるコントロールは以下です。詳細は解凍したフォルダのdocumentationの中のヘルプファイルをご覧ください。

private void button1_Click(object sender, EventArgs e)
{
CommonOpenFileDialog open = new CommonOpenFileDialog();
open.Controls.Add(new CommonFileDialogButton("Button"));
open.Controls.Add(new CommonFileDialogCheckBox("CheckBox"));
open.Controls.Add(new CommonFileDialogComboBox("CheckBox"));
CommonFileDialogGroupBox group = new CommonFileDialogGroupBox("GroupBox");
group.Items.Add(new CommonFileDialogCheckBox("Group's Item"));
open.Controls.Add(group);
open.Controls.Add(new CommonFileDialogLabel("Label"));
open.Controls.Add(new CommonFileDialogMenu("Menu"));
CommonFileDialogRadioButtonList radio = new CommonFileDialogRadioButtonList();
radio.Items.Add(new CommonFileDialogRadioButtonListItem("Rdaio1"));
radio.Items.Add(new CommonFileDialogRadioButtonListItem("Rdaio2"));
radio.Items.Add(new CommonFileDialogRadioButtonListItem("Rdaio3"));
open.Controls.Add(radio);
open.Controls.Add(new CommonFileDialogSeparator());
open.Controls.Add(new CommonFileDialogTextBox("TextBox"));
open.ShowDialog();
}



より細かく制御する


このダイアログにはほかにもいくつかの機能が追加されています。
左のプレースバーに好きな場所を追加したりするのは地味に便利。

さらに、開くフォルダを制限することなんかもできてしまいます。
フォルダを開こうとするとFolderChangingイベントが発生します。そのイベントソースのCancelをtrueにすることで移動をキャンセルすることができます。
移動しようとしたフォルダはFolderから取れます。
これによって、例えば「Program Filesの下のファイルのみ指定する」といったことができます。
といいたいところですが、油断してはいけません。ファイル名を絶対パスで入力することはできます。ですから、好きなファイルを指定することは容易です。あくまでインタフェースの問題で、ダイアログではどんなファイルが指定されるかはわからないと思わないと危険です。
たぶん、フックでひっかけて書き換えることも難しくはないでしょうし。ですので、セキュリティの問題にならないように注意してください。

さらに注意しないといけないのは、選択されるのがフォルダだけではないということです。
Windowsにはフォルダとは違う仕組みで管理がなされており、例えばコントロールパネルやライブラリフォルダなども表せるようになっています。
一般的に「PIDL」と呼ばれています。ファイルダイアログではそのGUIDをFolderとして渡してきます。C:\とかで始まらないので注意。

ちなみに、それらもShell.ShellFolderで扱うことができます。
サンプルです。フォルダの場合のみ開くことができます。
private void button1_Click(object sender, EventArgs e)
{
CommonOpenFileDialog open = new CommonOpenFileDialog();
open.FolderChanging += (_sender, _e) =>
{
if (!Microsoft.WindowsAPICodePack.Shell.ShellFolder.FromParsingName(_e.Folder).IsFileSystemObject)
{
_e.Cancel = true;
MessageBox.Show("ナビゲーションは拒否されました");
}
};
open.ShowDialog();
}



Windows API Codepackの例は田中さんのブログがおすすめです。
[TechEdポストセッション] Windows API Code Pack 連載一覧 - 田中達彦のブログ

関連記事

コメント

ここをクリックしてコメントを投稿

非公開コメント

トラックバック

http://tinqwill.blog59.fc2.com/tb.php/86-9ee5d635

« next  ホーム  prev »

プロフィール

tinq tinq(もしくはTinqWill)

Sky  For   Every 改装予定

プログラミングお勉強中の高校生。月一くらいは更新したい

最新記事

カテゴリ

月別アーカイブ

検索フォーム

最新コメント

リンク

最新トラックバック