Microsoft Visual Basic Express スタート キット

スタート キット : 画像管理

内容 :

概要
このスタートキットで学ぶポイント
はじめに
画像管理の動作
拡張
その他
参照項目

概要

画像管理は、画像ファイル(.jpg, .bmp, .gif, .tiff, .png)を自由な大きさのサムネイルで閲覧できるアプリケーションです。フォルダ ツリービューより画像ファイルのあるフォルダを選択すると、サムネイルが表示されます。表示する大きさや列の数を指定して表示したり、選択した画像のみのサムネイルを印刷したりできます。

画像管理メイン



このスタートキットで学ぶポイント



はじめに

画像管理のビルドと実行

画像管理を実行するには

画像管理のメイン画面が起動されます。マイ ピクチャが存在する環境であれば、マイ ピクチャの内容が最初に表示されます。

メイン画面のタイトルや何も無い部分をドラッグすると、ウィンドウの移動が行えます。


フォルダを選択する

メイン画面の左側にあるツリービューで、閲覧するフォルダを選択できます。エクスプローラのツリーと似たような感覚で、選択、名前の変更、コピー、貼り付け、削除、ドラッグ&ドロップが行えます。

また、右クリックでポップアップメニューを表示して、「エクスプローラ」の起動や「新規フォルダ」の作成も行えます。

制限として、ツリーのルートは名前の変更や削除ができないようになっています。

画像を選択する

メイン画面の右側に、フォルダ上にある画像ファイルのサムネイルが表示されます。画像をクリックすることで、そのファイルが選択状態になります。ファイルを選択状態にすることで、スライドショー、印刷、回転、画面を開く、コピー操作等を対象のファイルのみに限定することができます。

ファイル選択のルールとして、クリックのみでは単体選択、Ctrl キーを押しながらクリックで追加選択、Shift キーを押しながらクリックで前回選択箇所からの一括選択、Ctrl キーと Shift キー両方を押しながらのクリックで追加としての前回選択箇所からの一括選択となります。

右クリックではポップアップメニューが表示され、貼り付けと、選択されているファイルのコピーや削除が行えます。

その他の操作として、F5 キーで再読み込み、Delete キーまたは Ctrl キーを押しながらの D で削除、Ctrl キーを押しながら C でコピー、Ctrl キーを押しながら V で貼り付け、Ctrl キーを押しながら A で全選択が行えます。また、ダブルクリックまたは Enter キーで、選択されている画像を開きます。

機能ボタン

機能ボタン

メイン画面下の機能ボタンは左から、スライドショー表示、印刷、右回転、左回転、画像を開く、サムネイルのサイズ変更のスライドバー、ファイル名表示(上)とコメント表示(下)の有無、カラム数の自動設定(上)と手動設定(下)となっています。

「スライドショー表示」ボタンを押すと、二つ以上の画像ファイルが選択されていた場合はそれらのファイルのみで、そうでなければフォルダ上の画像全てでスライドショーを実行します。フォルダ上に画像ファイルが無かった場合には何も起きません。

「印刷」ボタンを押すと、画像ファイルが選択されていればそれらのファイルのみで、そうでなければフォルダ上の画像全てのサムネイルの印刷プレビューを開きます。

「右回転」、「左回転」ボタンを押すと、選択されているファイルをその方向に90度回転させます。なお、回転した結果はファイルに反映されるため、jpg 等の非可逆圧縮ファイルを回転させると画質が劣化する恐れがあります。

「画像を開く」ボタンを押すと、選択されているファイルを拡大画面で表示します。5つ以上のファイルを同時に開こうとした場合は、処理が重くなるため警告のメッセージを先に表示します。

「サムネイルのサイズ変更」のスライドバーを移動させると、サムネイル画像のサイズを 60x40 から 600x400 の間で変更できます。サイズの変更はリアルタイムで行われますが、画質の最適化が別スレッドで順次行われるため、サイズ変更直後はぼやけた画像となる場合があります。

「ファイル名表示」と「コメント表示」のボタンは、サムネイル画像の下にファイル名とコメントをそれぞれ表示するかどうかを切り替えます。なお、コメント機能は NTFS のストリームを使用しているため、FAT ファイルシステム上のファイル等ではコメントは表示されません。

「カラム数の自動設定」を選択すると、ウィンドウとサムネイルの大きさに対して、横スクロールバーが極力表示されないようにカラム数を調整します。

