怎么用BCB做磁性窗体

怎么用BCB做磁性窗体,第1张

利用BCB编写具有"磁性"特征的窗口

马明臣

一些著名的共享软件不但功能卓著,而且在程序界面的设计技巧上往往领导了一种时尚,WinAmp就是其中的一个代表。WinAmp有两个绝活,一是可以更换窗体的外观,也就是现在俗称的给软件换“皮肤”;另一个是及时磁性窗体技巧。

那么什么是磁性窗体呢?用过Winamp的用户都知道,Winamp的播放列表或均衡器在被移动的时候,仿佛会受到一股磁力,每当靠近主窗口时就一下子被“吸附”过去,自动沿边对齐。这就是磁性窗体,那么我们如何在自己的程序中实现这种奇妙的特性呢?经过笔者摸索琢磨出了实现这种“磁化”窗口的方法。该法适用于C++ builder的各个版本。下面笔者给大家介绍一下该技术。

实现粘贴的难点在于什么时候进行这个 *** 作,假设有两个窗体Form1和Form2,移动Form2向Form1靠近,当Form2与Form1的最近距离小于一个给定值时粘贴在一起。显然,应该在移动Form2的过程中进行判断,问题是在程序的什么位置插入判断代码呢?

合理的方法是利用系统产生的消息,我们知道窗体在移动时会产生WM_WINDOWPOSCHANGING和WM_MOVING消息,移动结束后会产生WM_WINDOWPOSCHANGED和WM_MOVE消息。我们这里使用WM_WINDOWPOSCHANGING消息来实现这一功能。

下面笔者就把实现磁性窗体的方法介绍如下:

先新建一应用程序项目,把主窗口Form1适当放小些,放一个按钮组件,修改该按钮组件的Caption属性为“创建磁性窗口”双击它并在OnClick事件中写入如下代码:

void __fastcall TForm1::Button1Click(TObject *Sender)

{

Form2= new TForm2(Application)

Form2->Show()//显示磁性窗口

}

选择“File”—>“New Form”创建一个新窗口Form2,在Form2上加入一个Edit组件Edit1和一个按钮组件Button1,修改Edit的TEXT属性为50(该值为当Form2靠近Form1时距离为50像素时进行吸附,一般设为20左右即可,这里为了效果明显所以设为50像素),修改按钮的Caption属性为“磁距”,接着在这个新窗口的unit2.h文件中的private:下面加入如下变量定义:

HWND snapwin//定义Form2吸附到哪一个窗口的句柄

RECT work_area

bool snapped//是否吸附标志

bool winprocthing

int thresh//距离多远开始吸附

void __fastcall SettingChanged(TMessage &msg)//改变窗口大小时产生

void __fastcall WMWindowPosChanging(TWMWindowPosChanging &msg)//移动窗口时产生

void __fastcall UpdateWorkArea()刷新窗口

接着在public: // User declarations下加入如下消息:

BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(WM_WINDOWPOSCHANGING,TWMWindowPosChanging,WMWindowPosChanging)//定义消息当窗口移动时调用WMWindowPosChanging

MESSAGE_HANDLER(WM_SETTINGCHANGE,TMessage,SettingChanged)

END_MESSAGE_MAP(TForm) //当窗口改变大小时调用SettingChanged

在Form2的单元文件unit.cpp中加入如下代码:

void __fastcall TForm2::SettingChanged(TMessage &msg)

{

UpdateWorkArea()

}

//---------------------------------------------------------------------------

void __fastcall TForm2::WMWindowPosChanging(TWMWindowPosChanging &msg)

