Visual C++设计超强仿QQ自动伸缩窗口(下)

转载 2011年03月03日 09:47:00

  暂时不管OnTimer中的DoHide(); DoShow();

 

先来看看核心的函数之一的 FixMoving,该函数OnMoving中被调用,FixMoving通过检测鼠标位置和窗口位置来决定窗口的收缩模式,并修正粘附边界时窗口的位置,从而达到像移动QQ时出现的效果。

  【代码四】

void CQQHideWndDlg::FixMoving(UINT fwSide, LPRECT pRect)
{
POINT curPos;
GetCursorPos(&curPos);
INT screenHeight = GetSystemMetrics(SM_CYSCREEN);
INT screenWidth = GetSystemMetrics(SM_CXSCREEN);
INT height = pRect->bottom - pRect->top;
INT width = pRect->right - pRect->left;

if (curPos.y <= INTERVAL)
{ //
粘附在上边

pRect->bottom = height - m_edgeHeight;
pRect->top = -m_edgeHeight;
m_hideMode = HM_TOP;
}
else if(curPos.y >= (screenHeight - INTERVAL - m_taskBarHeight))
{ //
粘附在下边
pRect->top = screenHeight - m_taskBarHeight - height;
pRect->bottom = screenHeight - m_taskBarHeight;
m_hideMode = HM_BOTTOM;
}
else if (curPos.x < INTERVAL)
{ //
粘附在左边
if(!m_isSizeChanged)
{
CRect tRect;
GetWindowRect(tRect);
m_oldWndHeight = tRect.Height();
}
pRect->right = width;
pRect->left = 0;
pRect->top = -m_edgeHeight;
pRect->bottom = screenHeight - m_taskBarHeight;
m_isSizeChanged = TRUE;
m_hideMode = HM_LEFT;
}
else if(curPos.x >= (screenWidth - INTERVAL))
{ //
粘附在右边

if(!m_isSizeChanged)
{
CRect tRect;
GetWindowRect(tRect);
m_oldWndHeight = tRect.Height();
}
pRect->left = screenWidth - width;
pRect->right = screenWidth;
pRect->top = -m_edgeHeight;
pRect->bottom = screenHeight - m_taskBarHeight;
m_isSizeChanged = TRUE;
m_hideMode = HM_RIGHT;
}
else
{ //
不粘附
if(m_isSizeChanged)
{ //
如果收缩到两边,则拖出来后会变回原来大小
//
"拖动不显示窗口内容下"只有光栅变回原来大小
pRect->bottom = pRect->top + m_oldWndHeight;
m_isSizeChanged = FALSE;
}
if(m_isSetTimer)
{ //
如果Timer开启了,则关闭之
if(KillTimer(1) == 1)
m_isSetTimer = FALSE;
}
m_hideMode = HM_NONE;
GetDlgItem(IDC_TIMER)->SetWindowText("Timer off");
}
}

 

 

  收缩模式和位置决定后,剩下的工作就由最后两个核心函数完成了:实现收缩的DoHide(),实现伸展的DoShow()。在这两个过程中m_hsFinishedm_hiding 这两个变量起到很重要的控制作用。由于伸缩过程没完成时,hsFinished始终为FALSE,所以Timer 2 不会关闭,于是在OnTimer中会重复调用这两个函数之一,在这两个函数体内,窗口位置有规律地递减或递增就可以达到QQ抽屉效果了,有趣的是即使伸缩过程还没完成,你也可以在这个过程中改变m_hiding这个值来决定他是伸还是缩,正如QQ一样。你可以把Timer 2 事件间隔调大一点,然后在窗口伸缩时,鼠标来回地进出窗口就会很容易看到这样有趣的效果(还没缩进去又被拉了出来,或者还没拉出来又缩进去了)。

  【代码五】

