类似QQ界面的实现

使用C语言实现类似QQ聊天界面抖动效果 其实,抖动效果就是通过不断改变窗口的位置来产生视觉上的震动感觉。具体来说,我们使用FindWindow函数来找到聊天窗口的句柄,然后使用SetWindowPos函数来改变窗口的位置。在上面的代码中,我们首先调用FindWindow函数来获取聊天窗口的句柄,然后进入一个循环,完成了5次抖动效果。在每一次循环中,我们使用SetWindowPos函数来改变窗口的位置,向左或向右移动10个像素。当然,在实际应用中,我们还需要考虑更多的细节问题,例如如何检测用户是否开启震动功能,如何更好地控制抖动强度等等。 阅读详情

类似QQ界面的实现

流浪狗

                                     下载源代码

一、需求分析:

   QQ是现在非常流行的一种及时通讯工具,它以强大的功能和漂亮、友好的界面获得了无数人的喜爱。本程序的目的是为了做出像QQ主界面的程序。

二、功能

   1)、实现OUTLOOK风格的QQ主界面。

   2)、实现自动隐藏功能。

   3)、实现系统托盘,并动态的更换图标,就像QQ上线时托盘所表现的动态画面。

三、说明:

  本程序复用了一些别人写的类,并在此基础上作出了部分修改,以实现本程序的功能,在此向CgfxOutBarCtrl类和CtrayIcon的作者表示感谢。

、具体实现

(一)、创建一个单文档的应用程序,命命为MyQQ,接下来都选默认选项。

1)编辑CMainFrame::PreCreateWindow

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

   ……

//设置窗口高度和宽度

   cs.cx=150;

   cs.cy=600;

  //去出菜单

   cs.hMenu=NULL;

//限定不能改变大小,去出最大化按钮

   cs.style&=~(WS_THICKFRAME|WS_MAXIMIZEBOX);

}

2)、编辑CMyQQApp::InitInstance在后面添加:

 //设置窗口文字 和窗口位置

AfxGetMainWnd()->SetWindowText("MyQQ");

AfxGetMainWnd()->SetWindowPos(&CWnd::wndTopMost,400,0,150,600,

SWP_SHOWWINDOW);

2)、准备一张图片  ,用做工具栏图标,删除原来的IDR_MAINFRAME图标,将新加的更名为IDR_MAINFRAME

(二)、实现QQ界面功能

  1)、准备。准备CgfxOutBarCtrl类(你可以在网上找到)和两张图片,用作大图标和小图标,命名为IDB_IMAGELISTIDB_SMALL_IMAGELIST。在QQ2005中将NEWFACE文件夹拷贝到当前工程目录下,准备一个声音文件folder.wav

2)、将CgfxOutBarCtrl和它要用到的一些类CgfxGroupEditCgfxPopupMenu一起导入工程。

3)、在MainFrm.h中添加包含#include "GfxOutBarCtrl.h",并添加属性CgfxOutBarCtrl wndBar CimageList imaLarge, imaSmall

4)、重载CmainFrameOnCreateClient函数

 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

    // TODO: Add your specialized code here and/or call the base class

        DWORD dwf = CGfxOutBarCtrl::fDragItems|

                CGfxOutBarCtrl::fEditGroups|

                CGfxOutBarCtrl::fEditItems|

                CGfxOutBarCtrl::fRemoveGroups|

                CGfxOutBarCtrl::fRemoveItems|

                CGfxOutBarCtrl::fAddGroups|

                CGfxOutBarCtrl::fAnimation;

    RECT rect;

    GetClientRect(&rect);

    wndBar.Create(WS_CHILD|WS_VISIBLE,rect,this,NULL,dwf);

    wndBar.SetOwner(this);

     //此处必须以真彩色显示

    imaLarge.Create(40,40,ILC_COLOR24,0,0);

    imaSmall.Create(16,16,ILC_COLOR24,0,0);

