#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);
}
// リソーススクリプト
#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