大晦日なので画像ビューワーを作りましょう(核爆)(錯乱)
完成するとこんな感じになります。
圧縮ファイルの中身を自動展開します。
今回のプロジェクトはこちら。
github.com
※「Windowsフォーム」は技術的に古い、みたいな話がネット上に散見されます。
本当に「Windowsフォームで作成すべきか」は一度検討してみてもよいと思います。
事前準備と画面の説明
開発環境は「Win10、Visual Studio 2017」です。
Visual Studioのインストール方法は割愛します。
プロジェクトを作成する
Visual Studioを開いて、右上の「ファイル」→「新規作成」→「プロジェクト」
でプロジェクト作成します。
今回は「Windows フォーム アプリケーション」を選択します。
フォルダを開くためにNugetからダウンロード
今回やることに必要なパッケージをNuGetからDLします。
今回使うのは下記のパッケージです。
(2017になって微妙にUIが変更されててビビった)
迷ったらDL数が多いものを選んでおけばよいのではないでしょうか。
画面の説明
- 各ウインドウの位置は人によって違うと思います
- ツールボックスが表示されていない人は上バーの「表示」から表示できます。
ここで覚えておいてほしいのは
ですです。
デザイナー上でコンポーネントをダブルクリックすると、勝手に関数が作成されます。
害はありませんが、コードが汚染されるので私は嫌いです。
フォルダを選択できるようにする
ツールボックスからMenuStrip
を探して、D&Dで追加してください。
追加後、ダブルクリックで項目を追加できます。
ここでは「フォルダを開く」という項目を追加します。
変数名の話
プロパティにて変数名を変更できます。
※GUI表示に使用されるのはText
です。
変更しないとコード内に日本語変数が紛れ込みます。
関数名に日本語が混ざります。
動作上問題はないのですが気持ち悪い・・・
イベント追加
MenuStrip
のイベントClick
に対して、関数を設定します。
Click
を選択してダブルクリックで勝手に関数が作成されます。
フォルダを開く コードの追加
private void ****ToolStripMenuItem_Click(object sender, EventArgs e)
という関数が自動生成されると思います。
下記のコードのように、クリックしたらフォルダ選択ダイアログが表示されるように実装します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Dialogs;
namespace Viewer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void DirOpenToolStripMenuItem_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
dialog.EnsureReadOnly = true;
dialog.AllowNonFileSystemItems = false;
dialog.DefaultDirectory = Application.StartupPath;
var Result = dialog.ShowDialog();
if (Result == CommonFileDialogResult.Ok)
{
this.Text = dialog.FileName;
}
}
}
}
※Form1.csがプログラムとして開けない人は、下記の方法で開いてみてください。
Form1.Designer.cs → Form→Form1()をクリック
ここまでいろいろやったのでコンパイルして、動くか確認しておきましょう。
コンパイル後、「フォルダを開く」ボタン→「フォルダ選択ダイアログ」が開き、
選択後にフォームのタイトルが「選択したパス」になっていればOKです。
画像ビューワーに仕立て上げる
ガワはできたので、ここから作りこんでいきます。
ここから説明する関数は全てForm1
クラスのメンバ関数です。また、適宜イベントを設定する必要があります。
下記の部品を追加します。
ListViewはプロパティ「View」を「List」にします(見た目が変わります)。
PictureBoxはプロパティ「SizeMode」を「Zoom」にする(画像の表示方法です)
以下のURLに詳しく記載されています。
PictureBoxコントロールに簡単に画像を表示する - .NET Tips (VB.NET,C#...)
画像ビューワーっぽくなってきましたね。
ファイル一覧を表示
ListViewに、選択したフォルダ内のファイル一覧を表示させます。
private void updateFileList(string path)
{
var fullpaths = System.IO.Directory.GetFiles(path, "*");
foreach (string filename in fullpaths)
{
listView1.Items.Add(filename);
}
}
※先ほどのDirOpenToolStripMenuItem_Click()
の
//updateFileList(select_path);
のコメントアウトを外してください
圧縮ファイルを開いて画像を登録する
ListViewの項目をクリックしたら、圧縮ファイル内の「画像ファイル」のみを読み込むようにします。
※読み込みの待ち時間や、IO負荷などはあまり考慮していません。
IArchive archive = null;
List<IArchiveEntry> imgs = null;
int lookPage = 0;
private void listView1_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
ListViewItem item = listView1.SelectedItems[0];
string path = item.SubItems[0].Text;
bool result = registerImage(path);
if (result)
{
lookPage = 0;
showImage(lookPage);
}
}
private bool registerImage(string path)
{
Console.WriteLine(path);
if (archive != null)
{
archive.Dispose();
archive = null;
}
try
{
archive = ArchiveFactory.Open(path);
var entries = archive.Entries.Where(e =>
e.IsDirectory == false && (
Path.GetExtension(e.Key).Equals(".jpg") ||
Path.GetExtension(e.Key).Equals(".jpeg") ||
Path.GetExtension(e.Key).Equals(".png") ||
Path.GetExtension(e.Key).Equals(".bmp")));
imgs = entries.ToList();
}
catch (Exception e)
{
MessageBox.Show(path + " " + e.ToString(), "ファイル展開エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
if (archive != null)
{
archive.Dispose();
}
archive = null;
return false;
}
imgs.Sort((a, b) => { return a.Key.CompareTo(b.Key); });
return true;
}
画像を表示させる+ページめくり機能をつける
いよいよ、画像表示機能を実装します。
といっても、登録している画像を表示させるだけですが・・・
ついでに、矢印キーでページめくりができるようにしておきます。
これは「ListView」に対して「KeyDown」イベントを設定します
private bool showImage(int index)
{
if (imgs.Count() == 0)
{
return false;
}
var entry = imgs[index];
try
{
pictureBox1.Image = Image.FromStream(entry.OpenEntryStream());
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "正常な画像ファイルではありません", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
return true;
}
private void listView1_KeyDown(object sender, KeyEventArgs e)
{
if (archive == null)
{
return;
}
if (e.KeyCode == Keys.Left)
{
lookPage--;
if (lookPage < 0)
{
lookPage = imgs.Count() - 1;
}
showImage(lookPage);
}
else if (e.KeyCode == Keys.Right)
{
lookPage++;
if (lookPage >= imgs.Count())
{
lookPage = 0;
}
showImage(lookPage);
}
}
全てのソースを合体させると、下記のようになります
Viewer/Form1.cs at master · gologius/Viewer · GitHub
まとめ
画像ビューワーを作成しました。
特に SharpCompress の使い方が分からず、最初は苦労しました。
常に圧縮ファイル内の全画像を持つようなコードになっているので、
負荷が気になるところです(といっても私のPCだと全く問題ありませんが・・・)
また、Windowsフォームも技術的には古いらしいので、他の手法も調査もしないとなぁと思いました。
おしまい。
github.com