//此处由于将QQ里的一百张图片全部加载进内存,所以要耗费很多内存,可以在寻求一个更好的办法

    for(int i=1;i<=100;i++)

    {

        CBitmap pBitmap;

        CString str;

        str.Format("NEWFACE//%d.bmp",i);

        //加载位图

        HBITMAP hBitmap; //定义位图对象句柄

        hBitmap=(HBITMAP):: LoadImage

            ( AfxGetInstanceHandle(),

             //取得应用程序句柄

            str,

             //位图文件名

            IMAGE_BITMAP,

           //类型为Windows位图

            0,0,

            LR_LOADFROMFILE);

            if(NULL==hBitmap)

            {

                AfxMessageBox("不能打开文件");

                return FALSE;

            }

           

            pBitmap.Attach(hBitmap);

            imaLarge.Add(&pBitmap,RGB(0,0,0));

 

  CBitmap sBitmap;

        str.Format("NEWFACE//%d_m.bmp",i);

        //加载位图

        hBitmap=(HBITMAP):: LoadImage

            ( AfxGetInstanceHandle(),

             //取得应用程序句柄

            str,

             //位图文件名

            IMAGE_BITMAP,

           //类型为Windows位图

            0,0,

            LR_LOADFROMFILE);

            if(NULL==hBitmap)

            {

                AfxMessageBox("不能打开文件");

                return FALSE;

            }

           

            sBitmap.Attach(hBitmap);

            imaSmall.Add(&sBitmap,RGB(0,0,0));

    }

         

    wndBar.SetImageList(&imaLarge, CGfxOutBarCtrl::fLargeIcon);

    wndBar.SetImageList(&imaSmall, CGfxOutBarCtrl::fSmallIcon);

 

    wndBar.SetAnimationTickCount(10);

wndBar.SetAnimSelHighlight(200);

wndBar.SetIfQueryRemove(true);

 

    wndBar.AddFolder("我的好友", 0);

    wndBar.AddFolder("陌生人", 1);

    wndBar.AddFolder("黑名单", 2);

 

 

    wndBar.InsertItem(0, 0, "午夜", 0, 0);

    wndBar.InsertItem(0, 1, "浪子", 1, 0);

    wndBar.InsertItem(0, 2, "未来之城", 2, 0);

    wndBar.InsertItem(0, 3, "黑色幽默", 3, 0);

    wndBar.InsertItem(0, 4, "想飞", 4, 0);

……//这儿省略一部分

 

    wndBar.InsertItem(2, 0, "酒鬼", 80, 0);

    wndBar.InsertItem(2, 1, "痴人", 81, 0);

    wndBar.InsertItem(2, 2, "逐梦人", 82, 0);

    wndBar.InsertItem(2, 3, "陆小凤", 83, 0);

 

    wndBar.SetSelFolder(0);

 

    return TRUE;

}

完成后我们可以编译改程序,但是当点击陌生人时,由于里面没有成员,本不应该出现下拉按钮,但是出现了,当我们点击时,就会发生溢出。所以修改原来的CgfxOutBarCtrl源文件的OnPaint函数:

if (l < GetItemCount() - 1

 

        //Modified By  jamiandy@163.com

        //Author:流浪狗  Date:2005Y-05M-13D::12:13

       //在此处修改原来的语句,以便使得当item为0时,不出现向下的按钮,防止溢出

        //修改if (l < GetItemCount() - 1)为if (l < GetItemCount() - 1&&GetItemCount()!=0)

         &&GetItemCount()!=0)

        {

            ……//此处省略

        }

        else bDownArrow = false;

5)、修改CgfxOutBarCtrl类的OnLButtonDown,在里面适当位置即响应点击FOLDER时的地方添加语句:

  BOOL r = sndPlaySound("sound//folder.wav",SND_SYNC |SND_NODEFAULT);//播放WAV

  ASSERT(r);   r = sndPlaySound("",SND_ASYNC|SND_NODEFAULT);//停止播放

6)、在CmainFrame的头文件中,DECLARE_MESSAGE_MAP()上面添加afx_msg long OnOutBarNotify(WPARAM wParam, LPARAM lParam);消息映射,在实现文件中,BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)和END_MESSAGE_MAP()之间加入ON_MESSAGE(WM_OUTBAR_NOTIFY, OnOutBarNotify)。编写代码:

long CMainFrame::OnOutBarNotify(WPARAM wParam, LPARAM lParam)

{

    switch (wParam)

    {

 

        case NM_SENDMSG:

            {

                 int index = (int) lParam;

//弹出发送消息对话框

                DoMsgDialog();

            }

            return 1;

              //你可以在此添加你自己的消息,从CGfxOutBarCtrl中发送

    }

    return 0;

}

修改CgfxOutBarCtrl中的代码,实现向主框架发送消息,可以用GetOwner()->SendMessage(WM_OUTBAR_NOTIFY, NM_SENDMSG, iHitInternal2)实现,具体情况可以根据需要改变。然后从主框架中处理消息,从而保证用主框架来响应外界的消息。

 

经过这些,基本的QQ界面实现了,现在编译运行,就可以看到漂亮的界面了。

 

(三)、实现QQ的自动隐藏。

原理:在检测到窗口靠近屏幕边缘时,移动窗口到屏幕外边,从而实现自动隐藏,当检测到鼠标移近时,将窗口显示出来,从而实现自动弹出,实现过程如下:

1)、在MainFrm.cpp中头部加入:

