開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 BmpViewer
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

作成中。

参考
Win32API(C言語)編 第22章 ビットマップを表示する
DIBをBMPファイルに保存する

BmpViewer.c
#include <tchar.h>
#include <Windows.h>
#include "resource.h"
 
// 関数プロトタイプ宣言
ATOM			MyRegisterClass(HINSTANCE hInstance);
BOOL			InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK	WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void			OnFileOpen(HWND hWnd);
void			OnFileSaveAs(HWND hWnd);
void			OnEditPaste(HWND hWnd);
void			OnPaint(HWND hWnd);
 
// グローバル変数
TCHAR		g_atcClassName[] = _T("BmpViewer");
TCHAR		g_atcWindowName[] = _T("Bitmap Viewer");
HINSTANCE	g_hInstance;
TCHAR		g_atcFileName[MAX_PATH];
HANDLE		g_hBitmap = NULL;
 
//==============================================================================
int APIENTRY _tWinMain(
	HINSTANCE	hInstance,
	HINSTANCE	hPrevInstance,
	LPTSTR		lpCmdLine,
	int		nCmdShow)
{
	MSG	msg;
	HACCEL	hAccelTable;
 
	MyRegisterClass(hInstance);
	if (InitInstance(hInstance, nCmdShow) == FALSE) {
		return 0;
	}
	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDR_MAINFRAME);
	while (GetMessage(&msg, NULL, 0, 0)) {
		if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg) == 0) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}
 
//------------------------------------------------------------------------------
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	= (LPCTSTR)IDR_MAINFRAME;
	wcex.lpszClassName	= g_atcClassName;
	wcex.hIconSm		= LoadIcon(NULL, IDI_APPLICATION);
	return RegisterClassEx(&wcex);
}
 
//------------------------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND	hWnd;
 
	g_hInstance = hInstance;
	hWnd = CreateWindow(
		g_atcClassName,
		g_atcWindowName,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0,
		CW_USEDEFAULT, 0,
		NULL, NULL,
		hInstance,
		NULL);
	if (hWnd == NULL) {
		return FALSE;
	}
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	return TRUE;
}
 
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case ID_FILE_OPEN:
			OnFileOpen(hWnd);
			break;
		case ID_FILE_SAVE_AS:
			OnFileSaveAs(hWnd);
			break;
		case ID_APP_EXIT:
			DestroyWindow(hWnd);
			break;
		case ID_EDIT_PASTE:
			OnEditPaste(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, uMsg, wParam, lParam);
		}
		break;
	case WM_DESTROY:
		if (g_hBitmap) {
			DeleteObject(g_hBitmap);
		}
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}
 
//------------------------------------------------------------------------------
void OnFileOpen(HWND hWnd)
{
	OPENFILENAME	ofn;
 
	ZeroMemory(&ofn, sizeof (OPENFILENAME));
	ofn.lStructSize		= sizeof (OPENFILENAME);
	ofn.hwndOwner		= hWnd;
	ofn.lpstrFilter		= _T("ビットマップ ファイル (*.bmp)\0*.bmp\0");
	ofn.Flags		= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	ofn.lpstrFile		= g_atcFileName;
	ofn.nMaxFile		= _countof(g_atcFileName);
	if (GetOpenFileName(&ofn) == FALSE) {
		return;
	}
 
	if (g_hBitmap) {
		DeleteObject(g_hBitmap);
	}
//	g_hBitmap = LoadImage(NULL, g_atcFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	g_hBitmap = LoadImage(NULL, g_atcFileName, IMAGE_BITMAP, 0, 0,
		LR_LOADFROMFILE | LR_CREATEDIBSECTION);
	if (g_hBitmap == NULL) {
		MessageBox(hWnd, _T("画像の読み込みに失敗しました"), NULL, MB_OK);
		return;
	}
 
	InvalidateRect(hWnd, NULL, TRUE);
}
 
//------------------------------------------------------------------------------
void OnFileSaveAs(HWND hWnd)
{
	OPENFILENAME	ofn;
	DIBSECTION	ds;
	BITMAPFILEHEADER	bmfh;
	HANDLE		hFile;
	DWORD		dw;
	int		i;
 
	if (g_hBitmap == NULL) {
		return;
	}
 
	ZeroMemory(&ofn, sizeof (OPENFILENAME));
	ofn.lStructSize		= sizeof (OPENFILENAME);
	ofn.hwndOwner		= hWnd;
	ofn.lpstrFilter		= _T("ビットマップ ファイル (*.bmp)\0*.bmp\0");
	ofn.Flags		= OFN_HIDEREADONLY;
	ofn.lpstrFile		= g_atcFileName;
	ofn.nMaxFile		= _countof(g_atcFileName);
	ofn.lpstrDefExt		= _T("bmp");
	if (GetSaveFileName(&ofn) == FALSE) {
		return;
	}
 
	i = GetObject(g_hBitmap, sizeof ds, &ds);
 
	ZeroMemory(&bmfh, sizeof bmfh);
	bmfh.bfType	= 0x4d42;	// "BM"
	bmfh.bfOffBits	= sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER);
	bmfh.bfSize	= bmfh.bfOffBits + ds.dsBmih.biSizeImage;
 
	hFile = CreateFile(g_atcFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW,
		FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		return;
	}
	WriteFile(hFile, &bmfh, sizeof bmfh, &dw, NULL);
	WriteFile(hFile, &ds.dsBmih, sizeof (BITMAPINFOHEADER), &dw, NULL);
	WriteFile(hFile, ds.dsBm.bmBits, ds.dsBmih.biSizeImage, &dw, NULL);
	CloseHandle(hFile);
}
 
