在现代操作系统中,邮件通知窗口是一种常见的用户界面元素,它能够以一种非侵入性的方式提醒用户收到新邮件。本文将介绍如何使用ATL(Active Template Library)来创建一个类似Outlook的邮件通知窗口。
最近,阅读了Nick Wälti的文章,虽然文章中没有提供C++代码,但尝试使用ATL来实现类似的功能。
在实现过程中,定义了三个类:
以下是CNotifyWnd类的定义:
typedef CWinTraits<WS_CLIPCHILDREN | WS_POPUP | WS_VISIBLE, 0> CNotificationWinTraits;
class CNotifyWnd : public CWindowImpl<CNotifyWnd, CWindow, CNotificationWinTraits> {
...
CBmpButton* m_pButton;
...
public:
constructor
DECLARE_WND_CLASS("CNotifyWnd")
BEGIN_MSG_MAP(CNotifier)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
...
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
void CreateNotifyWindow();
private:
LRESULT ChangeOpacity(BYTE iFactor);
};
在OnCreate函数中,通过添加WS_EX_LAYERED扩展样式来修改窗口的样式,使其成为分层窗口。
if (ModifyStyleEx(0, WS_EX_LAYERED)) {
SetTimer(TIMER_ID, 30);
m_bTimerActive = TRUE;
}
ChangeOpacity函数用于调整窗口的透明度:
LRESULT CNotifyWnd::ChangeOpacity(BYTE iFactor) {
typedef DWORD (WINAPI *pSetLayeredWindowAttributes)(HWND, DWORD, BYTE, DWORD);
pSetLayeredWindowAttributes SetLayeredWindowAttributes;
HMODULE hDLL = LoadLibrary("user32");
if (hDLL) {
SetLayeredWindowAttributes = (pSetLayeredWindowAttributes) GetProcAddress(hDLL, "SetLayeredWindowAttributes");
ATLASSERT(SetLayeredWindowAttributes);
BOOL bRes = SetLayeredWindowAttributes(m_hWnd, RGB(255, 255, 255), iFactor, LWA_COLORKEY | LWA_ALPHA);
FreeLibrary(hDLL);
} else {
ATLASSERT(0);
}
return 0;
}
CBmpButton类是一个按钮类,它使用三个位图来表示其状态:正常、鼠标移动和按下。
class CBmpButton : public CWindowImpl<CBmpButton> {
UINT m_BitmapId[3];
UINT m_nCurrentBmp;
public:
DECLARE_WND_SUPERCLASS(_T("BitmapButton"), _T("Button"))
BEGIN_MSG_MAP(CBmpButton)
MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
private:
};
OnCreate函数将按钮设置为自绘模式:
LRESULT CBmpButton::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
ModifyStyle(0, BS_OWNERDRAW);
return 1;
}
函数如CBmpButton::OnLButtonDown、CBmpButton::OnLButtonUP、CBmpButton::OnMouseLeave将设置m_nCurrentBmp为适当的位图。
代码假设任务栏始终在底部(不考虑其他情况)。