void CQQHideWndDlg::DoHide()
{
if(m_hideMode == HM_NONE)
return;

CRect tRect;
GetWindowRect(tRect);

INT height = tRect.Height();
INT width = tRect.Width();

INT steps = 0;

switch(m_hideMode)
{
case HM_TOP:
steps = height/HS_STEPS;
tRect.bottom -= steps;
if(tRect.bottom <= m_edgeWidth)
{ //
你可以把下面一句替换上面的 ...+=|-=steps 达到取消抽屉效果

//
更好的办法是添加个BOOL值来控制,其他case同样.
tRect.bottom = m_edgeWidth;
m_hsFinished = TRUE; //
完成隐藏过程

}
tRect.top = tRect.bottom - height;
break;
case HM_BOTTOM:
steps = height/HS_STEPS;
tRect.top += steps;
if(tRect.top >= (GetSystemMetrics(SM_CYSCREEN) - m_edgeWidth))
{
tRect.top = GetSystemMetrics(SM_CYSCREEN) - m_edgeWidth;
m_hsFinished = TRUE;
}
tRect.bottom = tRect.top + height;
break;
case HM_LEFT:
steps = width/HS_STEPS;
tRect.right -= steps;
if(tRect.right <= m_edgeWidth)
{
tRect.right = m_edgeWidth;
m_hsFinished = TRUE;
}
tRect.left = tRect.right - width;
tRect.top = -m_edgeHeight;
tRect.bottom = GetSystemMetrics(SM_CYSCREEN) - m_taskBarHeight;
break;
case HM_RIGHT:
steps = width/HS_STEPS;
tRect.left += steps;
if(tRect.left >= (GetSystemMetrics(SM_CXSCREEN) - m_edgeWidth))
{
tRect.left = GetSystemMetrics(SM_CXSCREEN) - m_edgeWidth;
m_hsFinished = TRUE;
}
tRect.right = tRect.left + width;
tRect.top = -m_edgeHeight;
tRect.bottom = GetSystemMetrics(SM_CYSCREEN) - m_taskBarHeight;
break;
default:
break;
}

SetWindowPos(&wndTopMost,tRect);
}

 

 

 

 

  【代码六】

void CQQHideWndDlg::DoShow()
{
if(m_hideMode == HM_NONE)
return;

CRect tRect;
GetWindowRect(tRect);
INT height = tRect.Height();
INT width = tRect.Width();

INT steps = 0;

switch(m_hideMode)
{
case HM_TOP:
steps = height/HS_STEPS;
tRect.top += steps;
if(tRect.top >= -m_edgeHeight)
{ //
你可以把下面一句替换上面的 ...+=|-=steps 达到取消抽屉效果

//
更好的办法是添加个BOOL值来控制,其他case同样.
tRect.top = -m_edgeHeight;
m_hsFinished = TRUE; //
完成显示过程

}
tRect.bottom = tRect.top + height;
break;
case HM_BOTTOM:
steps = height/HS_STEPS;
tRect.top -= steps;
if(tRect.top <= (GetSystemMetrics(SM_CYSCREEN) - height))
{
tRect.top = GetSystemMetrics(SM_CYSCREEN) - height;
m_hsFinished = TRUE;
}
tRect.bottom = tRect.top + height;
break;
case HM_LEFT:
steps = width/HS_STEPS;
tRect.right += steps;
if(tRect.right >= width)
{
tRect.right = width;
m_hsFinished = TRUE;
}
tRect.left = tRect.right - width;
tRect.top = -m_edgeHeight;
tRect.bottom = GetSystemMetrics(SM_CYSCREEN) - m_taskBarHeight;
break;
case HM_RIGHT:
steps = width/HS_STEPS;
tRect.left -= steps;
if(tRect.left <= (GetSystemMetrics(SM_CXSCREEN) - width))
{
tRect.left = GetSystemMetrics(SM_CXSCREEN) - width;
m_hsFinished = TRUE;
}
tRect.right = tRect.left + width;
tRect.top = -m_edgeHeight;
tRect.bottom = GetSystemMetrics(SM_CYSCREEN) - m_taskBarHeight;
break;
default:
break;
}

SetWindowPos(&wndTopMost,tRect);
}

BOOL CQQHideWndDlg::SetWindowPos(const CWnd* pWndInsertAfter, LPCRECT pCRect, UINT nFlags)
{
return CDialog::SetWindowPos(pWndInsertAfter,pCRect->left, pCRect->top,
pCRect->right - pCRect->left, pCRect->bottom - pCRect->top, nFlags);
}

 

 

 

 

 

 

  到此,程序终于完成了。在我的源代码中还有对WM_SIZING的处理和定义了与之相关的宏,这些主要是控制窗口在调整大小时不能超过最小的宽度和高度,与QQ的自动伸缩无关,所以不在这里提及了。

  三、结束语

  虽然还不能算是完美的模仿,但效果已经非常非常的接近了。也许有人会奇怪为什么要用Tool Window 风格,这是因为,这样在任务栏中不会显示窗口。从QQ的标题栏高度也可以判断出他也是这种风格,但这样一来就不能拥有最小化、最大化按键了。实际上QQ的最大化、最小化和关闭按键都是用DC画上去的。如何在Caption上增加按键,外国一些开源网站有源代码,我下载并看了一下,发现里面有个知识点很有趣,那就是更改消息路由,有兴趣的可以去下载来学习一下。

  QQ的成功很大部分在于他的界面比较人性化(用了MSN后深有感受),而这些界面实现起来原理也许很简单,难的是观察东西心要细、设计东西心要密、开发东西心要异。