//------------------------------------------------------------------------------
void OnEditPaste(HWND hWnd)
{
	HANDLE	hBmpClip;
	DWORD	dw;
 
	if (IsClipboardFormatAvailable(CF_BITMAP) == FALSE) {
		return;
	}
	OpenClipboard(hWnd);
	hBmpClip = GetClipboardData(CF_BITMAP);
//	hBmpClip = GetClipboardData(CF_DIB);	// CopyImageで失敗する
	if (g_hBitmap) {
		DeleteObject(g_hBitmap);
	}
//	g_hBitmap = CopyImage(hBmpClip, IMAGE_BITMAP, 0, 0, 0);
	g_hBitmap = CopyImage(hBmpClip, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
	if (g_hBitmap == NULL) {
		dw = GetLastError();
	}
	CloseClipboard();
	InvalidateRect(hWnd, NULL, TRUE);
}
 
//------------------------------------------------------------------------------
void OnPaint(HWND hWnd)
{
	PAINTSTRUCT	ps;
	HDC		hdc;
	HDC		hdcMem;
	RECT		rcClient;
	BITMAP		bm;
	int		iWidthDest;
	int		iHeightDest;
	int		iX;
	int		iY;
 
	hdc = BeginPaint(hWnd, &ps);
	if (g_hBitmap == NULL) {
		goto Exit;
	}
	hdcMem = CreateCompatibleDC(hdc);
	SelectObject(hdcMem, g_hBitmap);
 
	GetClientRect(hWnd, &rcClient);
	GetObject(g_hBitmap, sizeof bm, &bm);
	if (bm.bmWidth <= rcClient.right && bm.bmHeight <= rcClient.bottom) {
		// クライアント領域に収まる場合
		iWidthDest = bm.bmWidth;
		iHeightDest = bm.bmHeight;
	} else {
		// ビットマップとクライアント領域のアスペクト比を比較し
		// アスペクト比を維持したままクライアント領域に収める
		if (bm.bmWidth < bm.bmHeight * rcClient.right / rcClient.bottom) {
			iWidthDest = rcClient.bottom * bm.bmWidth / bm.bmHeight;
			iHeightDest = rcClient.bottom;
		} else {
			iWidthDest = rcClient.right;
			iHeightDest = rcClient.right * bm.bmHeight / bm.bmWidth;
		}
	}
	iX = (rcClient.right - iWidthDest) / 2;
	iY = (rcClient.bottom - iHeightDest) / 2;
	StretchBlt(hdc, iX, iY, iWidthDest, iHeightDest,
		hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
/*
	BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
		ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
		hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
*/	
	DeleteDC(hdcMem);
Exit:
	EndPaint(hWnd, &ps);
}
 

resource.h
#define IDR_MAINFRAME	128
#define ID_FILE_OPEN	129
#define ID_FILE_SAVE_AS	130
#define ID_APP_EXIT	131
#define ID_EDIT_PASTE	132
 

BmpViewer.rc
// リソーススクリプト
 
#include "resource.h"
 
//------------------------------------------------------------------------------
// メニュー
IDR_MAINFRAME MENU
BEGIN
	POPUP "ファイル(&F)"
	BEGIN
		MENUITEM "開く(&O)...\tCtrl+O", ID_FILE_OPEN
//		MENUITEM "上書き保存(&S)\tCtrl+S", ID_FILE_SAVE
		MENUITEM "名前を付けて保存(&A)...", ID_FILE_SAVE_AS
		MENUITEM SEPARATOR
		MENUITEM "アプリケーションの終了(&X)", ID_APP_EXIT
	END
	POPUP "編集(&E)"
	BEGIN
		MENUITEM "貼り付け(&P)\tCtrl+V", ID_EDIT_PASTE
	END
END
 
//------------------------------------------------------------------------------
// アクセラレータ
IDR_MAINFRAME ACCELERATORS
BEGIN
	"O",	ID_FILE_OPEN,		VIRTKEY,CONTROL
	"S",	ID_FILE_SAVE_AS,	VIRTKEY,CONTROL
	"V",	ID_EDIT_PASTE,		VIRTKEY,CONTROL
END
 
最終更新:2012年09月01日 16:45