使用 ATL 创建类似 Outlook 的通知窗口






4.92/5 (21投票s)
使用 ATL 创建 Outlook 风格的通知窗口。
引言
在使用 Microsoft® Outlook® 时,我们经常会看到邮件通知窗口,它会缓慢地出现并逐渐消失。它会显示邮件的摘要,包括发件人的姓名等。本文档描述了如何使用 ATL 构建这种窗口。
背景
我最近看到了一篇 Nick Wälti 的文章。但没有找到使用 C++ 代码实现相同功能的示例。因此,我尝试使用 ATL 实现类似的功能。
使用代码
有三个类:
CATLNotifyDialog
代表主要的 UI。CNotifyWnd
代表通知窗口。CBmpButton
代表位图按钮类,用作“关闭”按钮。
typedef CWinTraits <WS_CLIPCHILDREN | WS_POPUP |WS_VISIBLE ,0 > CNotificationWinTraits; class CNotifyWnd : public CWindowImpl<CNotifyWnd,CWindow,CNotificationWinTraits> { . . CBmpButton* m_pButton;//owner drawn button class public: //constructor DECLARE_WND_CLASS("CNotifyWnd") BEGIN_MSG_MAP(CNotifier) MESSAGE_HANDLER(WM_CREATE, OnCreate) . . . //reflect notifications to child REFLECT_NOTIFICATIONS() END_MSG_MAP() void CreateNotifyWindow(); private: LRESULT ChangeOpacity(BYTE iFactor); //message handler functions };
宏 REFLECT_NOTIFICATIONS
用于向子窗口发送消息。在这种情况下,按钮窗口是子窗口。在 OnCreate
函数中,通过添加 WS_EX_LAYERED
修改窗口的扩展样式。有关分层窗口的更多信息,请参阅 MSDN。
if ( ModifyStyleEx(0,WS_EX_LAYERED )) { //successfully modified style to make window as layered window //now use timer SetTimer(TIMER_ID ,30); m_bTimerActive=TRUE; }
该类的 ChangeOpacity
函数将为窗口带来半透明效果。
LRESULT CNotifyWnd::ChangeOpacity(BYTE iFactor) { //define function pointer typedef DWORD (WINAPI *pSetLayeredWindowAttributes)(HWND, DWORD, BYTE, DWORD); pSetLayeredWindowAttributes SetLayeredWindowAttributes; HMODULE hDLL = LoadLibrary ("user32"); if (hDLL ) { SetLayeredWindowAttributes = (pSetLayeredWindowAttributes) GetProcAddress(hDLL,"SetLayeredWindowAttributes"); ATLASSERT(SetLayeredWindowAttributes );//using WIN2k or onward ? BOOL bRes=SetLayeredWindowAttributes(m_hWnd,RGB(255,255,255), iFactor, LWA_COLORKEY | LWA_ALPHA); FreeLibrary(hDLL); } else { //not able to load library ATLASSERT(0); } return 0; }
类 CBmpButton
是一个按钮类。它使用三个位图来表示其状态,即正常、鼠标移动和按下。我无法为这个应用程序找到更好的位图,但更有艺术天赋的人可以将其做得更漂亮。
class CBmpButton :public CWindowImpl<CBmpButton> { UINT m_BitmapId[3];//represents three states of button UINT m_nCurrentBmp; public: DECLARE_WND_SUPERCLASS( _T("BitmapButton"), _T("Button") ) BEGIN_MSG_MAP(CBmpButton) //message handlers . . . MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) DEFAULT_REFLECTION_HANDLER()//this will handle messages refected by parent END_MSG_MAP() private: //message handlers };
以下是上述类的一个重要函数:
LRESULT CBmpButton::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { //make button owner drawn ModifyStyle(0,BS_OWNERDRAW); return 1; }
诸如 CBmpButton::OnLButtonDown
、CBmpButton::OnLButtonUP
、CBmpButton::OnMouseLeave
和 CBmpButton::OnMouseLeave
之类的函数会将 m_nCurrentBmp
设置为适当的位图。
//using this will enable WM_MOUSELEAVE notification TrackMouseEvent(&stMouseEvent);
代码假定任务栏始终位于底部(不考虑其他情况)。
关注点
它不使用 MFC(更轻量级!)。
历史
- v1.0 - 2006 年 8 月 11 日。