-
c语言入门之在bcb里实现像Winamp那样具有吸附效果
相信大家都用过Winamp,一定会对她那种具有吸附效果的窗口感到很惊喜吧。其实要实现这样的效果并不难,下面我就用bcb做出这样的效果。为了将问题简化,窗口只在屏幕顶端产生吸附效果。
打开bcb6.0,新建一工程,将Form1的BorderStyle的属性改为bsNone,做成一个无标题栏,无边框的窗体。正常情况下,我们是无法移动这样的窗体的。我们必须自己给窗口发送一个移动的消息,在Form1的MouseDown的事件中添加如下代码:
ReleaseCapture();
SendMessage(this->Handle,WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
其实道理很简单,相信大家都会这个,我也就不多说了,:)
为了窗口在接近屏幕顶端的时候有一种磁性效果,我们必须在窗口的移动之前做一个判断,判断窗口将要到达的新位置的Top值是否小于一定范围(这个范围我称之为磁性距离,大小可由自己定义,为方便起见,我在这里定为20)。但是bcb里面并没有窗体移动事件,我们必须自己在程序里面拦截窗体移动消息,为此,我们要重载WndProc这个函数:
void __fastcall TForm1::WndProc(TMessage& Message)
{
switch(Message.Msg)
{
/*在窗口移动之前,判断窗口新位置的Top值是不是在磁性范
围内,如果在,让它归0,表示不产生窗体移动,避免在磁性
范围内移动窗口的时候窗口过于闪烁*/
case WM_WINDOWPOSCHANGING:
if ((LPWINDOWPOS(Message.LParam))->y<20)
(LPWINDOWPOS(Message.LParam))->y=0;
break;
default:
break;
}
TForm::WndProc(Message); //自己处理完消息后再让系统做剩下的事情
}
OK,代码就这么多,是不是很简单?运行一下程序,看是不是果真如此呢?:)
也许有人会问为什么不是拦截WM_MOVE这个消息,其实只要你试一下就知道了,如果拦截这个消息,窗口在磁性范围内移动的时候会很闪烁。原因很简单,WM_WINDOWPOSCHANGING是在窗口移动之前就做出了判断,如果窗口将要在磁性范围内移动(此时尚未移动),则不让窗口移动。而WM_MOVE在窗口移动以后才做判断,这样的结果就是不断让Top复位成0,当然会造成窗口闪烁了。
另外,大家都知道,根据系统本身的设置不同,窗口在移动的过程中,有两种显示效果,一种是显示虚线框,一种是显示窗口内容。细心的朋友可能已经发现,在Winamp中,不管系统的设置是如何,移动Winamp的窗口的过程中总是会显示窗口内容。其实这样做的道理很简单,因为在显示虚线框的时候,磁性窗口的吸附效果不怎么好,大家可以亲手试试。
那如何也做成和Winamp一样呢?其实只要一个API函数就搞定了,:),代码如下:
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,true,NULL,SPIF_SENDCHANGE);
在窗口移动之前,通过调用上面的函数,就能达到Winamp一样的效果了。关于SystemParametersInfo这个函数及参数的具体用法,请各位参见MSDN,再没有比MSDN解释的更清楚了。
以上代码在Win2k Professional+bcb6.0下测试通过。
打开bcb6.0,新建一工程,将Form1的BorderStyle的属性改为bsNone,做成一个无标题栏,无边框的窗体。正常情况下,我们是无法移动这样的窗体的。我们必须自己给窗口发送一个移动的消息,在Form1的MouseDown的事件中添加如下代码:
ReleaseCapture();
SendMessage(this->Handle,WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
其实道理很简单,相信大家都会这个,我也就不多说了,:)
为了窗口在接近屏幕顶端的时候有一种磁性效果,我们必须在窗口的移动之前做一个判断,判断窗口将要到达的新位置的Top值是否小于一定范围(这个范围我称之为磁性距离,大小可由自己定义,为方便起见,我在这里定为20)。但是bcb里面并没有窗体移动事件,我们必须自己在程序里面拦截窗体移动消息,为此,我们要重载WndProc这个函数:
void __fastcall TForm1::WndProc(TMessage& Message)
{
switch(Message.Msg)
{
/*在窗口移动之前,判断窗口新位置的Top值是不是在磁性范
围内,如果在,让它归0,表示不产生窗体移动,避免在磁性
范围内移动窗口的时候窗口过于闪烁*/
case WM_WINDOWPOSCHANGING:
if ((LPWINDOWPOS(Message.LParam))->y<20)
(LPWINDOWPOS(Message.LParam))->y=0;
break;
default:
break;
}
TForm::WndProc(Message); //自己处理完消息后再让系统做剩下的事情
}
OK,代码就这么多,是不是很简单?运行一下程序,看是不是果真如此呢?:)
也许有人会问为什么不是拦截WM_MOVE这个消息,其实只要你试一下就知道了,如果拦截这个消息,窗口在磁性范围内移动的时候会很闪烁。原因很简单,WM_WINDOWPOSCHANGING是在窗口移动之前就做出了判断,如果窗口将要在磁性范围内移动(此时尚未移动),则不让窗口移动。而WM_MOVE在窗口移动以后才做判断,这样的结果就是不断让Top复位成0,当然会造成窗口闪烁了。
另外,大家都知道,根据系统本身的设置不同,窗口在移动的过程中,有两种显示效果,一种是显示虚线框,一种是显示窗口内容。细心的朋友可能已经发现,在Winamp中,不管系统的设置是如何,移动Winamp的窗口的过程中总是会显示窗口内容。其实这样做的道理很简单,因为在显示虚线框的时候,磁性窗口的吸附效果不怎么好,大家可以亲手试试。
那如何也做成和Winamp一样呢?其实只要一个API函数就搞定了,:),代码如下:
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,true,NULL,SPIF_SENDCHANGE);
在窗口移动之前,通过调用上面的函数,就能达到Winamp一样的效果了。关于SystemParametersInfo这个函数及参数的具体用法,请各位参见MSDN,再没有比MSDN解释的更清楚了。
以上代码在Win2k Professional+bcb6.0下测试通过。
最新更新
Objective-C语法之代码块(block)的使用
VB.NET eBook
Add-in and Automation Development In VB.NET 2003 (F
Add-in and Automation Development In VB.NET 2003 (8
Add-in and Automation Development in VB.NET 2003 (6
Add-in and Automation Development In VB.NET 2003 (5
AddIn Automation Development In VB.NET 2003 (4)
AddIn And Automation Development In VB.NET 2003 (2)
Addin and Automation Development In VB.NET 2003 (3)
AddIn And Automation Development In VB.NET 2003 (1)
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
武装你的WEBAPI-OData入门
武装你的WEBAPI-OData便捷查询
武装你的WEBAPI-OData分页查询
武装你的WEBAPI-OData资源更新Delta
5. 武装你的WEBAPI-OData使用Endpoint 05-09
武装你的WEBAPI-OData之API版本管理
武装你的WEBAPI-OData常见问题
武装你的WEBAPI-OData聚合查询
OData WebAPI实践-OData与EDM
OData WebAPI实践-Non-EDM模式