65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (21投票s)

2006年8月11日

CPOL

1分钟阅读

viewsIcon

56754

downloadIcon

1563

使用 ATL 创建 Outlook 风格的通知窗口。

Sample Image - Notifier_using_ATL.jpg

引言

在使用 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::OnLButtonDownCBmpButton::OnLButtonUPCBmpButton::OnMouseLeaveCBmpButton::OnMouseLeave 之类的函数会将 m_nCurrentBmp 设置为适当的位图。

    //using this will enable WM_MOUSELEAVE notification

    TrackMouseEvent(&stMouseEvent);

代码假定任务栏始终位于底部(不考虑其他情况)。

关注点

它不使用 MFC(更轻量级!)。

历史

  • v1.0 - 2006 年 8 月 11 日。
© . All rights reserved.