「カラム数の手動設定」を選択すると、右側のリストで3から16の範囲でカラム数を調整できます。サムネイル印刷では現在のカラム数にあわせて印刷時の幅を調整するため、印刷の調整にも便利です。

拡大画面

拡大画面では、画像を単体で表示し、コメントの入力等が行えます。

画像管理拡大画面

コメント入力

NTFS ストリームを使用して、画像ファイルにコメントを設定します。

機能ボタン

拡大表示画面の機能ボタン

拡大画面の機能ボタンは、左から、印刷プレビュー、印刷、前のファイル、次のファイル、右回転、左回転、拡大、縮小、ウィンドウに合わせての画像表示、画像の等倍表示となっています。

「印刷プレビュー」ボタンは、既定のプリンタで印刷プレビューを表示します。

「印刷」ボタンは、プリンタを選択しての印刷を行います。

「前のファイル」ボタンは、同じフォルダにある、手前の画像ファイルを表示します。既に最初のファイルだった場合には、最後のファイルに移動します。

「次のファイル」ボタンは、同じフォルダにある、次の画像ファイルを表示します。最後のファイルだった場合には最初のファイルに移動します。

「右回転」、「左回転」ボタンを押すと、その方向に90度回転させます。なお、回転した結果はファイルに反映されるため、jpg 等の非可逆圧縮ファイルを回転させると画質が劣化する恐れがあります。

「拡大」ボタンを押すと、画像の表示を拡大します。

「縮小」ボタンを押すと、画像が拡大表示されていた場合に縮小させます。

「ウィンドウに合わせての画像表示」ボタンを押すと、等倍以下の範囲でウィンドウに合わせて画像を表示させます。

「画像の等倍表示」ボタンを押すと、本来のイメージの大きさで画像を表示します。ウィンドウに入りきらない場合はスクロールバーが表示されます。

スライドショー画面

スライドショー

スライドショーでは、画面いっぱいの大きさで画像表示し、指定したタイマーで次の画像に移ります。

スライドショーではツールバーが表示されます。ツールバーには、前のファイル、次のファイル、再生/停止、タイマーのリスト、フレーム、閉じるボタンがあります。

「前のファイル」ボタンは、スライドショー設定されているファイルの中で、前のファイルを表示します。

「次のファイル」ボタンは、スライドショー設定されているファイルの中で、次のファイルを表示します。

「再生/停止」ボタンは、タイマーの実行の中断・再開を切り替えます。

「タイマーのリスト」ボックスを切り替えることで、スライドショーでのタイマー間隔を1秒から8秒の間で変更できます。

「フレーム」ボタンは、イメージの前景として表示する画像を選択します。フレーム用のイメージには、実行ファイルのあるフォルダの[FrameImages]フォルダ の中にある透過 PNG フォーマットのファイルを使用します。

「閉じる」ボタンでスライドショーを終了します。


マウスの右クリックにより、ツールバーの表示非表示を変更できます。

左ダブルクリックを行うと、初期状態の全画面表示から、通常ウィンドウ表示に切り替えることができます。ウィンドウ表示では、マウスのドラッグでウィンドウの移動が行えます。

スライドショー画面では、キーボードでも次の操作が行えます。



画像管理の動作

画像管理のプロジェクト ファイルとフォルダ

プロジェクトには、次の Visual Basic ソースコード ファイルとフォルダが含まれています。

GraphicCollectorForm.vb メイン画面のフォーム。
GraphicCollectorMain.vb メイン画面の機能を制御するコントロール。
PhotoViewerForm.vb 拡大画面のフォーム。
PhotoViewerMain.vb 拡大画面の機能を制御するコントロール。
SlideShowForm.vb スライドショーのフォーム。
SlideShowMain.vb スライドショーの機能を制御するコントロール。
PopupForm.vb コントロールからフォームの移動やサイズ変更を制御するための派生用コントロール。
FolderTreeView.vb Explorer 風のツリービューコントロール。
PhotoListUI.vb 画像のリストを表示するコントロール。
PhotoListCtl.vb PhotoListUI の表示を制御するコントロール。
ImageDataList.vb 画像のリストの管理や読み込みを行うクラス。
ImageButtonCtl.vb 拡張ボタンコントロール。


拡張

