| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2752 人关注过本帖, 2 人收藏
标题:悬浮窗口开放源码
只看楼主 加入收藏
我菜119
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
帖 子:938
专家分:1756
注 册:2009-10-17
结帖率:98.26%
收藏(2)
已结贴  问题点数:100 回复次数:22 
悬浮窗口开放源码
上次发了一篇帖子,https://bbs.bccn.net/thread-390247-1-1.html,里面没有提供源码,今天再开一篇帖子,分享一下源码!
如果写的有问题,还忘大家指点!

对于MFC中有个悬浮窗口的类:CDockablePane,感兴趣的朋友可以自己上网查找资料研究学习!

下面讲解一下我自己实现的悬浮窗口类,通过一个对话框来实现的,对话框模式选择为POPUP类型,因为我这个没有标题栏,所以选择为none,ID为IDD_POPUP,

实现功能:初始化为一个小窗口,通过CStatic控件将图片显示在该窗口上,避免了窗口大小变化时处理WM_PAINT消息,这样小窗口展现的就是一张小图片了,当鼠标移入到小窗口时,处理WM_MOUSEMOVE消息,在该消息的处理函数中添加监控鼠标离开窗口事件,调用函数_TrackMouseEvent函数,关于这个函数的用法可查阅msdn,该函数发送WM_MOUSELEAVE消息,在该消息的处理函数中判断此时的鼠标位置是否处于窗口的客户区,如果不在的话,则窗口变小。

代码如下:
程序代码:
#ifndef CPOPWINDOW_H
#define CPOPWINDOW_H


class CPopWindow : public CDialog
{
    DECLARE_DYNAMIC(CPopWindow)

public:
    CPopWindow(CWnd* pParent = NULL);
    virtual ~CPopWindow();

    enum { IDD = IDD_POPUP };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);

public:
    void    SetSmallRect(CRect &Crect);
    void    SetBigRect(CRect &Crect);
    void    SetImage(CRect &Crect, LPCTSTR lpszPath);

public:
    afx_msg void    OnMouseMove(UINT nFlags, CPoint point);
    LRESULT         OnMouseLeave(WPARAM wParam, LPARAM lParam);

    DECLARE_MESSAGE_MAP()

public:
    CStatic          m_Static;
    CRect            m_rcBig;
    CRect            m_rcSmall;
};


#endif //CPOPWINDOW_H


程序代码:
#define IDC_MY_STATIC    2000

IMPLEMENT_DYNAMIC(CPopWindow, CDialog)

CPopWindow::CPopWindow(CWnd* pParent /*=NULL*/)
    : CDialog(CDlgInfo::IDD, pParent)
{
}

CPopWindow::~CPopWindow()
{
}

void CPopWindow::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPopWindow, CDialog)
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()


BOOL CPopWindow::SetImage(CRect &Crect, LPCTSTR lpszPath)
{
    HBITMAP hBmp=(HBITMAP)::LoadImage(
                            0,
                            lpszPath,
                            IMAGE_BITMAP,
                            Crect.Width(),
                            Crect.Height(),
                            LR_LOADFROMFILE
                        );
    m_Static.Create(NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP, Crect, this, IDC_MY_STATIC);
    m_Static.SetBitmap(hBmp);
}

void CPopWindow::SetSmallRect(CRect &Crect)
{
    m_rcSmall = Crect;
    MoveWindow(&m_rcSmall);
}

void CPopWindow::SetBigRect(CRect &Crect)
{
    m_rcBig = Crect;
}

void CPopWindow::OnMouseMove(UINT nFlags, CPoint point)
{
    TRACKMOUSEEVENT tme;
    tme.cbSize=sizeof(TRACKMOUSEEVENT); //监控鼠标离开
    tme.dwFlags = TME_LEAVE;
    tme.hwndTrack=this->m_hWnd;
    if(::_TrackMouseEvent(&tme))
    {
        m_Static.ShowWindow(SW_HIDE);
        MoveWindow(&m_rcBig);
    }
}

LRESULT CPopWindow::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
    CPoint pt;
    GetCursorPos(&pt);        //获取相对于屏幕的坐标
    if(!m_rcBig.PtInRect(pt))
    {
        m_Static.ShowWindow(SW_SHOW);
        MoveWindow(&m_rcSmall);
    }
    return TRUE;
}
注意:因为该对话框模式属于POPUP所以SetBigRect和SetSmallRect函数传入的Crect参数应该是相对于屏幕坐标,而SetImage传入的Crect参数是相对于客户区坐标


上述程序执行后,效果很好,应该达到了我们想要的结果吧,可是不然,如果创建一个子控件完全覆盖对话框,会导致对话框无法接收到WM_MOUSEMOVE消息,当然也就无法实现最后的效果,开始的时候我没有想到这一点,在我的第一篇帖子中TonyDeng提到了这一点,当时没有考虑,实际却遇到这样的问题,不得不说TonyDeng比我高明,所以为了避免这样的情况,我采用鼠标钩子,把所以发往消息队列中的WM_MOUSEMOVE消息截获到,自己先处理一下,然后再发给窗口,
代码如下:

程序代码:
#ifndef CPOPWINDOW_H
#define CPOPWINDOW_H