{

RECT sr

snapped=false//设为不吸附

//test window

snapwin = Form1->Handle//定义Form2吸附到Form1上这里如改为别的软件的窗口句柄还可以吸附到别的软件窗口上

if (snapwin &&IsWindowVisible(snapwin))

/*该段得到窗口Form1的当前位置,当Form2移动时该函数判断Form2与Form1在上下左右方向上是否距离小于50,如小于50则自动改变Form2的位置,自动吸附到Form1上*/

{

if (GetWindowRect(snapwin,&sr))//得到Form1的位置

{

if ( (msg.WindowPos->x <= (sr.right+thresh)) &&

(msg.WindowPos->x >= (sr.right-thresh)) ) {

if ((msg.WindowPos->y >sr.top) &&(msg.WindowPos->y <sr.bottom)) {

snapped=true

msg.WindowPos->x = sr.right

}

}

else if ((msg.WindowPos->x + msg.WindowPos->cx) >= (sr.left-thresh) &&

(msg.WindowPos->x + msg.WindowPos->cx) <= (sr.left+thresh)) {

if ((msg.WindowPos->y >sr.top) &&(msg.WindowPos->y <sr.bottom)) {

snapped=true

msg.WindowPos->x = sr.left-msg.WindowPos->cx

}

}

if ( (msg.WindowPos->y <= (sr.bottom+thresh)) &&

(msg.WindowPos->y >= (sr.bottom-thresh)) ) {

if ((msg.WindowPos->x >sr.left) &&(msg.WindowPos->x <sr.right)) {

snapped=true

msg.WindowPos->y = sr.bottom

}

}

else if ((msg.WindowPos->y + msg.WindowPos->cy) <= (sr.top+thresh) &&

(msg.WindowPos->y + msg.WindowPos->cy) >= (sr.top-thresh)) {

if ((msg.WindowPos->x >sr.left) &&(msg.WindowPos->x <sr.right)) {

snapped=true

msg.WindowPos->y = sr.top-msg.WindowPos->cy

}

}

}

}

//测试屏幕

sr = work_area

if (abs(msg.WindowPos->x) <= (sr.left+thresh)) {

snapped=true

msg.WindowPos->x = sr.left

}

else if ((msg.WindowPos->x + msg.WindowPos->cx) >= (sr.right-thresh) &&

(msg.WindowPos->x + msg.WindowPos->cx) <= (sr.right+thresh)) {

snapped=true

msg.WindowPos->x = sr.right-msg.WindowPos->cx

}

if (abs(msg.WindowPos->y) <= (sr.top+thresh)) {

snapped=true

msg.WindowPos->y = sr.top

}

else if ((msg.WindowPos->y+msg.WindowPos->cy) >= (sr.bottom-thresh) &&

(msg.WindowPos->y+msg.WindowPos->cy) <= (sr.bottom+thresh)) {

snapped=true

msg.WindowPos->y = sr.bottom-msg.WindowPos->cy

}

}

//---------------------------------------------------------------------------

void __fastcall TForm2::UpdateWorkArea()

{

SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0)

}

双击“磁距”按钮加入如下代码:

void __fastcall TForm2::Button1Click(TObject *Sender)

{

thresh = StrToInt(Edit1->Text)//设定磁性窗口距Form1为edit1中的数值时开始吸附

}

在窗体Form2的OnCreate事件中加入如下代码:

void __fastcall TForm2::FormCreate(TObject *Sender)

{

snapped=false//设置为不吸附

UpdateWorkArea()

thresh = StrToInt(Edit1->Text)

snapwin = Form1->Handle

}

该程序在c++ builder 5.0、windows98系统下调试通过。

直接添加一个MID父窗体或在已有窗体的属性中找到IsMDIContainer属性,然后设置为True,然后创建第二个窗体 ,需要加载子窗体的时候:

Dim NewMDIChild As New Form2

NewMDIChild.MdiParent = Me

NewMDIChild.Show()

Public Shared Sub CheckMDIChildForm(ByVal MDIForm As Windows.Forms.Form, ByVal MDIChildForm As Windows.Forms.Form, ByVal MDIChildFormName As String)

        If MDIForm.MdiChildren.Length < 1 Then

            '如果没有任何一个MDI子窗体,则创该MDI子窗体的窗体实例

            Dim MDIChildFrm As Windows.Forms.Form = MDIChildForm ' 定义MDI子窗体

            MDIChildFrm.MdiParent = MDIForm '指定父窗体

            MDIChildFrm.Show() '打开窗体

            Exit Sub

        Else

            Dim x As Integer

            Dim frmyn As Boolean

            For x = 0 To (MDIForm.MdiChildren.Length) - 1

                Dim tempChild As Windows.Forms.Form = CType(MDIForm.MdiChildren(x), Windows.Forms.Form)

                If tempChild.Name = MDIChildFormName Then

                    '检测到有该MDI子窗体,设为激活 并退出循环

                    frmyn = True

                    tempChild.BringToFront()

                    Exit For

                Else

                    frmyn = False

                End If

            Next

            If Not frmyn Then

                '在打开的窗体中没检测到则新建

                Dim MDIChildFrm As Windows.Forms.Form = MDIChildForm ' 定义MDI子窗体

                MDIChildFrm.MdiParent = MDIForm '指定父窗体

                MDIChildFrm.Show() '打开窗体

            End If

        End If

    End Sub

点击项目右键,添加windows窗体。

在窗体属性中有窗口样式,可以自行设置(在属性栏最下面有说明的),窗口初始位置设置属性 StartPositior,有center就是在屏幕居中的。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/bake/11489900.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存