<機能>
(1)CreateEllipticRgnで楕円形のリージョン(Crgn)を作成します
(2)CreateRectRgnで四角形のリージョン(CRgn)を作成します
(3)CombineRgnでリージョンを結合します
(4)SetWindowRgnで非矩形ウィンドウを作成します
<動作検証&開発環境>
Visual Studio Community 2017
<イメージ>
元のダイアログ
[楕円1個]ボタン押下により楕円形のウィンドウに切り替え
[楕円2個]ボタン押下により楕円形2個のウィンドウに切り替え
[楕円くり抜き]ボタン押下により左右の矩形と楕円をXORしたウィンドウに切り替え
CombineRgnされた矩形ダイアログと楕円ダイアログのXOR部分が透明になります
<使い方>
(1)MFCアプリケーションでプロジェクトを作成
(2)アプリケーションの種類でダイアログベースを選択
(3)生成されたクラスで基底クラスにCDialogを選択
(4)MFCApplication1.rcを下記の通り修正
※MFCApplication1は各環境のプロジェクト名
(5)クラスウィザードでWM_NCHITTESTメッセージを追加
※非矩形ウィンドウはタイトルバーがなくなるためタイトルバー以外でドラッグ移動できるようにする
(6)ボタンを追加します(ダイアログの中央に集めてください)
(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;
}