Menu 選択で画像の入力と画像情報の表示



Menu 選択で入力した画像サイズに合わせて表示します。
また画像情報を表示する Menu を設定します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. テンプレートを使って、新規プロジェクト(BmpLoad)を作成して下さい。
    コモンダイアログを使うのでヘーダファイルを取り込みます。
    stdafx.h に次の記述を追加して下さい。
    // TODO: プログラムで必要なヘッダ参照を追加してください。
    #include <commdlg.h>
  2. 画像を選択するメニューと画像情報を表示するメニューを設定します。
    メニューの設定は メニュー選択で国旗を切り替える を参照して下さい。
    キャプション ID
    画像(&P)
    画像選択(&S) IDC_SELECT
    画像情報(&I) IDC_INFO
  3. GetOpenFileName() で使用する領域と、画像の幅と高さを記憶する領域を定義します。
        // グローバル変数 :
        HINSTANCE   hInst;
        TCHAR       szTitle[MAX_LOADSTRING];
        TCHAR       szWindowClass[MAX_LOADSTRING];
        char        szFile[MAX_PATH];   // オープンするファイル名(パス付き)
        char        szName[64];         // ファイル名
        char        szDir[64]= { "c:\\My Documents\\My Pictures" };
        long        BMP_W, BMP_H;
        
  4. BMP 画像の入力と描画に関係する関数を定義します。
        // このコード モジュールに含まれる関数の宣言を転送します :
        ATOM                MyRegisterClass(HINSTANCE hInstance);
        BOOL                InitInstance(HINSTANCE, int);
        LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
        LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
        int                 OpenFile();
        HRESULT             ShowBMP(HWND hWnd, LPCSTR szBitmap);
        void                Adjust_Win(HWND hWnd);
    
        //★ OPENFILENAME 構造体で BMP ファイルを選択する
        int OpenFile()
        {   OPENFILENAME    ofn;
    
            szFile[0]= '\0';
            memset(&ofn,0,sizeof(OPENFILENAME));
            ofn.lStructSize= sizeof(OPENFILENAME);
            ofn.hwndOwner= NULL;
            ofn.lpstrFilter= "bmp(*.bmp)\0*.bmp\0すべて(*.*)\0*.*\0\0";
            ofn.lpstrFile= szFile;
            ofn.lpstrFileTitle= szName;
            ofn.nMaxFile= MAX_PATH;
            ofn.Flags= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
            ofn.lpstrDefExt= "bmp";
            ofn.lpstrTitle= "ファイルオープン!";
            ofn.lpstrInitialDir= szDir;
            GetOpenFileName(&ofn);
            return 0;
        }
    
        //★ BMP 画像を表示する
        HRESULT ShowBMP(HWND hWnd, LPCSTR szBitmap)
        {   HBITMAP         hbm;
            HDC             hdc,hmdc;
            BITMAP          bm;
    
            //ファイルからイメージをロード
            hbm = (HBITMAP)LoadImage(NULL,szBitmap,IMAGE_BITMAP,0,0,
                                     LR_LOADFROMFILE|LR_CREATEDIBSECTION);
            if (hbm==NULL)
            {   OutputDebugString("Load Image Error\n");
                return FALSE;
            }
            hdc= GetDC(hWnd);
            hmdc= CreateCompatibleDC(hdc);
            SelectObject(hmdc,hbm);
            GetObject(hbm,sizeof(bm),&bm);
            BMP_W = bm.bmWidth;
            BMP_H = bm.bmHeight;
            BitBlt(hdc,0,0,BMP_W,BMP_H,hmdc,0,0,SRCCOPY);
            DeleteDC(hmdc);
            ReleaseDC(hWnd, hdc);
            DeleteObject(hbm);
            return TRUE;
        }
    
        //★ Window Size を画像に合わす
        void    Adjust_Win(HWND hWnd)
        {   RECT    rc;
            int     x,y;
    
            GetWindowRect(hWnd, &rc);
            x= rc.left;
            y= rc.top;
            rc.right= x + BMP_W;
            rc.bottom= y + BMP_H;
            AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,TRUE);
            MoveWindow(hWnd,x,y,rc.right-rc.left,rc.bottom-rc.top,TRUE);
        }
        
  5. WndProc() にメニューの処理を追加します。
    OpenFile() 関数の中身は GetOpenFileName() 関数を呼ぶだけです。
    char    str[256];
                 :
    // 選択されたメニューの解析 :
    switch (wmId)
    {
        case IDC_SELECT:
            OpenFile();
            ShowBMP(hWnd,szFile);
            Adjust_Win(hWnd);
            break;
        case IDC_INFO:
            wsprintf(str,"ファイル名 = %s\nBMP幅 = %d  BMP高さ = %d\n",
                     szFile,BMP_W,BMP_H);
            MessageBox(hWnd,str,"BITMAP情報",MB_OK);
            break;
        
  6. WM_PAINT に画像を表示するコードを追加します。
    ShowBMP() は IDC_SELECT: から呼び出した関数と同じものです。
    hdc では無く hWnd を渡していることに注目して下さい。
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: 描画コードをここに追加してください...
            ShowBMP(hWnd,szFile);
            EndPaint(hWnd, &ps);
            break;
        
  7. ShowBMP(hWnd,szFile) で BMP 画像を表示するには HDC が必要になります。
    HDC は hWnd から GetDC(hWnd) で取得することが出来ます。
    取得した HDC は用が済めば開放して下さい。
        HDC     hdc;
               :
            hdc= GetDC(hWnd);
               :
            ReleaseDC(hWnd,hdc);
               :
        
  8. [デバッグ][デバッグなしで開始]を選択してビルドに続いて実行を行います。
    最初は空のウインドウが表示されるので、メニューから[画像選択]を選びます。
    ファイルオープンダイアログが表示されて、BMP 画像を選択すると画像サイズに合わせて表示されます。
    メニューから[画像情報]を選ぶと画像の名前とサイズが表示されます。

プログラムの説明

GetOpenFileName() を実行すると szFile[] にパス付きのファイル名が格納されます。
szDir[64] は最初に表示される規定値のフォルダーです。
    char        szFile[MAX_PATH];   // オープンするファイル名(パス付き)
    char        szName[64];         // ファイル名
    char        szDir[64]= { "c:\\My Documents\\My Pictures" };

MENU の処理です。
画像選択を選ぶと IDC_SELECT に制御が渡されます。
IDC_SELECT では新しい画像をオープンして表示します。
    case IDC_SELECT:
        OpenFile();
        ShowBMP(hWnd,szFile);
        Adjust_Win(hWnd);
        break;

画像情報を選ぶと IDC_INFO に制御が渡されます。
IDC_INFO では表示中の画像情報をメッセージボックスに表示します。
    case IDC_INFO:
        wsprintf(str,"ファイル名 = %s\nBMP幅 = %d  BMP高さ = %d\n",
                     szFile,BMP_W,BMP_H);
        MessageBox(hWnd,str,"BITMAP情報",MB_OK);
        break;


仕様が変わった?

最初は szName でフォルダーを除いたファイル名が表示されたのですが何も表示されません。
Visual C++ Ver 6.0 でコンパイルするとファイル名が表示されるのですが .net では空白になります。 (^_^;) 
GetOpenFileName() の仕様が変わったのでしょうか?
    wsprintf(str,"ファイル名 = %s\nBMP幅 = %d  BMP高さ = %d\n",
             szName,BMP_W,BMP_H);

ファイル名だけを抜き出すときは、次の関数を使って下さい。
char    szTitle[128]= "Title";
    GetFileTitle(Bmp->szFile,szTitle,sizeof(szTitle));

超初心者のプログラム入門(Win32API C++)