今回は、メニューコントロールや「ファイルを開く」ダイアログボックス、ビットマップ用のAPI関数を活用し、ビットマップビューワの作成にチャレンジしてみます。


プロジェクトの作成

ノーマル ウィンドウ ベースのプロジェクト(プロジェクト名を "BmpViewer" とします)を作成し、メニューの作成(IDは "MainMenu")、メインウィンドウへのメニューの貼り付けを行っておきましょう。
"MainWnd" のプロパティ設定

まずは、ベースとなる "MainWnd" を開き、ウィンドウ プロパティの設定を行います。
背景色のボタンをクリックし、"NULL" に設定しておきます。
メニューを "なし" から "MainMenu" に変更し、"サイズ変更枠" を "細枠" に変更しておきます。今回作るビットマップビューワは、最大化ボタンの使いみちがないため、「最大化ボタン」のチェックもはずしておきましょう。

メニューの編集

"MainMenu" を開き、下のような構成になるよう、メニューの追加を行っていきます。メニュー項目を挿入する場合は、挿入したい場所の1つ上の項目を選択し、「挿入」ボタンをクリックしていくことを思い出しましょう。メニューの編集方法は、ステップ6、ステップ7で解説しています。


キャプション ID 備考
ファイル(&F) - ポップアップ
開く(&O) IDM_OPEN -
  • - セパレータ
終了(&X) IDM_EXIT -
ヘルプ(&H) - ポップアップ
バージョン情報(&A) IDM_ABOUT -



メニュー デザインが完了したら、それぞれのメニューに対するイベント コーディングを行います。

イベント コーディング前の準備

プロジェクト ビューのFileタブから、"MainWnd.sbp" を開き、ファイルの先頭部(「ここから」、「ここまで」の間の部分)に以下の定義文を記述しておきます。これらの変数はグローバル変数として管理され、プログラム内のあらゆるプロシージャが参照することができます。

' ----------------------------------ここから----------------------------------

'ビットマップのファイル名
Dim FileName As String

'「開く」ダイアログの拡張子フィルター
Dim BitmapFileFilter As String
BitmapFileFilter = "ビットマップ ファイル(*.bmp)" + Chr$(0) + "*.bmp" + Chr$(0) + _
                  "すべてのファイル(*.*)" + Chr$(0) + "*" + Chr$(0)

' ----------------------------------ここまで----------------------------------



「開く」メニュー イベント

OPENFILENAME構造体を定義、初期化したのち、GetOpenFileName関数を呼び出しています。ユーザーが「キャンセル」ボタンを押したときはプロシージャから抜け出し(Exit Sub)、「開く」ボタンをクリックしたときは、グローバル文字列変数のFileNameにパスをコピーし、InvalidateRect関数で、hMainWndに対して再描画を要求します。このInvalidateRect関数は、後ほどコーディングするPaintイベントを呼び出し、このPaintイベント内で実際にビットマップの描画が行われる形になります。

Sub MainWnd_IDM_OPEN_MenuClick()
   Dim ofn As OPENFILENAME
   Dim buffer As String

   'ファイル名を取得
   ofn.lStructSize=[[Len]](ofn)
   ofn.hwndOwner=hMainWnd
   ofn.lpstrFilter=[[StrPtr]](BitmapFileFilter)
   ofn.nFilterIndex=1
   buffer=ZeroString(MAX_PATH)
   ofn.lpstrFile=StrPtr(buffer)
   ofn.nMaxFile=MAX_PATH
   If GetOpenFileName(ofn)=0 Then Exit Sub

   FileName=ofn.lpstrFile

   '再描画要求を出す
   InvalidateRect(hMainWnd,ByVal 0,1)
End Sub



「終了」メニュー イベント

終了メニューがクリックされると、WM_CLOSEメッセージを送るようにします。WM_CLOSEメッセージは、ウィンドウの「閉じる(×)」ボタンが押されたときに呼び出されるメッセージです。

Sub MainWnd_IDM_EXIT_MenuClick()
   SendMessage(hMainWnd,WM_CLOSE,0,0)
