イメージプレビュー機能付きコモンダイアログ(C/C++版)
イメージプレビュー機能付きコモンダイアログのサンプルです。
サンプルの実行画面
ソースコード
[Sample52.c]
//-------------------------------------------------------------------------------------- // ■イメージプレビュー機能付きコモンダイアログ(Borland Delphi風)■ Sample NO.52 // //-------------------------------------------------------------------------------------- #include <windows.h> //ファイルのパスが日本語を含む可能性が高いので多めに設定(約4倍に変更) #undef MAX_PATH #define MAX_PATH 1000 //リソースID---> //メニュー #define IDM_MENU 200 #define IDM_FILEOPEN 106 #define IDM_EXIT 107 //ダイアログ #define IDD_COMDLG 100 #define IDD_COM_IMAGE 101 #define IDD_COM_CHECK 102 #define IDD_COM_STATIC 103 //コールバックプロシージャ&メッセージハンドラ LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); BOOL CALLBACK ExplorerHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL NEAR PASCAL OnNotify(HWND hDlg, LPOFNOTIFY pOFN); //------------------------------------------------------ //■関数 ScreenCenterX(ローカル) //■用途 ウインドウを中央にする為にX座標(LEFT)を算出する //■引数 // Width ...ウインドウの横幅 //------------------------------------------------------ int ScreenCenterX(int Width) { int X; X = (GetSystemMetrics(SM_CXSCREEN)- Width) / 2; if (X<0) X=0; return(X); } //------------------------------------------------------ //■関数 ScreenCenterY(ローカル) //■用途 ウインドウを中央にする為にY座標(TOP)を算出する //■引数 // Height ...ウインドウの縦幅 //------------------------------------------------------ int ScreenCenterY(int Height) { int Y; Y= (GetSystemMetrics(SM_CYSCREEN)- Height) / 2; if (Y<0) Y=0; return(Y); } //------------------------------------------------------ //■関数 CreateMainWindow(ローカル) //■用途 メインウインドウを作成する //■引数 // Width ...ウインドウの横幅 // Height ...ウインドウの縦幅 // Caption ...タイトル名 // hInstance ...インスタンスハンドル // nCmdShow ...ウインドウの表示形態 // lpfnWndProc ...コールバックプロシージャ // dwstyle ...ウインドウスタイル // dwExstyle ...拡張ウインドウスタイル // MenuID ...メニューのID // hIcon ...アイコン //■戻り値 // ウインドウのハンドル //------------------------------------------------------ HWND CreateMainWindow(int Width,int Height,LPCTSTR Caption,HINSTANCE hInstance,int nCmdShow,WNDPROC lpfnWndProc, DWORD dwstyle,DWORD dwExstyle,LPCTSTR MenuID,HICON hIcon) { HWND hWnd; //メインウインドウのハンドル WNDCLASS myClass; //WNDCLASS構造体 //WNDCLASS構造体を0で初期化 ZeroMemory(&myClass,sizeof(WNDCLASS)); //--->WNDCLASS構造体の設定&ウインドウクラスの登録 //ウインドウスタイルを設定 myClass.style =CS_HREDRAW | CS_VREDRAW; //コールバックプロシージャへのポインタ myClass.lpfnWndProc = lpfnWndProc; //インスタンスハンドルを設定 myClass.hInstance=hInstance; //カーソルの設定(Windows標準リソースを使用) myClass.hCursor=LoadCursor(NULL, IDC_ARROW); //ウインドウの背景を設定(デフォルトカラー) myClass.hbrBackground=(HBRUSH)COLOR_WINDOW; //クラス名の設定(Borland Delphi風) myClass.lpszClassName="TForm"; //アイコンの指定 myClass.hIcon =hIcon; //メニューの設定 myClass.lpszMenuName=MenuID; //ウィンドウ クラスを登録 RegisterClass(&myClass); //--->ウインドウの作成&表示 //メインウインドウの生成 hWnd = CreateWindowEx( //拡張ウインドウスタイル dwExstyle, //登録されたクラス名のアドレス "TForm", //ウインドウ名 Caption, //ウインドウスタイルを設定 dwstyle, //X座標の位置設定 ScreenCenterX(Width), //Y座標の位置設定 ScreenCenterY(Height), //横幅を設定 Width, //縦幅を設定 Height, //親ウインドウを設定 NULL, //メニューを設定 NULL, //インスタンスを識別 hInstance, //作成したウインドウに渡すデータへのポインタ NULL); //ウインドウの表示(表示方法はnCmdShowに従う) ShowWindow(hWnd, nCmdShow); return(hWnd); } //------------------------------------------------------ //■関数名 ControlCreate //■用途 ウインドウ(コントロール)を作成 //■引数 // hwndParent ...親ウインドウのハンドル // Left ...作成するウインドウの左隅のX座標 // Top ...作成するウインドウの左隅のY座標 // Width ...作成するウインドウの横幅 // Height ...作成するウインドウの縦幅 // dwExStyle ...ウインドウの拡張フラグ // dwFlag ...ウインドウの作成フラグ // Caption ...作成するウインドウのキャプション // ClassName ...作成するウインドウクラス名 // ChildID ...子ウインドウの識別子 // hInstance ...インスタンスハンドル //■戻り値 //子ウインドウのハンドル //------------------------------------------------------ HWND CreateControlWindow(HWND hwndParent, int Left, int Top,int Width, int Height,int dwExStyle ,int dwFlag ,LPCTSTR Caption, LPCTSTR ClassName,HMENU ChildID,HINSTANCE hInstance) { return CreateWindowEx(dwExStyle,ClassName,Caption,WS_CHILD | WS_VISIBLE | dwFlag , Left, Top, Width, Height, hwndParent, ChildID, hInstance, NULL); } //-------------------------------------------------------- //■関数 WinMain //■用途 メインの関数 //■引数 // hInstance ...現在のインスタンスのハンドル // hPrevInstance...以前のインスタンスのハンドル // pszCmdLine ...コマンド ラインのアドレス // nCmdShow ...ウィンドウの表示状態 //-------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; //メインウインドウを作成 CreateMainWindow(280,280,"イメージプレビュー機能付きコモンダイアログ",hInstance,nCmdShow,(WNDPROC)WindowProc, WS_OVERLAPPEDWINDOW,WS_EX_CONTROLPARENT | WS_EX_WINDOWEDGE,MAKEINTRESOURCE (IDM_MENU),LoadIcon(NULL,MAKEINTRESOURCE(IDI_APPLICATION))); //送られてくるメッセージを翻訳してプロシージャに渡す while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } //------------------------------------------------------ // ■関数 WindowProc // ■用途 メインウインドウに送られるメッセージを処理 // ■引数 // hwnd ...ウインドウのハンドル // uMsg ...メッセージID // wParam ...第1メッセージ パラメータ // lParam ...第2メッセージ パラメータ //------------------------------------------------------ LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_COMMAND: switch(LOWORD( wParam )) { case IDM_FILEOPEN: { OPENFILENAME OFN; TCHAR szFile[MAX_PATH] = "\0"; strcpy(szFile, ""); ZeroMemory(&OFN,sizeof(OPENFILENAME)); //構造体の設定 OFN.lStructSize = sizeof(OPENFILENAME); OFN.hwndOwner = hwnd; OFN.hInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE) ; OFN.lpstrFile = szFile; OFN.nMaxFile = sizeof(szFile); OFN.lpstrTitle = "ファイルを開く"; OFN.lpstrFilter ="BMP files(*.bmp)\0*.bmp\0\0"; OFN.lpfnHook = (LPOFNHOOKPROC)ExplorerHook; OFN.lpTemplateName = MAKEINTRESOURCE(IDD_COMDLG); OFN.Flags = OFN_ENABLEHOOK | OFN_ENABLETEMPLATE|OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY|OFN_EXPLORER; //ダイアログオープン if (GetOpenFileName(&OFN)) MessageBox(hwnd,strcat(OFN.lpstrFile,"\nを選択しました。"),"情報",MB_OK); break; } case IDM_EXIT: PostQuitMessage(0); break; default: return (DefWindowProc(hwnd, uMsg, wParam, lParam)); } break; case WM_DESTROY: PostQuitMessage(0); break; default:return(DefWindowProc(hwnd, uMsg, wParam, lParam)); } return (0); } //----------------------------------------------------------------- // ■関数 OnNotify // ■用途 ダイアログに送られてきたWM_NOTIFYメッセージを処理 // ■引数 // hwnd ...ダイアログベースのハンドル // pOFN ...OFNOTIFY構造体へのポインタ //----------------------------------------------------------------- BOOL NEAR PASCAL OnNotify(HWND hDlg, LPOFNOTIFY pOFN) { switch (pOFN->hdr.code) { case CDN_INITDONE: { RECT Rect; //ダイアログをセンタリング GetWindowRect((HWND)GetWindowLong(hDlg, GWL_HWNDPARENT), &Rect); SetWindowPos((HWND)GetWindowLong(hDlg, GWL_HWNDPARENT), 0,((GetSystemMetrics(SM_CXSCREEN) - Rect.right + Rect.left) / 2), (GetSystemMetrics(SM_CYSCREEN) - Rect.bottom + Rect.top) / 3,0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); break; } case CDN_SELCHANGE: { char szFile[MAX_PATH]; char buffer[100]; HBITMAP hBitmap=NULL,hDummy=NULL; BITMAP BMPINFO,DummyInfo; HDC hMem,hDC; RECT Rect; HBRUSH hBrsuh; int Width,Height,Top,Left; //パスの文字数が限界を超えていないかチェックする if (SendMessage(GetParent(hDlg), CDM_GETSPEC,(WPARAM)sizeof(szFile),(LPARAM)(LPWSTR)szFile)<=sizeof(szFile)); { //チェックボタンが選択されている場合のみファイルを読込む if (SendMessage(GetDlgItem(hDlg,IDD_COM_CHECK),BM_GETCHECK,0,0)==1) { //ビットマップのロード(LoadImage) hBitmap =(HBITMAP)LoadImage((HINSTANCE)GetWindowLong(GetParent(hDlg),GWL_HINSTANCE),szFile,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); if (hBitmap!=NULL) { //正確な画像の色数を取得する為にLR_CREATEDIBSECTIONでもう一度ロードする hDummy =(HBITMAP)LoadImage((HINSTANCE)GetWindowLong(GetParent(hDlg),GWL_HINSTANCE),szFile,IMAGE_BITMAP, 0, 0,LR_CREATEDIBSECTION| LR_LOADFROMFILE ); GetObject(hDummy, sizeof(BITMAP), &DummyInfo); DeleteObject(hDummy); hDC=GetDC(GetDlgItem(hDlg,IDD_COM_IMAGE)); GetWindowRect(GetDlgItem(hDlg,IDD_COM_IMAGE), &Rect); GetObject(hBitmap, sizeof(BITMAP), &BMPINFO); hMem = CreateCompatibleDC(hDC); SelectObject(hMem, hBitmap); Width =Rect.right-Rect.left; Height=Rect.bottom-Rect.top; //画像の詳細表示 wsprintf(buffer,"画像:%dx%d %dBitsPixel",BMPINFO.bmWidth,BMPINFO.bmHeight,DummyInfo.bmBitsPixel); SendMessage(GetDlgItem(hDlg,IDD_COM_STATIC),WM_SETTEXT,0,(LPARAM)buffer); //塗りつぶし GetClientRect(GetDlgItem(hDlg,IDD_COM_IMAGE),&Rect); //枠があるためサイズを変更 Rect.left=Rect.left+2;Rect.top=Rect.top+2;Rect.right=Rect.right-2;Rect.bottom=Rect.bottom-2; //ブラシ生成 hBrsuh=CreateSolidBrush(RGB(192,192,192)); FillRect(hDC,&Rect,hBrsuh); DeleteObject(hBrsuh); //ロードしたイメージのサイズがイメージコントロールより小さい場合(センタリング法の区別) if ((BMPINFO.bmWidth<Width+(int)(Height*0.1)) && (BMPINFO.bmHeight<Height)+(int)(Height*0.1)) { Left=(int)((Width-BMPINFO.bmWidth)/2); Top=(int)((Height-BMPINFO.bmHeight)/2); BitBlt(hDC,Left,Top, BMPINFO.bmWidth,BMPINFO.bmHeight, hMem, 0, 0, SRCCOPY); } else { Top =(int)(Height*0.1); Left=(int)(Width*0.1); //リサイズするので画像が汚くなります。(汚くならない方法がありますが今回はパスします) StretchBlt (hDC,Left,Top,(int)(Width*0.8),(int)(Height*0.8),hMem,0,0,BMPINFO.bmWidth,BMPINFO.bmHeight,SRCCOPY); } DeleteDC(hMem); DeleteObject(hBitmap); ReleaseDC(GetDlgItem(GetParent(hDlg),IDD_COM_IMAGE),hDC); } } } } break; } return(TRUE); } //------------------------------------------------------ // ■関数 ExplorerHook // ■用途 ダイアログに送られるメッセージを処理 // ■引数 // hwnd ...ダイアログハンドル // uMsg ...メッセージ // wParam ...第1メッセージ パラメータ // lParam ...第2メッセージ パラメータ //------------------------------------------------------ BOOL CALLBACK ExplorerHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: //チェックボタンを選択 SendMessage(GetDlgItem(hDlg,IDD_COM_CHECK),BM_SETCHECK,1,0); break; case WM_COMMAND: { HDC hDC; RECT Rect; HBRUSH hBrsuh; if (LOWORD(wParam)==IDD_COM_CHECK) { //チェックボタンが選択されていない場合はイメージの内容をクリアする if (SendMessage(GetDlgItem(hDlg,IDD_COM_CHECK),BM_GETCHECK,0,0)!=1) { hDC=GetDC(GetDlgItem(hDlg,IDD_COM_IMAGE)); //塗りつぶし GetClientRect(GetDlgItem(hDlg,IDD_COM_IMAGE),&Rect); //枠があるためサイズを変更 Rect.left=Rect.left+2;Rect.top=Rect.top+2;Rect.right=Rect.right-2;Rect.bottom=Rect.bottom-2; //ブラシ生成 hBrsuh=CreateSolidBrush(RGB(192,192,192)); FillRect(hDC,&Rect,hBrsuh); DeleteObject(hBrsuh); ReleaseDC(GetDlgItem(GetParent(hDlg),IDD_COM_IMAGE),hDC); //テキストの変更 SendMessage(GetDlgItem(hDlg,IDD_COM_STATIC),WM_SETTEXT,0,(LPARAM)"画像:"); } } break; } case WM_PAINT: { OFNOTIFY OFN; //再描画 OFN.hdr.code=CDN_SELCHANGE; OnNotify(hDlg, &OFN); return FALSE; break; } case WM_NOTIFY: OnNotify(hDlg, (LPOFNOTIFY)lParam); default: return FALSE; } return TRUE; }
ソースコード一式のダウンロード
capi_sample52.zip 5,011 バイト
動作環境
このサンプルは 「Windows98」及び「Microsoft Visual C++5.0」「Borland C++ Compiler 5.5」で確認しております。環境が異なる場合は正常に動作しない場合もございますのでご了承下さい。
Visual C++5.0でのコンパイル
VC5.0でサンプルをコンパイルする場合は新規プロジェクト(Win32Application)を作成後、各ファイルを追加してビルドしてください。
Borland C++ Compiler 5.5でのコンパイル
BCC5.5でサンプルをコンパイルする場合は「bcc32.exe」で*.c又は*.cppファイルをコンパイルします。リソースがある場合は「brc32.exe」で*resファイルを付与してください。
サンプルについて
このWindows APIサンプル集(C/C++版)は2000年頃にC/C++言語の学習の為に作成したものです。コードはエレガントではなく「初心者レベルのコーディング」です。仕事などの業務で利用する際にはエラー処理やメモリ解放などの再確認を必ずして下さい。
スポンサーリンク
関連記事
公開日:2015年03月19日
記事NO:00508