braintag

公開してしまう備忘録

MFC Feature Pack スタッカブルなCMFCDesktopAlertWnd

MFC Feature PackのCMFCDesktopAlertWndでデスクトップの右下に、MSN Messanger的なポップアップアラートを出せることがわかった。

MSN Messager的なポップアップアラート Win32,MFC
このように、方法を結構調べてたんだけど、MS標準でできるとあって大喜び。
早速、Visual C++ 2008 Feature PackのSampleを参考に実装してみたらいい感じ。

ちなみにこのサンプル、日本語版ではインストールされないので
英語版を取ってくる必要がある。ここらへんはややこしいので割愛。


だがしかし、アラートが消える前にアラートが表示されると重なって表示されてしまい、古いほうが見えなくなってしまう。

よって、重ならずに、上に表示するように改造。

CMFCDesktopAlertWndを継承して、CMyDesktopAlertWndを作成。

ヘッダ:CMyDesktopAlertWnd.h

#include <array>

typedef std::tr1::array<bool, 20> popup_container;
class CMyDesktopAlertWnd : public CMFCDesktopAlertWnd
{
protected:

	static int m_heignt;
	static int m_x;
	static int m_bottom;

	int m_pos;
	static popup_container m_popup;

public:
	DECLARE_MESSAGE_MAP()
	afx_msg void OnClose();
public:
	virtual BOOL Create(CWnd* pWndOwner, UINT uiDlgResID, HMENU hMenu = NULL,CRuntimeClass* pRTIDlgBar = RUNTIME_CLASS(CMFCDesktopAlertDialog));
protected:
public:
	afx_msg void OnActivateApp(BOOL bActive, DWORD dwThreadID);
};

中身:CMyDesktopAlertWnd.cpp

#include "stdafx.h"
#include "CMyDesktopAlertWnd.h"

int CMyDesktopAlertWnd::m_x;
int CMyDesktopAlertWnd::m_heignt;
int CMyDesktopAlertWnd::m_bottom;
popup_container CMyDesktopAlertWnd::m_popup;

BEGIN_MESSAGE_MAP(CMyDesktopAlertWnd, CMFCDesktopAlertWnd)
	ON_WM_CLOSE()
	ON_WM_ACTIVATEAPP()
END_MESSAGE_MAP()

void CMyDesktopAlertWnd::OnClose()
{
	// TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
	m_popup[m_pos]=false;
	CMFCDesktopAlertWnd::OnClose();
}
BOOL CMyDesktopAlertWnd::Create(CWnd* pWndOwner, UINT uiDlgResID, HMENU hMenu,CRuntimeClass* pRTIDlgBar)
{
	// TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
	CPoint ptPos = CPoint(-1,-1);
	for (popup_container::size_type pos = 0; pos < m_popup.size(); ++pos) {
		if(m_popup[pos] ==false){
			m_popup[pos]=true;
			m_pos = pos;
			if(pos==0){
				break;
			}
			int y = m_bottom  - m_heignt*(pos+1);
			ptPos = CPoint(m_x,y);
			break;
		}
	}
	return CMFCDesktopAlertWnd::Create(pWndOwner, uiDlgResID, hMenu, ptPos,pRTIDlgBar);
}

void CMyDesktopAlertWnd::OnActivateApp(BOOL bActive, DWORD dwThreadID)
{
	CMFCDesktopAlertWnd::OnActivateApp(bActive, dwThreadID);

	if(!m_heignt){
		CRect rcShowPoint;
		this->GetWindowRect(rcShowPoint);
		m_heignt = rcShowPoint.bottom-rcShowPoint.top;
		m_x = rcShowPoint.left;
		m_bottom = rcShowPoint.bottom;
	}
	// TODO: ここにメッセージ ハンドラ コードを追加します。
}

呼び出し方法

	CMyDesktopAlertWnd* pPopup = new CMyDesktopAlertWnd;
	pPopup->Create (this, IDD_DIALOG1, 
				NULL, 
				RUNTIME_CLASS (CMyDlg));//CPointなしで呼び出すだけであとは同じ

やや強引なコードだけど、動きはそこそこいい感じ。

追記

2009-2-16 やっぱり穴があったので修正。
mapやdequeあたりでスマートに作れないもんかといろいろやってみたけど結局ベタな方法になってしまった。
あと、デスクトップの一番上まで行ってしまったら、とか全く考慮していない。