int             ScreenX;                //屏幕宽度

int             ScreenY;                //屏幕高度

int             alignType;          //全局变量,用于记录窗体停靠状态

enum

{

    ALIGN_NONE,                                 //不停靠

        ALIGN_TOP,                                      //停靠上边

        ALIGN_LEFT,                                 //停靠左边

        ALIGN_RIGHT                                 //停靠右边

};

 

#define NEAR_SIZE 5 //定义自动停靠有效距离

#define NEAR_SIDE 3 //窗体隐藏后在屏幕上保留的像素,以使鼠标可以触及

OnCreate中加入:

ScreenX = GetSystemMetrics(SM_CXSCREEN);

ScreenY = GetSystemMetrics(SM_CYSCREEN);

SetTimer(WM_TIMER,50,NULL);

NearSide(GetSafeHwnd());

2)、添加NearSide函数

void CMainFrame::NearSide(HWND hWnd)

{

    int             change = 0;

    RECT            rect;

   

    GetWindowRect(&rect);

    alignType = ALIGN_NONE;

    if (rect.left < NEAR_SIZE)

    {

        alignType = ALIGN_LEFT;

        if ((rect.left != 0) && rect.right != NEAR_SIDE)

        {

            rect.right -= rect.left;

            rect.left = 0;

            change = 1;

        }

    }

    else if (rect.right > ScreenX - NEAR_SIZE)

    {

        alignType = ALIGN_RIGHT;

        if (rect.right != ScreenX && rect.left != ScreenX - NEAR_SIDE)

        {

            rect.left += (ScreenX - rect.right);

            rect.right = ScreenX;

            change = 1;

        }

    }

    //调整上下

    if (rect.top < NEAR_SIZE)

    {

        alignType = ALIGN_TOP;

        if (rect.top != 0 && rect.bottom != NEAR_SIDE)

        {

            rect.bottom -= rect.top;

            rect.top = 0;

            change = 1;

        }

    }

    if (change)

    {

        MoveWindow(rect.left, rect.top, rect.right - rect.left,

            rect.bottom - rect.top, TRUE);

    }

 

}

3)、重载OnTimer,编辑

void CMainFrame::OnTimer(UINT nIDEvent)

{

    // TODO: Add your message handler code here and/or call default

    POINT           pt;

    RECT            rc;

   

    GetCursorPos(&pt);

    GetWindowRect(&rc);

    if (!PtInRect(&rc, pt)) //若鼠标不在窗体内,隐藏窗体.

    {

        KillTimer(WM_TIMER);

        HideSide(GetSafeHwnd(),TRUE);

    }

 

    CFrameWnd::OnTimer(nIDEvent);

}

4)、添加HideSide,编辑:

void CMainFrame::HideSide(HWND hWnd, BOOL hide)

{

    RECT            rc;

    int             moves = 4;  //动画滚动窗体的步数,如果你觉得不够平滑,可以增大该值.

    int             xStep, yStep;

    int             xEnd, yEnd;

    int             width;

    int             height;

    register int    i;

   

    GetWindowRect(&rc);

    width = rc.right - rc.left;

    height = rc.bottom - rc.top;

    //下边判断窗体该如何移动,由停靠方式决定

    switch (alignType)

    {

    case ALIGN_TOP:

        {

            //向上移藏

            xStep = 0;

            xEnd = rc.left;

            if (hide)

            {

                yStep = -rc.bottom / moves;

                yEnd = -height + NEAR_SIDE;

            }

            else

            {

                yStep = -rc.top / moves;

                yEnd = 0;

            }

            break;

        }

    case ALIGN_LEFT:

        {

            //向左移藏

            //此处省略,类似向上隐藏

                        ……

            break;

        }

    case ALIGN_RIGHT:

        {

            //向右移藏

            //此处省略,类似向上隐藏

                        ……

            break;

        }

    default:

        return;

    }

    //动画滚动窗体.

    for (i = 0; i < moves; i++)

    {

        rc.left += xStep;

        rc.top += yStep;

 

        SetWindowPos(NULL, rc.left, rc.top, 0, 0,

            SWP_NOSIZE | SWP_NOSENDCHANGING);

        RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);

       

        Sleep(5);

    }

   

    SetWindowPos(NULL, xEnd, yEnd, 0, 0, SWP_NOSIZE);

 

    if (!hide)  //如果窗体已被显示,设置定时器.监视鼠标.

    {

        SetTimer(WM_TIMER, 50, NULL);

    }

 

}

5)、最后重载OnNcMouseMove,添加代码如下:

   void CMainFrame::OnNcMouseMove(UINT nHitTest, CPoint point)

