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

MSN Messenger 类型状态栏弹出消息框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (27投票s)

2001年10月15日

CPOL

3分钟阅读

viewsIcon

512076

downloadIcon

8328

MSN Messenger 类型状态栏弹出消息框

Sample Image - StatusBarMsgWnd.jpg

引言

最近,我发现 Windows 编程中一个有趣的事情是,当有人登录 MSN Messenger 时,状态栏会弹出消息窗口。 我想与大家分享这段代码,如果您也想使用它,但因为没有直接的 API 帮助而无法实现,那么这段代码可以帮助您。

如何使用源代码

在您的项目中包含以下文件

  • StatusBarMsgWnd.h
  • StatusBarMsgWnd.cpp

以下代码展示了如何创建 CStatusBarMsgWnd 对象并使用它来弹出窗口。我们使用一个伪构造函数 CreateObject(),因为我们想强制在堆上创建对象。 为了使普通构造函数不可用,我们将其设为 "private"。我们想在堆上创建对象,因为 PopMsg() 函数会触发定时器,并在函数返回后继续动画显示窗口的弹出和折叠。 因此,消息窗口应该保留在内存中,直到所有定时器都停止并且窗口折叠。 这样,父应用程序的响应速度比我之前使用的 Sleep() API 更快。 使用 Sleep() 会导致应用程序阻塞,直到窗口被销毁。

CStatusBarMsgWnd* t_MsgWnd = CStatusBarMsgWnd::CreateObject(
    _T("Some idiot has signed in !!"), // the message to be displayed
    180,                               // width of the window
    150,                               // height of window   
    4000,                              // time for the message to be displayed
    10,                                // delay for animation, how fast the window opens and closes
    CRect(30, 30, 130, 110),           // rectangle in the window where the 
                                       // message will be displayed 
    this                               // parent of the message window
    );
t_MsgWndMsg.PopMsg();

详细说明

PopMsg() 函数首先检查状态栏在桌面上的位置。只有四种情况:

  1. 状态栏在屏幕底部
  2. 状态栏在屏幕顶部
  3. 状态栏在屏幕左侧
  4. 状态栏在屏幕右侧

下面显示了 PopMsg() 函数的代码

void CStatusBarMsgWnd::PopMsg()
{
    if (CheckIfStatusBarBottom())  
        // Most frequent case is status bar at bottom
    {
        PopWndForBottomStatusBar();
    }
    else
    {
        if (CheckIfStatusBarTop())
        {
            PopWndForTopStatusBar();
        }
        else
        {
            if (CheckIfStatusBarLeft())
            {
                PopWndForLeftStatusBar();
            }
            else
            {
                PopWndForRightStatusBar();
            }
        }
    }
}

CheckIfStatusBarBottom()(或 CheckIfStatusBarTop()CheckIfStatusBarLeft())函数使用 GetSystemMetrics()SystemParatmeterInfo() API 来计算全屏区域以及屏幕上减去状态栏的区域。 然后,通过一些基本的中学数学知识,我们计算出状态栏的确切位置(底部、顶部、左侧或右侧),并以动画方式显示消息窗口。

真正的操作发生在 OnTimer() 函数中,该函数由 WM_TIMER 消息触发。有三个定时器:

  1. IDT_POP_WINDOW_TIMER -> 用于动画弹出窗口
  2. IDT_SHOW_WINDOW_TIMER -> 用于显示窗口并保持其位置一段时间
  3. IDT_COLLAPSE_WINDOW_TIMER -> 用于动画窗口折叠

还有三个常量,分别是 STP_BOTTOMSTP_TOPSTP_RIGHTSTP_LEFT,它们表示状态栏的位置。这些在 OnTimer() 中用于进行相应的动画计算。

窗口在使用 delete thisOnTimer() 函数中折叠后会自动删除。 这就是我们强制在堆上创建此窗口的原因。

类详细信息

CStatusBarMsgWnd 派生自 CFrameWnd。 标题栏在 OnCreate() 成员函数中删除。 创建了两个 CFont 对象,一个带有下划线,另一个没有下划线。 当鼠标位于窗口上方时,我们使用 OnMouseHover() 函数(针对 WM_MOUSEHOVER 消息)显示带有下划线的字体。 类似地,当鼠标离开窗口时,我们使用 OnMouseLeave() 函数(针对 WM_MOUSELEAVE 消息)显示不带下划线的字体。 初始化一个“手”型光标 m_hCursor,以便在鼠标悬停在窗口上时显示。

重写 OnLButtonDown() 函数,以适应您想要做的任何事情,以处理 WM_LBUTTONDOWN 消息。 目前,OnLButtonDown() 仅显示一个消息框。 您可以更改并执行任何操作以满足您的需求。

int CStatusBarMsgWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    ModifyStyle(WS_CAPTION, 0, 
        SWP_FRAMECHANGED); // removes title bar

    // Start creating two fonts, one underlined , 
    // other non underlined 
    
    // LOGFONT structure for font properties
    LOGFONT lf;
    ::ZeroMemory (&lf, sizeof (lf));
    lf.lfHeight = 100;
    lf.lfWeight = FW_BOLD;
    lf.lfUnderline = TRUE;

    ::strcpy (lf.lfFaceName, _T("Arial"));

    // Prepare for an underlined font
    m_fontMessageUnderline.CreatePointFontIndirect(&lf);

    // Prepare  an non underlined font
    lf.lfUnderline = FALSE;
    m_fontMessageNoUnderline.CreatePointFontIndirect(&lf);

    // Initialize the cursor.
    m_hCursor = ::LoadCursor(NULL, IDC_HAND);

    return 0;
}

如何使用演示项目 EXE

双击 popwnd.exe 并使用“消息菜单”来弹出消息窗口。

未来的工作,进行中...

  • MSN Messenger 在消息框中使用颜色方案,该颜色取自活动标题栏。
© . All rights reserved.