ビットマップの表示

ビットマップ

ビットマップ(bmpファイル)を表示します。

WM_PAINTメッセージ - インコのWindowsSDK で作成したソースを修正します。

流れ

WM_CREATE

WM_CREATEは、ウインドウが生成されたときに1回だけ実行されます。

1.LoadImage()で、ビットマップをロードします。

HANDLE LoadImage(
    HINSTANCE hinst,   // インスタンスのハンドル
    LPCTSTR lpszName,  // イメージの名前またはID
    UINT uType,        // イメージのタイプ
    int cxDesired,     // 幅
    int cyDesired,     // 高さ
    UINT fuLoad        // オプション
);

hinst インスタンスのハンドル
ビットマップファイルを読み込む場合、NULLを指定
lpszName イメージの名前またはID
uType イメージのタイプ
IMAGE_BITMAP ビットマップをロード
IMAGE_CURSOR カーソルをロード
IMAGE_ICON アイコンをロード
cxDesired アイコンまたはカーソルの幅をピクセル単位で指定
実際のリソースの幅を表示する場合、0を指定
cyDesired アイコンまたはカーソルの高さをピクセル単位で指定
実際のリソースの高さを表示する場合、0を指定
fuLoad オプション
LR_DEFAULTCOLOR 何もしません
LR_CREATEDIBSECTION DIBセクションマップを戻り値に設定
LR_DEFAULTSIZE このフラグを指定し、cxDesiredメンバおよび cyDesiredメンバを0にした場合、表示にシステムメトリックが使用されます。 このフラグを指定しない場合、実際のリソースのサイズが使用されます。
LR_LOADFROMFILE lpszNameメンバで指定されるファイルからイメージを読み込みます。
これがない場合は、lpszNameメンバはリソースの名前とします。
LR_LOADMAP3DCOLORS イメージ内の灰色部(ダークグレー[RGB(128,128,128)]、グレー[RGB(192,192,192)]、ライトグレー[RGB(223,223,223)])を対応する 3D カラーに置き換えます。
LR_LOADTRANSPARENT イメージ内の最初のピクセルの色を取得し、カラーテーブル内の対応するエントリをデフォルトウィンドウカラー (COLOR_WINDOW) に置き換えます。
LR_MONOCHROME イメージを白黒で読み込みます。
LR_SHARED イメージハンドルを共有します。
LR_VGACOLOR True Colorを使います。

WM_PAINT

1.CreateCompatibleDC()で、メモリデバイスコンテキストを作成します。

メモリデバイスコンテキストとは、メモリ上にあるGDIオブジェクトのビットマップに描画するためのデバイスコンテキストです。

HDC CreateCompatibleDC(
    HDC hDC       // デバイスコンテキストのハンドル
);

この関数が成功すると、作成したメモリデバイスコンテキストのハンドルが、戻り値として返ります。

2.SelectObject()で、指定されたデバイスコンテキストのオブジェクトを選択。

3.GetObject()で、指定されたグラフィックオブジェクトの情報を取得します。

int GetObject(
    HGDIOBJ hgdiobj, // オブジェクトのハンドル
    int cbBuffer,    // バッファサイズ
    PVOID pvObject   // 情報を格納するバッファ
);

4.GetObject()の第4引数pvObjectには、BITMAP構造体をセットします。
BITMAP構造体は、ビットマップの高さ、幅、色、およびビット値を格納する構造体です。
BITMAP構造体のメンバ、bmWidth、bmHeightからビットマップの大きさを取得します。

typedef struct tagBITMAP
  {
    LONG bmType;       // ビットマップのタイプ。論理ビットマップでは、このメンバは0にします。 
    LONG bmWidth;      // ビットマップの幅(ピクセル単位)。
    LONG bmHeight;     // ビットマップの高さ(ラスタ行数)。
    LONG bmWidthBytes; // ラスタ行ごとのバイト数。
    WORD bmPlanes;     // ビットマップのカラー プレーンの数。
    WORD bmBitsPixel;  // 1 ピクセルを定義するのに必要な、各プレーン上の隣接したカラービットの数を指定。 
    LPVOID bmBits;     // ビットマップのビット値の位置。
  } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;