{

    RECT            rc;

    GetWindowRect(&rc);

    if (rc.left < 0 || rc.top < 0 || rc.right > ScreenX)    //未显示

    {

        HideSide(GetSafeHwnd(), FALSE);

    }else

    {

        HideSide(GetSafeHwnd(), FALSE);

        SetTimer(WM_TIMER,50,NULL);

    }

    CFrameWnd::OnNcMouseMove(nHitTest, point);

}

这样,自动隐藏的功能就实现了,当你把它拖到屏幕边上的时候,就自动消失了,当鼠标移近时,又自动出现。

(四)、托盘程序的实现

  (1)、将CtrayIcon(你可以从网上找到它)加入工程。添加两个图标,分别命名为IDI_ONLINE和IDI_OFFLINE,表示交替的两个图标。在MainFrm.h中加入私有变量CTrayIcon   m_trayIcon; BOOL IsOnline;在构造函数中对其初始化,m_trayIcon(IDR_TRAYICON),IsOnline=FALSE。在MainFrm.cpp中添加#define WM_MY_TRAY_NOTIFICATION WM_USER+0

  (2)、在OnCreate中添加:

m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);

    m_trayIcon.SetIcon(IDI_ONLINE);

    SetTimer(2,500,NULL);

 (3)、修改OnTimer:

     if(nIDEvent==2)

    {

        IsOnline=!IsOnline;

        m_trayIcon.SetIco(IsOnlineIDI_ONLINE:IDI_OFFLINE);

    }

这样就可以动态改变图标了。

到此为止,我们要求的所有功能都实现了,现在可以编译运行,修改不正确的地方。效果如图所示:

   cs.style&=~(WS_THICKFRAME|WS_MAXIMIZEBOX);

}

2)、编辑CMyQQApp::InitInstance在后面添加:

 //设置窗口文字 和窗口位置

AfxGetMainWnd()->SetWindowText("MyQQ");

AfxGetMainWnd()->SetWindowPos(&CWnd::wndTopMost,400,0,150,600,

SWP_SHOWWINDOW);

2)、准备一张图片  ,用做工具栏图标,删除原来的IDR_MAINFRAME图标,将新加的更名为IDR_MAINFRAME

(二)、实现QQ界面功能

  1)、准备。准备CgfxOutBarCtrl类(你可以在网上找到)和两张图片,用作大图标和小图标,命名为IDB_IMAGELISTIDB_SMALL_IMAGELIST。在QQ2005中将NEWFACE文件夹拷贝到当前工程目录下,准备一个声音文件folder.wav

2)、将CgfxOutBarCtrl和它要用到的一些类CgfxGroupEditCgfxPopupMenu一起导入工程。

3)、在MainFrm.h中添加包含#include "GfxOutBarCtrl.h",并添加属性CgfxOutBarCtrl wndBar CimageList imaLarge, imaSmall

4)、重载CmainFrameOnCreateClient函数

 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

    // TODO: Add your specialized code here and/or call the base class

        DWORD dwf = CGfxOutBarCtrl::fDragItems|

                CGfxOutBarCtrl::fEditGroups|

                CGfxOutBarCtrl::fEditItems|

                CGfxOutBarCtrl::fRemoveGroups|

                CGfxOutBarCtrl::fRemoveItems|

                CGfxOutBarCtrl::fAddGroups|

                CGfxOutBarCtrl::fAnimation;

    RECT rect;

    GetClientRect(&rect);

    wndBar.Create(WS_CHILD|WS_VISIBLE,rect,this,NULL,dwf);

    wndBar.SetOwner(this);

     //此处必须以真彩色显示

    imaLarge.Create(40,40,ILC_COLOR24,0,0);

    imaSmall.Create(16,16,ILC_COLOR24,0,0);

//此处由于将QQ里的一百张图片全部加载进内存,所以要耗费很多内存,可以在寻求一个更好的办法

    for(int i=1;i<=100;i++)

    {

        CBitmap pBitmap;

        CString str;

        str.Format("NEWFACE//%d.bmp",i);

        //加载位图

        HBITMAP hBitmap; //定义位图对象句柄

        hBitmap=(HBITMAP):: LoadImage

            ( AfxGetInstanceHandle(),

             //取得应用程序句柄

            str,

             //位图文件名

            IMAGE_BITMAP,

           //类型为Windows位图

            0,0,

            LR_LOADFROMFILE);

            if(NULL==hBitmap)

            {

                AfxMessageBox("不能打开文件");

                return FALSE;

            }

           

            pBitmap.Attach(hBitmap);

            imaLarge.Add(&pBitmap,RGB(0,0,0));

 

  CBitmap sBitmap;

        str.Format("NEWFACE//%d_m.bmp",i);

        //加载位图

        hBitmap=(HBITMAP):: LoadImage

            ( AfxGetInstanceHandle(),

             //取得应用程序句柄

            str,

             //位图文件名

            IMAGE_BITMAP,

           //类型为Windows位图

            0,0,

            LR_LOADFROMFILE);

            if(NULL==hBitmap)

            {

                AfxMessageBox("不能打开文件");

                return FALSE;

            }

           

            sBitmap.Attach(hBitmap);

            imaSmall.Add(&sBitmap,RGB(0,0,0));

    }

         

    wndBar.SetImageList(&imaLarge, CGfxOutBarCtrl::fLargeIcon);

    wndBar.SetImageList(&imaSmall, CGfxOutBarCtrl::fSmallIcon);

 

    wndBar.SetAnimationTickCount(10);