class CPopWindow : public CDialog
{
    DECLARE_DYNAMIC(CPopWindow)

public:
    CPopWindow(CWnd* pParent = NULL);
    virtual ~CPopWindow();

    enum { IDD = IDD_POPUP };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);

public:
    void    SetSmallRect(CRect &Crect);
    void    SetBigRect(CRect &Crect);
    void    SetImage(CRect &Crect, LPCTSTR lpszPath);

    DECLARE_MESSAGE_MAP()

public:
    CStatic            m_Static;
    CRect            m_rcBig;
    CRect            m_rcSmall;
};

程序代码:
#define IDC_MY_STATIC    2000

HHOOK        g_hHook;    //鼠标钩子句柄
CDlgInfo    *g_PopWindow;


LRESULT CALLBACK  MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if(wParam == WM_MOUSEMOVE)
    {
        POINT pt;
        pt = ((MOUSEHOOKSTRUCT *)lParam)->pt;
        CRect Crect;
        g_PopWindow->GetClientRect(&Crect);
        g_PopWindow->ClientToScreen(&Crect);
        if(!Crect.PtInRect(pt))
        {
            g_PopWindow->m_Static.ShowWindow(SW_SHOW);
            g_PopWindow->MoveWindow(&g_PopWindow->m_rcSmall);
        }
        else
        {           
            g_PopWindow->m_Static.ShowWindow(SW_HIDE);
            g_PopWindow->MoveWindow(&g_PopWindow->m_rcBig);
        }
    }
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}


IMPLEMENT_DYNAMIC(CPopWindow, CDialog)

CPopWindow::CPopWindow(CWnd* pParent /*=NULL*/)
    : CDialog(CDlgInfo::IDD, pParent)
{
    g_PopWindow = this;
    g_hHook = ::SetWindowsHookEx(WH_MOUSE, MouseProc, 0, GetCurrentThreadId());
}

CPopWindow::~CPopWindow()
{
    if(g_hHook)
    {
        ::UnhookWindowsHookEx(g_hHook);
    }
}

void CPopWindow::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPopWindow, CDialog)
END_MESSAGE_MAP()


BOOL CPopWindow::SetImage(CRect &Crect, LPCTSTR lpszPath)
{
    HBITMAP hBmp=(HBITMAP)::LoadImage(
                            0,
                            lpszPath,
                            IMAGE_BITMAP,
                            Crect.Width(),
                            Crect.Height(),
                            LR_LOADFROMFILE
                        );
    m_Static.Create(NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP, Crect, this, IDC_MY_STATIC);
    m_Static.SetBitmap(hBmp);
}

void CPopWindow::SetSmallRect(CRect &Crect)
{
    m_rcSmall = Crect;
    MoveWindow(&m_rcSmall);
}

void CPopWindow::SetBigRect(CRect &Crect)
{
    m_rcBig = Crect;
}


这样就避免了上述的问题了!

说明:CStatic控件的大小最好与小窗口的大小一样,小窗口看起来就好像是一张图片了!

如果大家还有更好的方法欢迎一起交流学习!
QQ群:234174291

[ 本帖最后由 我菜119 于 2012-12-13 23:12 编辑 ]
搜索更多相关主题的帖子: 对话框 标题栏 资料 
2012-12-13 23:10
yuccn
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:何方
等 级:版主
威 望:167
帖 子:6815
专家分:42393
注 册:2010-12-16
收藏
得分:5 
顶下,
鼓励直接上源代码,而不要贴代码

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2012-12-13 23:23
青春无限
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江苏
等 级:贵宾
威 望:24
帖 子:3452
专家分:19340
注 册:2012-3-31
收藏
得分:5 
支持

学 会看代码…学习写程序…学会搞开发…我的目标!呵呵是不是说大话啊!!一切皆可能
2012-12-13 23:25
阿鞠尼
Rank: 13Rank: 13Rank: 13Rank: 13
来 自:首尔
等 级:蒙面侠
威 望:5
帖 子:1467
专家分:4442
注 册:2012-5-30
收藏
得分:5 
楼主v5

喜欢睡觉 却经常熬夜
2012-12-13 23:42
小小战士
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:1
帖 子:569
专家分:1313
注 册:2012-11-3
收藏
得分:5 
重量级代码,高深

小小战士,战士中的战斗机!
2012-12-14 00:49
_peak
Rank: 5Rank: 5
来 自:90后
等 级:禁止访问
帖 子:83
专家分:347
注 册:2012-12-12
收藏
得分:5 
上次他发的时候也是百分帖

团结,进步,务实,创新!
2012-12-14 07:22
yaobao
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:4
帖 子:1854
专家分:4121
注 册:2012-10-25
收藏
得分:5 
高深啊

认认真真的学习,踏踏实实的走路:戒骄戒躁!!!
2012-12-14 08:34
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:5 
标记一下  备用

DO IT YOURSELF !
2012-12-14 09:05
一个孩子
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:356
专家分:954
注 册:2012-10-1
收藏
得分:5 
学习。

重要的不是结果,是求一个结果的过程,哪怕千难万难,当你有想要的结果时,你已走的很远
2012-12-14 10:39
crystall
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:184
专家分:809
注 册:2012-12-1
收藏
得分:5 
支持学习
2012-12-14 10:43
快速回复:悬浮窗口开放源码
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.080705 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved