OrangeMaker_logo
memo アイコン SDK-MFC 備忘録

Windows SDKやMFCに関するメモです。
(記載内容について正しいことを保証するものではありません。MSDN等で確認してください)

フレームなしのエアロなウィンドウの作り方

2009/11/13 作成

エアロなダイアログの作り方の説明のDwmExtendFrameIntoClientArea()の代わりにDwmEnableBlurBehindWindow()を使います。

リージョンを指定した例があまりないようなのお試しで確認した内容でメモっておきます。

前回同様にmfcのダイアログ的に整理するるまえに、mfcのリソースの設定でフレームなし(枠なし)の設定をおこなっているものとします。(必要に応じてModifyStyle()やGetWindowLong()/SetWindowLong()などでウィンドウスタイルを自分で変更しても可)

クラスの宣言部:
 BOOL m_bCompositEnable;	//Aero合成有効無効
 HRGN m_hDwmRgn;	//リージョンハンドル
VOID changeBlur(); //エアロフレームの設定&再設定 コンストラクタ: m_bCompositEnable = FALSE; OnInitDialog()ハンドラ: //初期状態設定 HRESULT hr = DwmIsCompositionEnabled(&m_bCompositEnable); //楕円リージョンを作成(同じリージョンを2個作成) CRect r; GetWindowRect(r); HRGN hWinRgn = CreateEllipticRgn(0,0,r.Width(),r.Height()); m_hDwmRgn = CreateEllipticRgn(0,0,r.Width(),r.Height()); //ウィンドウにリージョンを設定 int ret = SetWindowRgn(hWinRgn, TRUE); //エアロ設定 changeBlur(); OnCompositionChanged()ハンドラ: HRESULT hr = DwmIsCompositionEnabled(&m_bCompositEnable); changeBlur(); OnCtlColor()ハンドラ: if(m_bCompositEnable){ pDC->SetBkMode(TRANSPARENT); return static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)); } changeBlure()関数: VOID CAeroCircleDlg::changeBlur() { if(m_bCompositEnable){ HRESULT hr = S_OK; //Create and populate the BlurBehind structre DWM_BLURBEHIND bb = {0}; //Disable Blur Behind and Blur Region; bb.dwFlags = DWM_BB_ENABLE|DWM_BB_BLURREGION; bb.fEnable = true; bb.hRgnBlur = m_hDwmRgn; //Blur Behind hr =DwmEnableBlurBehindWindow(this->m_hWnd, &bb); if (SUCCEEDED(hr)) { //do more things } } this->Invalidate(); return ; } DestroyWindow()ハンドラ: if(m_bCompositEnable){ HRESULT hr = S_OK; //Create and populate the BlurBehind structre DWM_BLURBEHIND bb = {0}; bb.dwFlags = DWM_BB_ENABLE; bb.fEnable = false; //Blur Behind hr =DwmEnableBlurBehindWindow(this->m_hWnd, &bb); } //リージョンハンドルを破棄 DeleteObject(m_hDwmRgn);

DwmExtendFrameIntoClientArea()の使用方法とおおよそ同じですが、リージョンの設定でWindowに設定した同じリージョンを使いたくなるのですが、SetWindowRgn()で設定したリージョンハンドルは使いまわしができないので、同じ形のリージョンを2回生成しています。
MSDNを読む限りDwmEnableBehindWindow()に渡すリージョンハンドルは関数を実行後DeleteObject()しても問題ないようです。なので毎回リージョンのCreateをおこなってもよいように思います。また、上記例ではDestroyWindow()ハンドルでDisableにしていますがこれも必要ないのかもしれません。

上記例では、こんなウィンドウが表示されます。

フレームなしAeroウィンドウサンプル