wndBar.SetAnimSelHighlight(200);

wndBar.SetIfQueryRemove(true);

 

    wndBar.AddFolder("我的好友", 0);

    wndBar.AddFolder("陌生人", 1);

    wndBar.AddFolder("黑名单", 2);

 

 

    wndBar.InsertItem(0, 0, "午夜", 0, 0);

    wndBar.InsertItem(0, 1, "浪子", 1, 0);

    wndBar.InsertItem(0, 2, "未来之城", 2, 0);

    wndBar.InsertItem(0, 3, "黑色幽默", 3, 0);

    wndBar.InsertItem(0, 4, "想飞", 4, 0);

……//这儿省略一部分

 

    wndBar.InsertItem(2, 0, "酒鬼", 80, 0);

    wndBar.InsertItem(2, 1, "痴人", 81, 0);

    wndBar.InsertItem(2, 2, "逐梦人", 82, 0);

    wndBar.InsertItem(2, 3, "陆小凤", 83, 0);

 

    wndBar.SetSelFolder(0);

 

    return TRUE;

}

完成后我们可以编译改程序,但是当点击陌生人时,由于里面没有成员,本不应该出现下拉按钮,但是出现了,当我们点击时,就会发生溢出。所以修改原来的CgfxOutBarCtrl源文件的OnPaint函数:

if (l < GetItemCount() - 1

 

        //Modified By  jamiandy@163.com

        //Author:流浪狗  Date:2005Y-05M-13D::12:13

       //在此处修改原来的语句,以便使得当item为0时,不出现向下的按钮,防止溢出

        //修改if (l < GetItemCount() - 1)为if (l < GetItemCount() - 1&&GetItemCount()!=0)

         &&GetItemCount()!=0)

        {

            ……//此处省略

        }

        else bDownArrow = false;

5)、修改CgfxOutBarCtrl类的OnLButtonDown,在里面适当位置即响应点击FOLDER时的地方添加语句:

  BOOL r = sndPlaySound("sound//folder.wav",SND_SYNC |SND_NODEFAULT);//播放WAV

  ASSERT(r);   r = sndPlaySound("",SND_ASYNC|SND_NODEFAULT);//停止播放

6)、在CmainFrame的头文件中,DECLARE_MESSAGE_MAP()上面添加afx_msg long OnOutBarNotify(WPARAM wParam, LPARAM lParam);消息映射,在实现文件中,BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)和END_MESSAGE_MAP()之间加入ON_MESSAGE(WM_OUTBAR_NOTIFY, OnOutBarNotify)。编写代码:

long CMainFrame::OnOutBarNotify(WPARAM wParam, LPARAM lParam)

{

    switch (wParam)

    {

 

        case NM_SENDMSG:

            {

                 int index = (int) lParam;

//弹出发送消息对话框

                DoMsgDialog();

            }

            return 1;

              //你可以在此添加你自己的消息,从CGfxOutBarCtrl中发送

    }

    return 0;

}

修改CgfxOutBarCtrl中的代码,实现向主框架发送消息,可以用GetOwner()->SendMessage(WM_OUTBAR_NOTIFY, NM_SENDMSG, iHitInternal2)实现,具体情况可以根据需要改变。然后从主框架中处理消息,从而保证用主框架来响应外界的消息。

 

经过这些,基本的QQ界面实现了,现在编译运行,就可以看到漂亮的界面了。

 

(三)、实现QQ的自动隐藏。

原理:在检测到窗口靠近屏幕边缘时,移动窗口到屏幕外边,从而实现自动隐藏,当检测到鼠标移近时,将窗口显示出来,从而实现自动弹出,实现过程如下:

1)、在MainFrm.cpp中头部加入:

int             ScreenX;                //屏幕宽度

int             ScreenY;                //屏幕高度

int             alignType;          //全局变量,用于记录窗体停靠状态

enum

{

    ALIGN_NONE,                                 //不停靠

