【VC++】非矩形のダイアログを作成する

0

    <機能>

    (1)CreateEllipticRgnで楕円形のリージョン(Crgn)を作成します

    (2)CreateRectRgnで四角形のリージョン(CRgn)を作成します

    (3)CombineRgnでリージョンを結合します

    (4)SetWindowRgnで非矩形ウィンドウを作成します

     

    <動作検証&開発環境>
    Visual Studio Community 2017

     

    <イメージ>

    元のダイアログ

    MFC,非矩形ウィンドウ,画面イメージ1

    [楕円1個]ボタン押下により楕円形のウィンドウに切り替え

    MFC,非矩形ウィンドウ,画面イメージ2

    [楕円2個]ボタン押下により楕円形2個のウィンドウに切り替え

    MFC,非矩形ウィンドウ,画面イメージ3

    [楕円くり抜き]ボタン押下により左右の矩形と楕円をXORしたウィンドウに切り替え

    MFC,非矩形ウィンドウ,画面イメージ4

    CombineRgnされた矩形ダイアログと楕円ダイアログのXOR部分が透明になります

    MFC,非矩形ウィンドウ,RGN_XOR,

     

    <使い方>

    (1)MFCアプリケーションでプロジェクトを作成

    (2)アプリケーションの種類でダイアログベースを選択

    MFC,非矩形ウィンドウ,ウィザード,アプリケーションの種類,

    (3)生成されたクラスで基底クラスにCDialogを選択

    MFC,非矩形ウィンドウ,ウィザード,生成されたクラス,

    (4)MFCApplication1.rcを下記の通り修正

    ※MFCApplication1は各環境のプロジェクト名

    MFC,非矩形ウィンドウ,ウィザード,ダイアログアプリの既存バグ修正,

    (5)クラスウィザードでWM_NCHITTESTメッセージを追加

    ※非矩形ウィンドウはタイトルバーがなくなるためタイトルバー以外でドラッグ移動できるようにする

    MFC,非矩形ウィンドウ,クラスウィザード,

    (6)ボタンを追加します(ダイアログの中央に集めてください)

    MFC,非矩形ウィンドウ,リソース追加,

    (7)ソースを追加します

     

    MFCApplication1Dlg.h
    // CMFCApplication1Dlg ダイアログ
    class CMFCApplication1Dlg : public CDialog
    {
        //〜〜省略〜〜
    private:
        int m_iTh;
        int m_iEw;
        int m_iEh;
        CRect m_Rect;
    public:
        afx_msg void OnBnClickedEllipse2();
        afx_msg void OnBnClickedEllipse1();
        afx_msg void OnBnClickedButton();
        afx_msg LRESULT OnNcHitTest(CPoint point);
    };

    MFCApplication1Dlg.cpp
    // CMFCApplication1Dlg メッセージ ハンドラー
    BOOL CMFCApplication1Dlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        //〜〜省略〜〜
        // クライアント領域(タイトルバーなどを除いた領域)のサイズを取得
        GetClientRect(&m_Rect);
        // タイトルバーの高さ
        m_iTh = GetSystemMetrics(SM_CYCAPTION);
        // ダイアログ枠線の幅
        m_iEw = GetSystemMetrics(SM_CXFRAME);
        // サイズ調整
        m_iEw += 5;
        // ダイアログ枠線の高さ
        m_iEh = GetSystemMetrics(SM_CYFRAME);
        // サイズ調整
        m_iEh += 5;
        return TRUE;
    }
    /*************************************************
    関数名 OnBnClickedNormal
    機能   [もとに戻す] ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedNormal()
    {
        // ウィンドウを元に戻す
        SetWindowRgn(0, TRUE);
    }
    /*************************************************
    関数名 OnBnClickedEllipse1
    機能   [楕円1個] ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedEllipse1()
    {
        CRgn rgn;
        int th = m_iTh + m_iEh;
        // 指定した領域(左上X座標,左上Y座標,右下X座標,右下Y座標)で楕円リージョンを作成
        rgn.CreateEllipticRgn(m_iEw, th, m_Rect.Width()+m_iEw, m_Rect.Height()+th);
        // 非矩形ウィンドウを作成する
        SetWindowRgn(rgn, TRUE);
    }
    /*************************************************
    関数名 OnBnClickedEllipse2
    機能   [楕円2個] ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedEllipse2()
    {
        CRgn rgn, rgn1, rgn2;
        int th = m_iTh + m_iEh;
        // 指定した領域(左上X座標,左上Y座標,右下X座標,右下Y座標)で楕円リージョンを作成
        rgn1.CreateEllipticRgn(m_iEw, th, (m_Rect.Width() / 2)+m_iEw, m_Rect.Height()+th);
        rgn2.CreateEllipticRgn((m_Rect.Width() / 2)+m_iEw, th, m_Rect.Width() + m_iEw, m_Rect.Height() + th);
        rgn.CreateRectRgn(0, 0, 1, 1);
        // 2つのリージョン(rgn1とrgn2)を結合する
        // 結合するときに実行する操作はDeveloperNetwork参照
        int iResult = rgn.CombineRgn(&rgn1, &rgn2, RGN_OR);
        if (iResult == ERROR || iResult == NULLREGION)
        {
            AfxMessageBox(L"リージョン結合(CombineRgn)に失敗しました", MB_ICONERROR);
            OnBnClickedNormal();
            return;
        }
        rgn1.DeleteObject();
        rgn2.DeleteObject();
        // 非矩形ウィンドウを作成する
        SetWindowRgn(rgn, TRUE);
    }
    /*************************************************
    関数名 OnBnClickedButton
    機能   [楕円くり抜き] ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedButton()
    {
        CRgn rgn, rgn1, rgn2,rgn3;
        int th = m_iTh + m_iEh;
        int iResult;
        // 指定した領域で四角形リージョンを作成
        // 詳細はDeveloperNetwork参照
        rgn1.CreateRectRgn(m_iEw, th, 150, m_Rect.Height()+th);
        rgn2.CreateRectRgn(m_Rect.Width()-150, th, m_Rect.Width()+m_iEw, m_Rect.Height()+th);
        rgn.CreateRectRgn(0, 0, 1, 1);
        // リージョンを結合する
        iResult = rgn.CombineRgn(&rgn1, &rgn2, RGN_OR);
        if (iResult == ERROR || iResult == NULLREGION)
        {
            AfxMessageBox(L"リージョン結合(CombineRgn)に失敗しました",MB_ICONERROR);
            OnBnClickedNormal();
            return;
        }
        // 指定した領域で楕円リージョンを作成
        rgn3.CreateEllipticRgn(m_iEw, th, m_Rect.Width()+m_iEw, m_Rect.Height()+th);
        // rgnにrgn3を結合する
        // 結合する際に実行する操作としてRGN_XORを指定(詳細はDeveloperNetwork参照)
        iResult = rgn.CombineRgn(&rgn, &rgn3, RGN_XOR);
        if (iResult == ERROR || iResult == NULLREGION)
        {
            AfxMessageBox(L"リージョン結合(CombineRgn)に失敗しました", MB_ICONERROR);
            OnBnClickedNormal();
            return;
        }
        rgn1.DeleteObject();
        rgn2.DeleteObject();
        rgn3.DeleteObject();
        // 非矩形ウィンドウを作成する
        SetWindowRgn(rgn, TRUE);
    }
    /*************************************************
    関数名 OnNcHitTest
    機能   タイトルバーがなくてもクライアント領域でウィンドウ移動を可能とする
    *************************************************/

    LRESULT CMFCApplication1Dlg::OnNcHitTest(CPoint point)
    {
        return HTCAPTION;
    }

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


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



    selected entries

    categories

    calendar

    S M T W T F S
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
    << December 2018 >>

    profile

    others

    archives