【VC++】SDIにマウスイベントで四角形を描画する

0

    <機能>

    (1)MFCのSDIアプリケーションにマウスイベントを追加します

     WM_MOUSELEAVE : ウィンドウのクライアント領域を離れた

     WM_MOUSEMOVE : マウスカーソルが動いた

     WM_RBUTTONDOWN : マウスの右ボタンが押下された

     WM_RBUTTONUP : マウスの右ボタンが解放された

    (2)マウスの右ボタンでクライアント領域をドラッグすると四角形を描画します

     CDC->Rectangle

    (3)メニューで描画する四角形の塗りつぶし色、線の種類を変更できます

     塗りつぶし色

     ・赤系の色

     ・緑系の色

     ・青系の色

     線のスタイル

     ・実線(PS_SOLID)

     ・破線(PS_DASH)

     ・点線(PS_DOT)

     

    <実行イメージ>

    メニューを指定すると描画する四角形の色と線のスタイルが変更できます

    VisualStudio,MFC,C++,MOUSE,GetMenu,GetMenuState,
     

    マウスの右ボタン押下するとスタート位置セット、

    マウスの右ボタンUPすると終了位置をセットして四角形を描画します

    VisualStudio,MFC,C++,MOUSE,OnCommand,CheckMenuRadioItem,
     

    <動作検証&開発環境> 
    Visual Studio Community 2017 
     
    <使い方> 
    1.MFCアプリケーションでプロジェクトを作成 
    2.アプリケーションの種類でシングルドキュメントを選択 

    ※その他の設定は下図参照

    VisualStudio,MFC,C++,MOUSE,アプリケーションの種類,ウィザード,
    3.ユーザーインターフェイス機能でクラシックメニューを使用するを選択

    ※その他の設定は下図参照

    VisualStudio,MFC,C++,MOUSE,ユーザーインターフェイス,ウィザード,
     

    4.高度な機能で不要なチェックを外す

    VisualStudio,MFC,C++,MOUSE,高度な機能,ウィザード,
     

    5.プロジェクト構成を確認してソースを追加する

    VisualStudio,MFC,C++,MOUSE,ソリューションエクスプローラー,
    6.クラスウィザードでCChileViewクラスにマウスイベントハンドラを追加

    WM_MOUSELEAVE : クライアント領域の外にカーソルが移動したとき座標を初期化

    WM_MOUSEMOVE : 移動中のマウスカーソルを変更する

    WM_RBUTTONDOWN : マウスの右ボタンでスタート座標取得

    WM_RBUTTONUP : マウスの右ボタンUPで終了座標取得して描画

    VisualStudio,MFC,C++,MOUSE,クラスウィザード,マウスイベント追加,
     

    7.リソースの[Menu]->[IDR_MAINFRAME]を修正してメニュー項目を追加

    以下項目を追加します

     赤系の色 : ID_32771 

     緑系の色 : ID_32772 

     青系の色 : ID_32773

     ――境界線をセット――

     実線 : ID_32774

     破線 : ID_32775

     点線 : ID_32776

    ※塗りつぶし色と線のスタイルはCheckMenuRadioItemでそれぞれグループ化します

    VisualStudio,MFC,C++,MOUSE,Menu,Resource,
    メニューのIDはここではID_32771~ID32776ですがソース内もそれぞれの環境に応じて変更してください

     

    8.クラスウィザードでCMainFrameにOnCommandを追加します

    メニューが操作されたとき塗りつぶし色、線のスタイルを変更する

    VisualStudio,MFC,C++,MOUSE,クラスウィザード,CMainFrame,
     

     

    MFCApplication1.h
    class CMFCApplication1App : public CWinApp
    {
    //〜〜省略〜〜

     

    //グローバル変数
    public:
        //メニューでの選択値
        COLORREF selClr;
        COLORREF selLinfClr;
        int iSelStyle;
    };
    extern CMFCApplication1App theApp;


    MainFrm.h
    class CMainFrame : public CFrameWnd
    {
    //〜〜省略〜〜

     

    private:
        //塗りつぶしの色
        COLORREF clr[3] = {
            RGB(216,130,187),
            RGB(146,208,80),
            RGB(155,194,230)
        };
        //線の色
        COLORREF lineclr[3] = {
            RGB(199,73,157),
            RGB(97,148,40),
            RGB(47,117,181)
        };
        //線のスタイル
        int iStyle[3] = {
            PS_SOLID,
            PS_DASH,
            PS_DOT
        };

        
        virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
    };


    MainFrm.cpp
    #include "stdafx.h"
    #include "MFCApplication1.h"
    #include "MainFrm.h"

    //CMainFrameオブジェクト
    extern CMFCApplication1App theApp;

     

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {

        //〜〜省略〜〜

     

        CMenu *pMenu = this->GetMenu();
        //ON_COMMAND ハンドラーが自動的に無効になるのを停止
        CFrameWnd::m_bAutoMenuEnable = FALSE;
        //全てのメニューを有効化
        pMenu->EnableMenuItem(ID_32771, MF_BYCOMMAND | MF_ENABLED);
        pMenu->EnableMenuItem(ID_32772, MF_BYCOMMAND | MF_ENABLED);
        pMenu->EnableMenuItem(ID_32773, MF_BYCOMMAND | MF_ENABLED);
        pMenu->EnableMenuItem(ID_32774, MF_BYCOMMAND | MF_ENABLED);
        pMenu->EnableMenuItem(ID_32775, MF_BYCOMMAND | MF_ENABLED);
        pMenu->EnableMenuItem(ID_32776, MF_BYCOMMAND | MF_ENABLED);

        //色のメニューをグループ化して赤系にチェックOn

        //CheckMenuRadioItemについてはDeveloperNetwork参照
        pMenu->CheckMenuRadioItem(ID_32771, ID_32773, ID_32771, MF_BYCOMMAND);
        //線のメニューをグループ化して実線にチェックOn
        pMenu->CheckMenuRadioItem(ID_32774, ID_32776, ID_32774, MF_BYCOMMAND);
        //初期値をセット
        theApp.selClr = clr[0];
        theApp.selLinfClr = lineclr[0];
        theApp.iSelStyle = iStyle[0];

        return 0;
    }

    /***********************************************************
    OnCommand
    メニューが変更されたら塗りつぶし色、線の種類を変更

    ※環境に応じてメニューのIDは変更してください
    ***********************************************************/

    BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
    {
        int iSelClr = 0;
        int iSelStyle = 0;
        CMenu *pMenu = this->GetMenu();

        //現在(変更前)のメニューの状態を取得
        if (pMenu->GetMenuState(ID_32771, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 0;
        if (pMenu->GetMenuState(ID_32772, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 1;
        if (pMenu->GetMenuState(ID_32773, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 2;
        if (pMenu->GetMenuState(ID_32774, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 0;
        if (pMenu->GetMenuState(ID_32775, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 1;
        if (pMenu->GetMenuState(ID_32776, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 2;

        //変更されたメニュー項目(iItem)で更新
        UINT iItem = LOWORD(wParam);
        switch (iItem)
        {
        case ID_32771:
            iSelClr = 0;
            break;
        case ID_32772:
            iSelClr = 1;
            break;
        case ID_32773:
            iSelClr = 2;
            break;
        case ID_32774:
            iSelStyle = 0;
            break;
        case ID_32775:
            iSelStyle = 1;
            break;
        case ID_32776:
            iSelStyle = 2;
            break;
        default:
            ;
        }

        //塗りつぶしグループの値を変更
        if (iItem == ID_32771 || iItem == ID_32772 || iItem == ID_32773)
        {
            pMenu->CheckMenuRadioItem(ID_32771, ID_32773, iItem, MF_BYCOMMAND);
            theApp.selClr = clr[iSelClr];
            theApp.selLinfClr = lineclr[iSelClr];
        }
        //線の種類グループの値を変更
        if (iItem == ID_32774 || iItem == ID_32775 || iItem == ID_32776)
        {
            pMenu->CheckMenuRadioItem(ID_32774, ID_32776, iItem, MF_BYCOMMAND);
            theApp.iSelStyle = iStyle[iSelStyle];
        }
        TRACE(L"iSelClr=%d iSelStyle=%d¥r¥n",iSelClr, iSelStyle);
        return CFrameWnd::OnCommand(wParam, lParam);
    }


    ChildView.h
    class CChildView : public CWnd
    {
    //〜〜省略〜〜

     

    public:
        afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
        afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);
        afx_msg void OnMouseLeave();

    private:
        void DrawRectangle();
        //描画中フラグ(描画中のときTRUE)
        BOOL bDrawing;
        //座標情報
        CPoint stPoint, edPoint;
    };

     

    ChildView.cpp
    #include "stdafx.h"
    #include "MFCApplication1.h"
    #include "ChildView.h"

    //CMainFrameオブジェクト
    extern CMFCApplication1App theApp;

    BEGIN_MESSAGE_MAP(CChildView, CWnd)
        //〜〜省略〜〜
        ON_WM_RBUTTONDOWN()
        ON_WM_RBUTTONUP()
        ON_WM_MOUSEMOVE()
        ON_WM_MOUSELEAVE()
    END_MESSAGE_MAP()

     

    /***********************************************************
    OnRButtonDown
    子ウィンドウでマウスの右ボタンが押下されたイベント
    ***********************************************************/

    void CChildView::OnRButtonDown(UINT nFlags, CPoint point)
    {
        bDrawing = TRUE;
        SetCursor(LoadCursor(NULL,IDC_SIZEALL));

        //開始位置を終了位置を初期化
        stPoint.SetPoint(0, 0);
        edPoint.SetPoint(0, 0);
        //開始位置をセット
        stPoint = point;

        CWnd::OnRButtonDown(nFlags, point);
    }

    /***********************************************************
    OnRButtonUp
    子ウィンドウでマウスの右ボタンが離されたイベント
    ***********************************************************/

    void CChildView::OnRButtonUp(UINT nFlags, CPoint point)
    {
        if (bDrawing)
        {
            SetCursor(LoadCursor(NULL,IDC_ARROW));
            //終了位置をセット
            edPoint = point;
            //四角形を描画する
            DrawRectangle();
        }
        bDrawing = FALSE;

        CWnd::OnRButtonUp(nFlags, point);
    }


    /***********************************************************
    OnMouseMove
    マウスが移動中に発生するイベント
    ***********************************************************/

    void CChildView::OnMouseMove(UINT nFlags, CPoint point)
    {
        if (bDrawing)
        {
            SetCursor(LoadCursor(NULL,IDC_SIZEALL));
        }

        //WM_MOUSELEAVEイベントを受け取れるようにしておく
        //TrackMouseEventについてはDeveloperNetwork参照
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = WM_NCMOUSELEAVE;
        tme.hwndTrack = this->GetSafeHwnd();
        tme.dwHoverTime = 0; //関係ないので0をセットしておく
        TrackMouseEvent(&tme);

        CWnd::OnMouseMove(nFlags, point);
    }

     

    /***********************************************************
    OnMouseLeave
    子ウィンドウのクライアント領域をマウスが離れたイベント
    描画フラグとアイコンをリセットする
    ***********************************************************/

    void CChildView::OnMouseLeave()
    {
        bDrawing = FALSE;
        SetCursor(LoadCursor(NULL, IDC_ARROW));
        TRACE(L"OnMouseLeave¥r¥n");

        CWnd::OnMouseLeave();
    }

     

    /***********************************************************
    DrawRectangle
    開始Pointと終了Pointに対して四角形を描画する
    塗りつぶし色、線の色、線のスタイルはメニューの選択値を取得
    ***********************************************************/

    void CChildView::DrawRectangle()
    {
        CDC *pDC = this->GetDC();

        //四角形を塗りつぶすブラシ
        CBrush brs(theApp.selClr);
        CBrush *pOldBrush = pDC->SelectObject(&brs);

        //四角形を描画するペン
        //1より大きな幅を指定するとPS_SOLIDスタイルになるため幅は0とする
        CPen pen;
        pen.CreatePen(theApp.iSelStyle, 0, theApp.selLinfClr);
        CPen *pOldPen = pDC->SelectObject(&pen);

        //四角形を描画する領域
        CRect rect(stPoint,edPoint);
        //参考情報として出力ウィンドウに座標表示
        CString cs;
        cs.Format(L"st.x=%d st.y=%d ed.x=%d ed.y=%d¥r¥n", 
            stPoint.x, stPoint.y, edPoint.x, edPoint.y);
        TRACE(cs);

        //四角形を描画
        pDC->Rectangle(rect);

        //オブジェクトを戻す
        pDC->SelectObject(pOldBrush);
        pDC->SelectObject(pOldPen);
    }

     

    よろしければポチッと押してください

    プログラマー ブログランキングへ

     



    selected entries

    categories

    calendar

    S M T W T F S
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    << March 2024 >>

    profile

    others

    archives