        ALIGN_TOP,                                      //停靠上边

        ALIGN_LEFT,                                 //停靠左边

        ALIGN_RIGHT                                 //停靠右边

};

 

#define NEAR_SIZE 5 //定义自动停靠有效距离

#define NEAR_SIDE 3 //窗体隐藏后在屏幕上保留的像素,以使鼠标可以触及

OnCreate中加入:

ScreenX = GetSystemMetrics(SM_CXSCREEN);

ScreenY = GetSystemMetrics(SM_CYSCREEN);

SetTimer(WM_TIMER,50,NULL);

NearSide(GetSafeHwnd());

2)、添加NearSide函数

void CMainFrame::NearSide(HWND hWnd)

{

    int             change = 0;

    RECT            rect;

   

    GetWindowRect(&rect);

    alignType = ALIGN_NONE;

    if (rect.left < NEAR_SIZE)

    {

        alignType = ALIGN_LEFT;

        if ((rect.left != 0) && rect.right != NEAR_SIDE)

        {

            rect.right -= rect.left;

            rect.left = 0;

            change = 1;

        }

    }

    else if (rect.right > ScreenX - NEAR_SIZE)

    {

        alignType = ALIGN_RIGHT;

        if (rect.right != ScreenX && rect.left != ScreenX - NEAR_SIDE)

        {

            rect.left += (ScreenX - rect.right);

            rect.right = ScreenX;

            change = 1;

        }

    }

    //调整上下

    if (rect.top < NEAR_SIZE)

    {

        alignType = ALIGN_TOP;

        if (rect.top != 0 && rect.bottom != NEAR_SIDE)

        {

            rect.bottom -= rect.top;

            rect.top = 0;

            change = 1;

        }

    }

    if (change)

    {

        MoveWindow(rect.left, rect.top, rect.right - rect.left,

            rect.bottom - rect.top, TRUE);

    }

 

}

3)、重载OnTimer,编辑

void CMainFrame::OnTimer(UINT nIDEvent)

{

    // TODO: Add your message handler code here and/or call default

    POINT           pt;

    RECT            rc;

   

    GetCursorPos(&pt);

    GetWindowRect(&rc);

    if (!PtInRect(&rc, pt)) //若鼠标不在窗体内,隐藏窗体.

    {

        KillTimer(WM_TIMER);

        HideSide(GetSafeHwnd(),TRUE);

    }

 

    CFrameWnd::OnTimer(nIDEvent);

}

4)、添加HideSide,编辑:

void CMainFrame::HideSide(HWND hWnd, BOOL hide)

{

    RECT            rc;

    int             moves = 4;  //动画滚动窗体的步数,如果你觉得不够平滑,可以增大该值.

    int             xStep, yStep;

    int             xEnd, yEnd;

    int             width;

    int             height;

    register int    i;

   

    GetWindowRect(&rc);

    width = rc.right - rc.left;

    height = rc.bottom - rc.top;

    //下边判断窗体该如何移动,由停靠方式决定

    switch (alignType)

    {

    case ALIGN_TOP:

        {

            //向上移藏

            xStep = 0;

            xEnd = rc.left;

            if (hide)

            {

                yStep = -rc.bottom / moves;

                yEnd = -height + NEAR_SIDE;

            }

            else

            {

                yStep = -rc.top / moves;

                yEnd = 0;

            }

            break;

        }

    case ALIGN_LEFT:

        {

            //向左移藏

            //此处省略,类似向上隐藏

                        ……

            break;

        }

    case ALIGN_RIGHT:

        {

            //向右移藏

            //此处省略,类似向上隐藏

                        ……

            break;

        }

    default:

        return;

    }

    //动画滚动窗体.

    for (i = 0; i < moves; i++)

    {

        rc.left += xStep;

        rc.top += yStep;

 

        SetWindowPos(NULL, rc.left, rc.top, 0, 0,

            SWP_NOSIZE | SWP_NOSENDCHANGING);

        RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);

       

        Sleep(5);

    }

   

    SetWindowPos(NULL, xEnd, yEnd, 0, 0, SWP_NOSIZE);

 

    if (!hide)  //如果窗体已被显示,设置定时器.监视鼠标.

    {

        SetTimer(WM_TIMER, 50, NULL);

    }

 

}

5)、最后重载OnNcMouseMove,添加代码如下:

   void CMainFrame::OnNcMouseMove(UINT nHitTest, CPoint point)

{

    RECT            rc;

    GetWindowRect(&rc);

    if (rc.left < 0 || rc.top < 0 || rc.right > ScreenX)    //未显示

    {

        HideSide(GetSafeHwnd(), FALSE);

    }else

    {

        HideSide(GetSafeHwnd(), FALSE);

        SetTimer(WM_TIMER,50,NULL);

    }

    CFrameWnd::OnNcMouseMove(nHitTest, point);

}

