Windows API Primer   イメージビューワ

ホーム   目次

ImageViewer

imageviewer.c


#include <windows.h>

#define FILE 10
#define OPEN 11
#define QUIT 12

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int     WINAPI   WinMain(HINSTANCE hInstance,
			 HINSTANCE hPrevInstance,
			 LPSTR     lpCmdLine,
			 int       nCmdShow)
{
  HMENU    hMenubar;
  HMENU    hMenuFile;
  
  HACCEL   haccel;
  ACCEL    accel[2];
  
  WNDCLASS wc;
  HWND     hwnd;
  MSG      msg;

  hMenubar  = CreateMenu();
  hMenuFile = CreateMenu();

  AppendMenu(hMenuFile, MF_STRING, OPEN, TEXT("Open\tCtrl + O"));
  AppendMenu(hMenuFile, MF_SEPARATOR, 0, NULL                 );
  AppendMenu(hMenuFile, MF_STRING, QUIT, TEXT("Quit\tCtrl + Q"));
  AppendMenu(hMenubar , MF_POPUP , (UINT_PTR)hMenuFile, TEXT("File"));

  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = NULL;
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = TEXT("IMAGEVIEWER");

  RegisterClass(&wc);

  hwnd             = CreateWindow(TEXT("IMAGEVIEWER"),
				  TEXT("Windows API Primer"),
				  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
				  CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
				  NULL, hMenubar, hInstance, NULL);

  accel[0].key   = 0x4F;  // O key
  accel[0].cmd   = OPEN;
  accel[0].fVirt = FCONTROL | FVIRTKEY;
  accel[1].key   = 0x51;  // Q key
  accel[1].cmd   = QUIT;
  accel[1].fVirt = FCONTROL | FVIRTKEY;
  haccel = CreateAcceleratorTable(accel, 2);

  while (GetMessage(&msg, NULL, 0, 0))
    {
      if (!TranslateAccelerator(hwnd, haccel, &msg)) {
	DispatchMessage(&msg);
      }
    }
    DestroyAcceleratorTable(haccel);

  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC            hdc, hMdc;
  PAINTSTRUCT    ps;
  OPENFILENAME   filename;
  TCHAR          filesize[MAX_PATH];
  static         HBITMAP hbmp;
  BITMAP         bmp;
  
  ZeroMemory(&filename,        sizeof(filename));
  filename.lStructSize       = sizeof(filename );
  filename.lpstrFile         = filesize;
  filename.lpstrFile[0]      = '\0';
  filename.hwndOwner         = hwnd;
  filename.nMaxFile          = sizeof(filesize );
  filename.lpstrFilter       = TEXT("BMP file(*.bmp)\0*.bmp\0");
  filename.nFilterIndex      = 1;
  filename.lpstrInitialDir   = NULL;
  filename.lpstrFileTitle    = NULL;
  filename.Flags             = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  
  switch (msg)
    {
    case WM_PAINT:
      hdc  = BeginPaint(hwnd, &ps);
      hMdc = CreateCompatibleDC(hdc);
      SelectObject(hMdc, hbmp);
      GetObject   (hbmp, sizeof(BITMAP), &bmp);
      BitBlt (hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hMdc, 0, 0, SRCCOPY);
      DeleteDC    (hMdc);
      //DeleteObject(hbmp);  // Deleteしてはいけない
      EndPaint    (hwnd, &ps);
      break;
    case WM_COMMAND:
      switch (LOWORD(wParam))
	{
	case OPEN:
	  if (GetOpenFileName(&filename))
	    {
	      hbmp = (HBITMAP)LoadImage(NULL, filename.lpstrFile, IMAGE_BITMAP,
					0, 0, LR_LOADFROMFILE);
	      //MessageBox(hwnd, filename.lpstrFile, "Choice", MB_OK);
	      // for Debug.
	      InvalidateRect(hwnd, NULL, TRUE);
	    }
	  break;
	case QUIT:
	  SendMessage(hwnd, WM_CLOSE, 0, 0);
	  break;
	}
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
    

実行結果

コード説明

  1. OPENFILENAME filename;
    ファイルダイアログのいろいろなデータを保持する構造体です。この構造体を static 指定したとしてもデータを継続させることはできません。一回一回必ず初期化されます
  2. static HBITMAP hbmp;
    代わりに、このデータを static にしたところが今回のミソです。この方法を見つけるのにかなり苦労しました。
  3. //DeleteObject(hbmp);   // Deleteしてはいけない
    hbmp はせっかく static にしているので、ここで Delete してはいけません。
  4. 余談ですが、bmp はデリートしてもしなくても同じです。
  5. //MessageBox(hwnd, filename.lpstrFile, "Choice", MB_OK);
    取得したファイルパスは、¥ 区切りでした。¥¥ 区切りや / 区切りではありませんでした。それでも問題なく読み込めるみたいです。


39421 visits
Posted: Jun. 12, 2020
Update: Jun. 14, 2020

ホーム   目次