Visual C++ 设计超强仿 QQ 自动伸缩窗口

  • xin_l_o
  • xin_l_o
  • 2010年05月17日 13:22
  • 181

Visual C++设计超强仿QQ自动伸缩窗口

Visual C++设计超强仿QQ自动伸缩窗口   摘要:  某天在论坛上看到有人发帖询问QQ自动伸缩窗口是怎么实现的,我也好想知道,于是到百度一搜索,结果不多,来来去去都是那几篇,下载那些demo运...
  • Athenaer
  • Athenaer
  • 2007年09月29日 23:34
  • 986

超强仿QQ自动伸缩窗口

原代码下载                              某天在CSDN论坛上看到有人发帖询问QQ自动伸缩窗口是怎么实现的,我也好想知道,于是到百度一搜索,结果不多,来来去去都是那几篇,下...
  • windboyzsj
  • windboyzsj
  • 2007年09月23日 13:45
  • 717

Visual Basic设计仿QQ2011登陆窗口的思路

QQ2011的登陆窗口很美观,如果我们要设计登陆窗口,可以效仿之,一定会为程序增色不少。笔者近期做课程设计,要求用VB+数据库设计一个管理软件,此软件应设置登陆窗口,于是我决定模仿QQ2011的登陆窗...
  • lionelluthor
  • lionelluthor
  • 2011年12月14日 18:45
  • 1547

Visual C++设计超强仿QQ自动伸缩窗口(转载至中国IT实验室)

一、观察  模仿前最重要的一步就是观察,经过半天对QQ的摆弄和摸索,总结出了以下一些特点:  1、窗口开始粘附时,检测的是鼠标坐标与桌面边界的距离,特别地,粘附在下面的时候,检测的是与任务栏的距离; ...
  • pzfan
  • pzfan
  • 2008年03月25日 16:17
  • 197

MFC仿QQ窗口靠边自动收缩隐藏效果(附源代码)

/*在原创的基础上做了*/ 一、【观察】 模仿前最重要的一步就是观察,经过半天对QQ的摆弄和摸索,总结出了以下一些特点: 1、窗口开始粘附时,检测的是鼠标坐标与桌面边界的距离,特别地,粘附在下...
  • u013100446
  • u013100446
  • 2014年12月20日 19:45
  • 1687

VC++仿QQ自动伸缩窗口

某天在论坛上看到有人发帖询问QQ自动伸缩窗口是怎么实现的,我也好想知道,于是到百度一搜索,结果不多,来来去去都是那几篇,下载那些demo运行一下,发觉效果与QQ相差很大,于是决定自己动手做个,要求要近...
  • hilaochen
  • hilaochen
  • 2013年03月26日 10:07
  • 643

Qt仿QQ界面,主界面、聊天界面、表情界面

利用Qt仿的QQ的界面如下:
  • llmys
  • llmys
  • 2017年06月09日 20:24
  • 1118

2013-06-18《C++仿QQ系统设计与实…

仿QQ聊天系统   1.引言 1 1.1编写目的 1 1.2项目背景 1 1.3定义 2 1.4参考资料 2 2.总体设计 2 2.1需求概述 2 2.2软件结构 2 3.程序描述 ...
  • HXPshakele
  • HXPshakele
  • 2013年11月30日 20:33
  • 1012

qt实现类似QQ伸缩窗口--鼠标事件应用

上一章节讲了qt鼠标事件实现,获取鼠标参数的方法。这一讲主要讲怎么应用上讲的鼠标事件实现一个小功能。  qq好友对话框右侧 未展开时如图: 鼠标移动到 “隐藏侧边”处单击可以隐藏侧边,隐藏后效果如...
  • hiwubihe
  • hiwubihe
  • 2014年08月19日 10:30
  • 3371
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Visual C++设计超强仿QQ自动伸缩窗口(下)
举报原因:
原因补充:

(最多只允许输入30个字)