这样,自动隐藏的功能就实现了,当你把它拖到屏幕边上的时候,就自动消失了,当鼠标移近时,又自动出现。

(四)、托盘程序的实现

  (1)、将CtrayIcon(你可以从网上找到它)加入工程。添加两个图标,分别命名为IDI_ONLINE和IDI_OFFLINE,表示交替的两个图标。在MainFrm.h中加入私有变量CTrayIcon   m_trayIcon; BOOL IsOnline;在构造函数中对其初始化,m_trayIcon(IDR_TRAYICON),IsOnline=FALSE。在MainFrm.cpp中添加#define WM_MY_TRAY_NOTIFICATION WM_USER+0

  (2)、在OnCreate中添加:

m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);

    m_trayIcon.SetIcon(IDI_ONLINE);

    SetTimer(2,500,NULL);

 (3)、修改OnTimer:

     if(nIDEvent==2)

    {

        IsOnline=!IsOnline;

        m_trayIcon.SetIco(IsOnlineIDI_ONLINE:IDI_OFFLINE);

    }

这样就可以动态改变图标了。

到此为止,我们要求的所有功能都实现了,现在可以编译运行,修改不正确的地方。效果如图所示:

C#实现类似QQ音乐界面的完整指南 本文还有配套的精品资源,点击获取 简介:本文将介绍如何使用C#语言和***开发环境创建一个类似QQ音乐的应用程序界面。我们将深入探讨创建项目、控件使用、界面布局、皮肤主题、事件处理、多媒体播放、数据库集成、网络通信以及用户体验等关键步骤。通过这些步骤,开发人员可以学习到构建现代、动态UI的技巧,并提升在C#开发上的多项技能。 1. C#基础和Windows Forms... 阅读详情

相关推荐

用C#实现类似QQ面板的界面设计

本文还有配套的精品资源,点击获取 简介:本文详细介绍了如何用C#语言创建一个与QQ即时通讯软件界面相似的面板。项目将涵盖C#中GUI设计、事件处理和交互逻辑等方面的知识。开发者将通过模仿QQ面板的设计,学习使用.NET平台和Visual Studio IDE,掌握如何使用Windows Forms应用来构建用户界面。此外,还将探讨性能优化、测试和调试的实践方法。 1....

weixin_42186015的博客 1007

CGfxOutBarCtrl类源码下载和使用实例

摘要:VC/C++源码,控件相关,CGfxOutBarCtrl  CGfxOutBarCtrl类源码和使用实例,类库中包括了如下文件的下载:   GfxOutBarCtrl.h、GfxOutBarCtrl.cpp、GfxGroupEdit.cpp、GfxGroupEdit.h、GfxPopupMenu.cpp、GfxPopupMenu.h。具体的使用方法如下:在stdafx.h中输入:   #ifndef WINVER // 允许使用 Windows 95 和 Windows NT 4 或更高版本的特定功能。   #define WINVER 0x0500 //为 Windows98 和 W

CGfxOutBarCtrl类及使用示例和使用文档

里面包括CGfxOutBarCtrl的这个类的源码 还有一个改进版的示例及使用说明 就是那种visual studio工具箱类似的菜单 可以看看

CodeGuru: An Outlook98 bar-like control

Download demo and code 142KThis is another control which trys to reproduce an Outlook98-like bar. It try to have a more near look and fell with the original outlook bar, and support Folders, editi

happy5856的专栏 1297

CMFCOutlookBar add CDialog

1.准备两个对话框资源 设置对话框的Border属性为None,Style属性为Child,给两个对话框设置两个类 2、在CMainFrame类创建成员变量 创建三个成员变量,一个OutLook风格的选项卡,两个对话框。 3、在CMainFrame类的OnCreate方法创建 大概的流程是先创建OutLook风格的选项卡,创建两个对话框,然后把对话框添加到选项卡中。 ...

540

C++远程监控系统发送端播放视频文件2/响应消息WSA_READ

C++远程监控系统发送端播放视频文件2/响应消息WSA_READ

D20187的博客 163

QT 实现类似qq的登录注册界面

QT 实现类似qq的登录界面运用sql进行简单注册登录 功能快捷键 撤销:Ctrl/Command + Z 重做:Ctrl/Command + Y 加粗:Ctrl/Command + B 斜体:Ctrl/Command + I 标题:Ctrl/Command + Shift + H 无序列表:Ctrl/Command + Shift + U 有序列表:Ctrl/Command + Shift + O 检查列表:Ctrl/Command + Shift + C 插入代码:Ctrl/Command + Shi