5.BitBlt()で、画像のビットブロック転送を行ないます。

BOOL BitBlt(
    HDC hdcDest,    // コピー先デバイスコンテキスト
    int nXDest,     // コピー先x座標
    int nYDest,     // コピー先y座標
    int nWidth,     // コピーする幅
    int nHeight,    // コピーする高さ
    HDC hdcSource,  // コピー元デバイスコンテキスト
    int nXSource,   // コピー元x座標
    int nYSource,   // コピー元y座標
    DWORD dwRaster  // ラスタオペレーションコード
);

dwRasterにSRCCOPYを指定すれば、コピー元をコピー先にそのままコピーします。

6.DeleteDC()で、指定されたデバイスコンテキストを削除します。

BOOL DeleteDC(
    HDC hDC     // デバイスコンテキストのハンドル
);

WM_DESTROY

DeleteObject()で、作成したオブジェクトを削除。

ソースコードの入力

ソースコードは下記のように入れてください。

test.cpp
#include <windows.h>
#include "resource.h"

// このコード モジュールに含まれる関数の宣言を転送します:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow)
{
    MSG msg;
    MyRegisterClass(hInstance);

    // アプリケーションの初期化を実行します:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
    // メイン メッセージ ループ:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

//
//  関数: MyRegisterClass()
//
//  目的: ウィンドウ クラスを登録します。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL , IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HP);
    wcex.lpszClassName = TEXT("HP");
    wcex.hIconSm = LoadIcon(NULL , IDI_APPLICATION);

    return RegisterClassEx(&wcex);
}

//
//   関数: InitInstance(HINSTANCE, int)
//
//   目的: メイン ウィンドウを作成します。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hWnd = CreateWindow(TEXT("HP"), TEXT("HP"), WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:  メイン ウィンドウのメッセージを処理します。
//
//  WM_CREATE  - ウインドウ作成時の処理
//  WM_COMMAND - アプリケーション メニューの処理
//  WM_PAINT   - メイン ウィンドウの描画
//  WM_DESTROY - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    static HBITMAP hBitmap;      // ビットマップのハンドル
    static HBITMAP hPrevBitmap;  // ビットマップのハンドル
    static HDC hCompatDC;        // デバイスコンテキストハンドル
    BITMAP bmp;
    UINT BMP_W;                  // ビットマップの幅
    UINT BMP_H;                  // ビットマップの高さ

    switch (message)
    {
        case WM_CREATE:
            // ビットマップをファイルからロードする
            hBitmap = (HBITMAP)LoadImage(NULL, TEXT("toolbar.bmp"),
                       IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
            break;
        case WM_COMMAND:
            wmId = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // 選択されたメニューの解析:
            switch (wmId)
            {
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // メモリデバイスコンテキストを作成する
            hCompatDC = CreateCompatibleDC(hdc);
            // ロードしたビットマップを選択する
            hPrevBitmap = (HBITMAP)SelectObject(hCompatDC, hBitmap);
            GetObject(hBitmap, sizeof(BITMAP), &bmp);
            BMP_W = (int)bmp.bmWidth;
            BMP_H = (int)bmp.bmHeight;
            BitBlt(hdc, 10, 10, BMP_W, BMP_H, hCompatDC, 0, 0, SRCCOPY);
            DeleteDC(hCompatDC);
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

上記の太線で示している箇所のみ追加です。

resource.h (変更なし)
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDC_HP 109

test.rc リソースファイル (変更なし)
#include "resource.h"

/////////////////////////////////////////////////////////////////////////////
//
// メニュー
//

IDC_HP MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...", IDM_ABOUT
    END
END

toolbar.bmp
VCwin32アプリケーション10