End Sub



「バージョン情報」メニュー イベント

ここは単純に、プログラム名とバージョン情報をメッセージボックスを利用して表示します。

Sub MainWnd_IDM_ABOUT_MenuClick()
   MessageBox(hMainWnd, "ビットマップ ビューワ Ver1.00","バージョン情報",MB_OK or MB_ICONINFORMATION)
End Sub



"MainWnd" のPaintイベント

"MainWnd" のRAD画面を開き、ウィンドウ内の適当な場所を右クリックしたのち、「イベント コード」をクリックして「イベント処理」ダイアログを開きます。ここでPaintイベントを選択し、「コーディング」ボタンをクリックします。下のコードがPaintイベント プロシージャになります。

まずは、LoadImage関数でFileNameが示すパスのビットマップ ファイルをロードします。
GetObject関数でビットマップの高さ、幅を取得、計算した後、ウィンドウ サイズをビットマップのサイズに変更します。
いったんメモリ デバイス コンテキスト内にビットマップを展開し、BitBlt関数でビットマップを描画します。
最後に、利用したデバイス コンテキスト、オブジェクト(ビットマップ)を破棄して終わりです。

この一連の動作が、再描画要求が出されるたびに行われることになります。再描画要求というと、ちょっとピンとこないかもしれませんが、他のウィンドウに隠れている、画面の外にはみ出しているときなどに、ウィンドウを移動したり、最前面に表示したりすると、隠れていた部分に対して再描画が要求されることになります。また、「開く」メニューのイベント プロシージャからInvalidateRect関数が呼び出されたときも、このイベントが実行されます。

Sub MainWnd_Paint(hDC As Long)
   Dim hBmp As Long              'ビットマップ [[ハンドル]]
   Dim hMemDC As Long            'メモリ内 デバイスコンテキストのハンドル
   Dim BitmapReport As BITMAP    'ビットマップ情報を格納するための構造体
   Dim dx As Long, dy As Long    'ウィンドウサイズとクライアント領域サイズの差

   'ファイルが開かれていない場合は抜け出す
   If FileName="" Then Exit Sub

   'ビットマップをロード
   hBmp=LoadImage(GetWindowLong(hMainWnd, GWL_HINSTANCE), FileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
   If hBmp=0 Then
       MessageBox(hMainWnd, "ビットマップのオープンに失敗", "BmpViewer", MB_OK)
       Exit Sub
   End If

   'ビットマップのサイズを取得
   GetObject(hBmp, Len(BitmapReport), BitmapReport)

   'ウィンドウサイズとクライアント領域サイズの差を計算
   Dim rc_[[Window]] As RECT, rc_Client As RECT
   GetWindowRect(hMainWnd, rc_Window)
   GetClientRect(hMainWnd, rc_Client)
   dx = (rc_Window.right - rc_Window.left) - (rc_Client.right - rc_Client.left)
   dy = (rc_Window.bottom - rc_Window.top) - (rc_Client.bottom - rc_Client.top)

   'ウィンドウサイズをビットマップのサイズにあわせる
   MoveWindow(hMainWnd, rc_Window.left, rc_Window.top, BitmapReport.bmWidth+dx ,BitmapReport.bmHeight+dy, 1)

   hMemDC=CreateCompatibleDC(hDC)  'メモリ内にデバイスコンテキストを作成する
   SelectObject(hMemDC, hBmp)      'ビットマップを選択

   'ビットマップを描画
   BitBlt(hDC, 0, 0, BitmapReport.bmWidth, BitmapReport.bmHeight, hMemDC, 0, 0, SRCCOPY)

   DeleteDC(hMemDC)    'メモリ内のデバイスコンテキストを解放する
   DeleteObject(hBmp)  'ビットマップ ハンドルを破棄する
End Sub



これですべての作業が完了です。コンパイル、実行をしてみて、ビットマップがしっかりと表示されるかどうか、試してみて下さい。

タグ:

+ タグ編集
  • タグ:
最終更新:2010年06月16日 17:10