kay3123的博客 4131

【WPF】实现类似QQ聊天消息的界面

【WPF】实现类似QQ聊天消息的界面 原文:【WPF】实现类似QQ聊天消息的界面最近公司有个项目,是要求实现类似 QQ 聊天这种功能的。 如下图 这没啥难的,稍微复杂的也就表情的解析而已。 表情在传输过程中的实现参考了新浪微博,采用半角中括号代表表情的方式。例如:“abc[doge]def”就会显示 abc,然后一个,再 def。 ...

weixin_30551947的博客 660

使用ViewPager实现几个界面的切换,类似QQ

这几天在研究ViewPager,简单的写一下如何使用ViewPager实现类似QQ的“最近联系人、好友、群组”的界面切换(不知道他们是不是用这个方法实现的)。 ViewPager已经在android-sdk中加入了,具体的位置在 %android_sdk_home%\android-compatibility\v4 %android_sdk_home%是你的android-sd

carterjin的专栏 4751

MFC登录界面实现类似QQ的功能(详细步骤及代码)

首先添加一个combobox控件,控件添加m_cbExample变量,此外添加“记住密码”复选框。 之后在CLoginDlg::OnInitDialog()函数里调用函数_OnSetComboBox(),此函数主要是进行下拉框用户名记录的显示,用户名及密码存储在UserInfo.ini文件里,存储格式为"用户名","密码","复选框状态",复选框状态为0或者1,代码如下: vo...

风轻时听花落的博客 9300

CgfxOutBarCtrl

本组件从CWnd派生出CGfxOutBarCtrl等若干类,用于实现Outlook 98中的条形控件。可以方面做出OutLook风格的界面

CGfxOutBarCtrl类仿QQ窗口界面的VC++

摘要:VC/C++源码,界面编程,仿QQ,CGfxOutBarCtrl  仿QQ窗体界面实例使用了CGfxOutBarCtrl类,该类所使用的GfxGroupEdit.cpp、GfxGroupEdit.h、GfxOutBarCtrl.cpp、GfxOutBarCtrl.h、GfxPopupMenu.cpp、GfxPopupMenu.h文件需要到网上下载,下载后拷贝到工程文件夹下即可。   //创建并设置大小图标链表    imaLarge.Create(32,32,ILC_COLOR32|ILC_MASK,0,0);    imaSmall.Create(16,16,ILC_COLOR32|I

CGfxOutBarCtrl

很好的vc模板,类似qq导航窗口以及TGO导航窗口,可以用来作为vc界面开发的框架

改进的CGfxOutBarCtrl类源码示例

摘要:VC/C++源码,控件相关,CGfxOutBarCtrl,Outlook  VC++中使用的CGfxOutBarCtrl类,做了一些改进,并附上一个outlook风格的左侧菜单实例源代码,在这个outlook菜单实例中,左侧的菜单可展开/折叠,展开的内容可以是树形菜单、头像列表菜单等形式,和前几年老版本的QQ主窗口头像面板十分相似,学会使用了CGfxOutBarCtrl类,制作类似效果的菜单就容易多了。

Qt与HTML,jQuery交互实现类似QQ聊天界面

作为一个前端的小白,在jQuery和HTML上真的是头疼不已,而项目开发正好需要用到HTML和jQuery做一个类似QQ聊天界面的消息记录框,查找了很多资料并自己动手终于将基本功能全部搞定了。接下来将详细谈一下: 先上效果图,毕竟有图有真相。 1. 气泡效果 http://blog.csdn.net/tax10240809163com/article/details/50610

slowlytalk 8418

Qt+html+JavaScript实现类似QQ聊天界面的气泡效果

这是一个简单的类似QQ聊天界面的Demo,用Qt实现,在QWebView里嵌入网页的方式实现。先看效果图: 无论怎样,我觉得自己动手写出来的东西才是自己的,所以源码不全,重点的代码我会放上来。只是模拟实现了两个人的聊天,并没有真正实现聊天。 首先这里定义两个人的头像,可以看到,otherhead的图片是在桌面上,因此,文件并不一定非要加载在资源文件里面,使用相对路径来定义。 以下均在构造函

slowlytalk 1万+

CImageList类Create函数参数解析

前面提到了CImageList类的Create(...)函数,虽然MSDN上已经有所解释,但仍有网友问到参数的具体含义,下面就我的理解,对参数进行一次轻量级的剖析  函数原型: BOOL Create( int cx, int cy, UINT nFlag

GIS_wudi的专栏 1万+
上一篇: 一个分酒问题的求解
下一篇: 算法中的精确时间计数器的应用
jamiandy
博客等级 码龄22年 0粉丝 4原创
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值