大きさを調整したサムネイル画像を別のファイルとして保存し、HTML 形式のファイルで閲覧できるように保存できると便利です。イメージの保存とテキスト ストリームへの出力を使って、実画像へのリンク付きのサムネイルの HTML ファイルを作れるようにしてみます。

HTMLとサムネイル出力を実装するには

  1. GraphicCollectorMain.vb をデザイナで表示します。
  2. プロパティ画面で CMSListWnd を選択します。
  3. ContextMenuStrip にセパレータと、新しいメニュー項目「HTMLに出力(&H)」を追加します
  4. 新しいメニュー項目をダブルクリックして、対応するイベント メソッドを追加します。
  5. デザイナのツールボックスから、SaveFileDialogGraphicCollectorMain のフォーム上にドラッグします。
  6. HTML に出力を行う次のような関数を作成し、メニュー項目のイベントから呼び出すようにします。

    Private Function ThumbToHtml() As Boolean
      Dim imgdl As ImageDataList
      Dim bError As Boolean = False
      
      ' 選択されている画像のリストを取得
      imgdl = PhotoListCtl1.SelectedImages
      If imgdl Is Nothing Then
        MessageBox.Show("画像がありません", My.Application.Info.Title, MessageBoxButtons.OK)
        Return False
      ElseIf imgdl.Count <= 0 Then
        MessageBox.Show("画像がありません", My.Application.Info.Title, MessageBoxButtons.OK)
        Return False
      End If
      
      Try
        ' 保存するフォルダ名を確認
        SaveFileDialog1.InitialDirectory = FolderTreeView1.SelectedNode.Name
        If Not SaveFileDialog1.ShowDialog() = DialogResult.OK Then
          Return False
        End If
        
        Dim sFolderName As String = SaveFileDialog1.FileName
        Dim sName As String = sFolderName + "¥" + Path.GetFileName(sFolderName) + ".html"
        
        ' ファイルを置くフォルダを作成
        If Not Directory.Exists(sFolderName) Then
          Try
            Directory.CreateDirectory(sFolderName)
            Directory.CreateDirectory(sFolderName + "¥Thumb")
          Catch ex As Exception
            MessageBox.Show("フォルダ" + sFolderName + "の作成に失敗しました。", My.Application.Info.Title, MessageBoxButtons.OK)
            Return False
          End Try
        ElseIf Not File.Exists(sName) Then ' フォルダがあるのにファイルが無かったら、上書き確認
          If MessageBox.Show(sFolderName + "内にサムネイルファイルを作成しますがよろしいですか?", My.Application.Info.Title, MessageBoxButtons.YesNo) = DialogResult.No Then
            Return True
          End If
          If Not Directory.Exists(sFolderName + "¥Thumb") Then
            Directory.CreateDirectory(sFolderName + "¥Thumb")
          End If
        End If
        
        
        ' 先に、サムネイルに対応したファイルを作成
        Dim sSFileName As String
        Dim sOFileName As String
        For Each imgd As ImageData In imgdl
          Try
            sSFileName = sFolderName + "¥Thumb¥" + Path.GetFileNameWithoutExtension(imgd.strName) + "_s.png"
            sOFileName = sFolderName + "¥" + imgd.strFile
            imgd.img.Save(sSFileName, Imaging.ImageFormat.Png)
            
            File.Copy(imgd.strName, sOFileName, True)
          Catch ex As Exception
            bError = True ' サムネイルファイル作成や個々のファイルコピー時のエラーは終了させず続行
          End Try
        Next
        
        Dim fs As FileStream
        Dim sw As StreamWriter
        Dim sLine As String
        Dim sizThumb As Size = Me.PhotoListCtl1.ThumbSize
        Dim iCols As Integer = Me.PhotoListCtl1.Columns
        Dim i As Integer
        fs = File.Open(sName, IO.FileMode.Create)
        sw = New StreamWriter(fs, System.Text.Encoding.GetEncoding(932)) ' 日本語で出力
        
        sw.WriteLine("<HTML><HEAD><TITLE>")
        sw.WriteLine(My.Application.Info.Title)
        sw.WriteLine("</TITLE></HEAD><BODY>")
        sw.WriteLine("<TABLE border=1>")
        sLine = ""
        sLine += "<TR valign=middle"
        sLine += " height='"
        sLine += (sizThumb.Height + 6).ToString()
        sLine += "'"
        sLine += ">"
        sw.WriteLine(sLine)
        
        i = 0
        For Each imgd As ImageData In imgdl
          sSFileName = "Thumb/" + Path.GetFileNameWithoutExtension(imgd.strName) + "_s.png"
          
          If i >= iCols Then
            sLine = ""
            sLine += "</TR><TR valign=middle"
            sLine += " height='"
            sLine += (sizThumb.Height + 6).ToString()
            sLine += "'"
            sLine += ">"
            sw.WriteLine(sLine)
            i = 0
          End If
          i = i + 1
          
          sLine = ""
          sLine += "<TD align=center"
          sLine += " width='"
          sLine += (sizThumb.Width + 6).ToString()
          sLine += "'"
          sLine += ">"
          
          ' 原寸ファイルをリンクとして設置
          sLine += "<A href='"
          sLine += imgd.strFile
          sLine += "'>"
          ' イメージにはサムネイルファイルを使用
          sLine += "<IMG src='"
          sLine += sSFileName
          sLine += "'"
          sLine += " border='0'"
          ' コメントがあればAltテキストに追加
          If imgd.strComment IsNotNothing Then
            sLine += " alt='"
            sLine += imgd.strComment
            sLine += "'"
          Else ' コメントが無ければファイル名をAltテキストに
            sLine += " alt='"
            sLine += imgd.strFile
            sLine += "'"
          End If
          sLine += ">"
          sLine += "</A>"
          sLine += "</TD>"
          
          sw.WriteLine(sLine)
        Next
        sw.WriteLine("</TR></TABLE>")
        sw.WriteLine("</BODY></HTML>")
        
        sw.Close()
        fs.Close()
      Catch ex As Exception
        MessageBox.Show("処理中にエラーが発生しました。", My.Application.Info.Title, MessageBoxButtons.OK)
        Return False
      End Try
      
      If bError Then
        MessageBox.Show("htmlの作成は行えましたが、サムネイルファイル作成中にエラーが発生しています。", My.Application.Info.Title, MessageBoxButtons.OK)
      End If
      
      Return True
    End Function


