//
//   BMPファイルからDIBを読み込む
//
//     1998/ 6/ 1  宍戸 輝光
//

#include <windows.h>

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

HINSTANCE hInst;
HWND hwnd;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow){

	MSG  msg;
	WNDCLASSEX  wndclass ;

	hInst=hInstance; // プロセスのハンドルを保存

	wndclass.cbSize        = sizeof(wndclass);
	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = "Test Window";
	wndclass.hIconSm       = LoadIcon (NULL, IDI_APPLICATION);

	RegisterClassEx (&wndclass);

	hwnd = CreateWindow ("Test Window",
		    "BMPファイル読み込み",
                    WS_OVERLAPPEDWINDOW,
                    64,64,
                    480,400,
                    NULL,
                    NULL,
                    hInstance,
		            NULL);

	ShowWindow (hwnd,iCmdShow);      // ウインドウを表示
	UpdateWindow (hwnd);             // 再描画

	while (GetMessage (&msg,NULL,0,0)) { // メッセージループ

		TranslateMessage(&msg);
		DispatchMessage(&msg);

	}

	return msg.wParam ;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {

	static OPENFILENAME ofn;
	static char szFn[256],szFt[256],str[280];
	static LPBITMAPINFO lpInfo;
	static LPBYTE lpBMP,lpBuf;
	static int xSize,ySize,i;
	DWORD offset,dummy;
	static BOOL loaded;

	HANDLE fh;
	static HWND hwCtrB;
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMsg) {

		case WM_CREATE:

			hwCtrB=CreateWindow("Button","Load BMP", // ボタン作成
				WS_CHILD | WS_VISIBLE,32,8,128,32,hwnd,
				(HMENU)0,hInst,NULL);

			loaded=FALSE; // 読み込みフラグリセット

			return 0;

		case WM_COMMAND:

			ofn.lStructSize=sizeof(OPENFILENAME); // ファイルを開くダイアログ
			ofn.hwndOwner=hwnd;
			ofn.hInstance=NULL;
			ofn.lpstrFilter= // フィルター
				"ビットマップ(*.bmp)\0*.bmp\0すべてのファイル(*.*)\0*.*\0\0";
			ofn.lpstrCustomFilter=NULL;
			ofn.nMaxCustFilter=0;
			ofn.nFilterIndex=1; // フィルターの初期位置
			ofn.lpstrFile=szFn; // ファイル名用文字列バッファ
			ofn.nMaxFile=255;  // 文字列バッファのサイズ
			ofn.lpstrFileTitle=szFt; // ファイルのタイトル用文字列バッファ
			ofn.nMaxFileTitle=255; // 文字列バッファのサイズ
			ofn.lpstrInitialDir=NULL;
			ofn.lpstrTitle="コモンダイアログテスト"; // タイトル
			ofn.Flags=OFN_FILEMUSTEXIST;// | OFN_HIDEREADONLY;
			ofn.nFileOffset=0;
			ofn.nFileExtension=0;
			ofn.lpstrDefExt=NULL;
			ofn.lCustData=0;
			ofn.lpfnHook=NULL;
			ofn.lpTemplateName=NULL;
			
			if (!GetOpenFileName(&ofn)) // ファイルを選択
				return 0;

			if (loaded) // 以前確保したバッファを解放
				GlobalFree(lpBuf);

			fh=CreateFile(szFn,GENERIC_READ,0,NULL,OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,NULL); // ファイルオープン

			lpBuf=GlobalAlloc(GPTR,GetFileSize(fh,NULL)); // バッファ確保

			ReadFile(fh,lpBuf,GetFileSize(fh,NULL),&dummy,NULL);

			lpInfo=(LPBITMAPINFO)(lpBuf+sizeof(BITMAPFILEHEADER));

			offset=*(LPDWORD)(lpBuf+10);
			lpBMP=lpBuf+offset;

			CloseHandle(fh);

			if (lpBuf[0]!='B' || lpInfo->bmiHeader.biBitCount<16) {

				GlobalFree(lpBuf);
				loaded=FALSE;

				SetWindowText(hwnd,"Error!!");

				return 0;

			}

			xSize=lpInfo->bmiHeader.biWidth;
			ySize=lpInfo->bmiHeader.biHeight;

			wsprintf(str,"%s %d*%dPixel %dBit",szFn,xSize,ySize,
				lpInfo->bmiHeader.biBitCount);

			SetWindowText(hwnd,str); // ビットマップの情報表示

			loaded=TRUE; // 読み込みフラグセット

			InvalidateRgn(hwnd,NULL,FALSE);
			UpdateWindow (hwnd);             // 再描画

			return 0;

		case WM_PAINT:

			hdc=BeginPaint(hwnd,&ps);

			if (loaded)
				StretchDIBits(hdc,4,48,xSize,ySize,0,0,xSize,ySize,lpBMP,
					lpInfo,DIB_RGB_COLORS,SRCCOPY); // DIBを画面に描画

			EndPaint(hwnd,&ps);

			return 0;

		case WM_DESTROY :

			if (loaded)
				GlobalFree(lpBuf);

			PostQuitMessage(0);
			return 0;

	}

	return DefWindowProc (hwnd, iMsg, wParam, lParam) ;

}