Image BIG

選択範囲を拡大して描画します。

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

選択範囲を拡大して描画

  1. 選択範囲を拡大して描画する Main.cpp のソースコードです。
    //★ 選択範囲を拡大して描画    2018-03-15   前田 稔
    #define     NAME    "Select Rect"
    #include    <windows.h>
    #include    "IMAGEAI.h"
    #define     SAFE_DELETE(p)  { if (p) { delete (p); (p)=NULL; } }
    
    IMAGEAI     *Img= NULL;             //IMAGE AI Object Class
    char        ImgFile[]= "c:\\data\\test\\ffx2.bmp";
    HDC         hdc;                    // デバイスコンテキストのハンドル
    BOOL        bCap=FALSE;             // 矩形が描画されている状態
    BOOL        bBlock=FALSE;           // 矩形を描画中
    BOOL        stretch=FALSE;          // 拡大描画 
    POINTS      beg, end, oldend;
    
    //★ 矩形を表示する
    void  DrawRect(HWND hWnd, POINTS beg, POINTS end)
    {   HPEN    hPen;
        int     old;
    
        hdc = GetDC(hWnd);
        old= SetROP2(hdc, R2_NOT);
        hPen = CreatePen(PS_SOLID,2,RGB(0,0,0));
        SelectObject(hdc, hPen);
        MoveToEx(hdc, beg.x, beg.y, NULL);
        LineTo(hdc, end.x, beg.y);
        LineTo(hdc, end.x, end.y);
        LineTo(hdc, beg.x, end.y);
        LineTo(hdc, beg.x, beg.y);
        DeleteObject(hPen);
        SetROP2(hdc, old);
        ReleaseDC(hWnd, hdc);
    }
    
    //★ CALLBACK 関数
    LRESULT  CALLBACK  WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {   PAINTSTRUCT ps;
    
        switch(msg)
        {   case WM_CREATE:
                Img= new IMAGEAI(hWnd);
                if (Img->LoadBmp(ImgFile)==FALSE)
                {   SAFE_DELETE(Img);
                    PostMessage(hWnd,WM_CLOSE,0,0);
                    break;
                }
                Img->Adjust();
                break;
            case WM_PAINT:
                hdc= BeginPaint(hWnd, &ps);
                if (Img)
                {   if (stretch)    Img->Show(hdc,beg,end);
                    else
                    {   Img->Show(hdc,0,0);
                        if (bCap)   DrawRect(hWnd,beg,end);
                    }
                }
                EndPaint(hWnd, &ps);
                break;
            case WM_LBUTTONDOWN:    // 左ボタンをクリック
                if (bCap)
                {   DrawRect(hWnd,beg,end); // 古い矩形を消す
                    bCap= FALSE;
                }
                bBlock = TRUE;
                beg = MAKEPOINTS(lParam);
                oldend = beg;
                DrawRect(hWnd, beg, oldend);
                SetCursor(LoadCursor(NULL, IDC_CROSS));
                break;
            case WM_MOUSEMOVE:
                if(bBlock)
                {   end = MAKEPOINTS(lParam);
                    DrawRect(hWnd, beg, oldend);
                    DrawRect(hWnd, beg, end);
                    oldend = end;
                }
                break;
            case WM_LBUTTONUP:      // 矩形が確定
                if  (bBlock)
                {   bBlock= FALSE;
                    bCap= TRUE;
                    SetCursor(LoadCursor(NULL, IDC_ARROW));
                    end = MAKEPOINTS(lParam);
                    stretch = TRUE;
                    InvalidateRect(hWnd, NULL, TRUE);
                }
                break;
            case WM_RBUTTONDOWN:    // 右ボタンで矩形の取り消し
                bBlock= FALSE;
                bCap= FALSE;
                stretch = 0;
                InvalidateRect(hWnd, NULL, TRUE);
                break;
            case WM_DESTROY:
                SAFE_DELETE(Img);
                PostQuitMessage(0);
                return 0L;
        }
        return  DefWindowProc(hWnd,msg,wParam,lParam);
    }
    
    //★ Windows Main 関数
    int PASCAL  WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine,int nCmdShow)
    {   HWND        hWnd;
        MSG         msg;
    
        WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInstance,NULL,LoadCursor(NULL,IDC_ARROW),
                        (HBRUSH)GetStockObject(LTGRAY_BRUSH),NULL,NAME };
        if (RegisterClass(&wc)==0)    return FALSE;
        hWnd= CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,CW_USEDEFAULT,1200,800,
                NULL,NULL,hInstance,NULL);
        if (!hWnd)  return FALSE;
    
        ShowWindow(hWnd,nCmdShow);
        UpdateWindow(hWnd);
        SetFocus(hWnd);
        while (GetMessage(&msg,NULL,0,0))
        {   TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
  2. 画像の拡大表示に関係する関数です。
    画像解析などで、サイズの調整が必要なときに利用して下さい。
    StretchBlt を使うと選択範囲を拡大して描画することが出来ます。
    POINTS beg が拡大画像の左上座標で、POINTS end が右下座標です。
    HRESULT  IMAGEAI::Show(HDC hdc,long x,long y,long w,long h,long sx,long sy,long sw,long sh)
    {   if (hBmpDC==NULL)   return FALSE;
        StretchBlt(hdc,x,y,w,h,hBmpDC,sx,sy,sw,sh,SRCCOPY);
        return TRUE;
    }
    
    HRESULT  IMAGEAI::Show(HDC hdc,POINTS beg,POINTS end)
    {   if (hBmpDC==NULL)   return FALSE;
        StretchBlt(hdc,0,0,m_Width,m_Height,hBmpDC,beg.x,beg.y,end.x-beg.x,end.y-beg.y,SRCCOPY);
        return TRUE;
    }
    
  3. Main.cpp の WM_PAINT で画像を描画します。
    stretch フラグが true のときは、選択範囲を拡大して描画します。
    off のときは、元の画像の上から DrawRect() で矩形を描画します。
            case WM_PAINT:
                hdc= BeginPaint(hWnd, &ps);
                if (Img)
                {   if (stretch)    Img->Show(hdc,beg,end);
                    else
                    {   Img->Show(hdc,0,0);
                        if (bCap)   DrawRect(hWnd,beg,end);
                    }
                }
                EndPaint(hWnd, &ps);
                break;
    
  4. マウスの左ドラッグで選択された矩形領域を拡大して描画します。
    マウスを右クリックすると元の画像に戻ります。
    Main.cpp で矩形領域を選択するプログラムの説明は 矩形で領域を選択 を参照して下さい。
    StretchBlt() と画像の拡大は 画像の拡大・縮小とスクロール を参照して下さい。

[Next Chapter ↓] Color ⇒ Grayscale
[Previous Chapter ↑] Light

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