その他

本スタートキットでは、コメントの表示と書き込みのために外部モジュール dsofile.dll を使用しています。

dsofile.dll については、次の URL より参照できます。

Tales from the Script

http://www.microsoft.com/japan/technet/community/columns/scripts/sg0305.mspx


また、本スタートキット作成時点でのオリジナルの dsofile.dll では、新規の概要プロパティを作成できないため、本スタートキット付属の dsofile.dll には独自の変更を行ってあります。 具体的には、summprops.cppCDsoSummaryProperties::GetPropertyFromList を次の様にしています。

STDMETHODIMP_(CDsoDocProperty*) CDsoSummaryProperties::GetPropertyFromList(CDsoDocProperty* plist, PROPID id, BOOL fAppendNew)
{
  CDsoDocProperty* pitem = plist;
  CDsoDocProperty* plast = pitem;
  
    ODS("CDsoSummaryProperties::FindPropertyInList\n");
  
// Loop the list until you find the item...
  while (pitem)
  {
    if (pitem->GetID() == id)
      break;
    plast = pitem;
    pitem = pitem->GetNextProperty();
  }
// If no match is found, we can add a new item to end of the list...
// if ((pitem == NULL) && (plast) && (fAppendNew))
  if ((pitem == NULL) && (fAppendNew)) // fix
  {
  // Create the item...
    pitem = new CDsoDocProperty();
    if (pitem)
    {
      VARIANT var; var.vt = VT_EMPTY;
          if( plast) // fix
          { // fix
            if (FAILED(pitem->InitProperty(NULL, id, &var, TRUE, (plast->AppendLink(pitem)))))
            { // If we fail, try to reverse the append and kill the new object...
              plast->AppendLink((pitem->GetNextProperty()));
              pitem->Release();
              pitem = NULL;
            }
          }// fix
          }else fix
          { // fix
            if( FAILED(pitem->InitProperty(NULL, id, &var, TRUE, NULL))) // fix
            { // fix
              pitem->Release(); // fix
              pitem = NULL; // fix
            } // fix
          } // fix
    }
  }
  
  return pitem;
}


参照項目

オンライン情報源


© Microsoft Corporation and/or its suppliers.All rights reserved.Terms of Use.