//
//   ファイルのドラッグ&ドロップ
//
//     1998/ 6/11  宍戸 輝光
//

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
void readBMP(char fn[]);

HINSTANCE hInst;
HWND hwnd;
int xSize,ySize;
BOOL loaded;
LPBITMAPINFO lpInfo;
LPBYTE lpBMP,lpBuf;

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",
		    "ファイルのドラッグ&ドロップ",
                    WS_OVERLAPPEDWINDOW,
                    64,64,
                    480,400,
                    NULL,
                    NULL,
                    hInstance,
		            NULL);

	DragAcceptFiles(hwnd,TRUE); // ドラッグ&ドロップ受入

	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];
	HDROP hDrop;

	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;

			readBMP(szFn); // BMPファイル読み込み

			return 0;

		case WM_DROPFILES: // ファイルがドロップされた時の処理

			hDrop=(HDROP)wParam; // HDROPを取得

			DragQueryFile(hDrop,0,szFn,256); // ファイル名を取得

			readBMP(szFn); // BMPファイルを読み込んで表示

			DragFinish(hDrop); // 終了処理

			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) ;

}

void readBMP(char fn[]) {

	char str[280];
	DWORD offset,dummy;

	HANDLE fh;

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

	fh=CreateFile(fn,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) { // BMPでない

		GlobalFree(lpBuf);
		loaded=FALSE;

		SetWindowText(hwnd,"Error!!");

		return;

	}

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

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

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

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

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

}