怎样实现类似qq的窗口顶部停靠效果?
怎样实现类似qq的窗口顶部停靠效果?
当窗体在屏幕上方某个区域时,窗体上移,只留一小部分在屏幕显示
当鼠标移入这一小部分的时候,窗体下移
当鼠标移出时,窗体又上移.
我想了一下:主要有两个技术点:
1:怎么得到窗体的移动结束事件?我想应该是截获WM_MOVE消息
2:怎么得到鼠标移入,移出窗体的事件,我想应该可以用到
CM_MOUSEENTER,CM_MOUSELEAVE消息
下面是我初步实现的效果:
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TEdit *Edit1;
private: // User declarations
bool in; //标识鼠标是否进入窗体
void __fastcall MouseEnter(Messages::TMessage &Message);
void __fastcall MouseLeave(Messages::TMessage &Message);
void __fastcall FormMoveEnd(Messages::TMessage &Message);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(CM_MOUSEENTER,Messages::TMessage,MouseEnter)
VCL_MESSAGE_HANDLER(CM_MOUSELEAVE,Messages::TMessage,MouseLeave)
VCL_MESSAGE_HANDLER(WM_MOVE,Messages::TMessage,FormMoveEnd)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
in = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MouseEnter(Messages::TMessage &Message)
{
if(in)
exit;
in = true;
Edit1->Text = "enter";
if(Form1->Top < 0)
Form1->Top = 10;
}
void __fastcall TForm1::MouseLeave(Messages::TMessage &Message)
{
in = false;
Edit1->Text = "leave";
if(Form1->Top == 10)
{
Form1->Top = -(Form1->Height -15);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMoveEnd(Messages::TMessage &Message)
{
if(Form1->Top < 10)
{
Form1->Top = -(Form1->Height - 15);
}
}
以上程序初步实现了类似效果.但有点问题,就是我的鼠标移动到屏幕最上方时候,窗体会不间断的闪烁.
好像是连续激发了鼠标离开窗体和进入窗体的事件.
有点苦恼,请高手指点一下
问题点数:50、回复次数:7Top
1 楼constantine(飘遥的安吉儿)回复于 2005-06-07 13:41:30 得分 20
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ExtCtrls, StdCtrls;
type
TfrmMain = class(TForm)
lbl1: TLabel;
mmo1: TMemo;
tmrMouseOut: TTimer;
procedure MouseLeaveProc(Sender: TObject);
private
{ Private declarations }
protected
procedure WMMOVING(var Msg: TMessage); message WM_MOVING;
procedure MouseEnterProc(var Msg: TMessage); message CM_MOUSEENTER;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
{
****************************
* 以下为窗口效果相关过程 *
****************************
}
//限制窗口的Top不能小于0,即窗口不能被拖动到顶部以外
procedure TfrmMain.WMMOVING(var Msg: TMessage);
begin
inherited;
//当窗口被移动的时候
if PRECT(Msg.lParam).Top < 0 then
PRECT(Msg.lParam).Top := 0;
end;
//实现窗口自动弹出
procedure TfrmMain.MouseEnterProc(var Msg: TMessage);
begin
inherited;
tmrMouseOut.Enabled := True;
//如果窗口不是隐藏的,不用弹出。
if Self.Top >= 0 then
Exit;
Self.Top := 0;
Msg.Result := 0;
end;
//实现窗口自动隐藏
procedure TfrmMain.MouseLeaveProc(Sender: TObject);
var
pt: TPoint;
begin
GetCursorPos(pt);
if (not PtInRect(Self.BoundsRect, pt)) and (GetAsyncKeyState(VK_LButton) <> 0) then
Exit;
if PtInRect(Self.BoundsRect, pt) then
Exit;
tmrMouseOut.Enabled := False;
//如果窗口不在最顶部,不用隐藏。
if Self.Top > 0 then
Exit;
//将窗口上缩,只显示三个像素
Self.Top := -Self.Height + 3;
end;
{
****************************
* 以上为窗口控制相关过程 *
****************************
}
end.
Top
2 楼constantine(飘遥的安吉儿)回复于 2005-06-07 13:41:50 得分 0
delphi 自己看Top
3 楼lcllcl987(毛爷爷)回复于 2005-06-07 14:02:33 得分 0
没懂,郁闷
我的程序错在哪了?
怎么鼠标在最上面的时候,要闪烁?Top
4 楼F117p(走两步,你走两步?)回复于 2005-06-07 14:23:53 得分 30
改动一下:
static bool IsHide;
bool CanHide;
void __fastcall TForm1::MouseEnter(Messages::TMessage &Message)
{
if(in)
exit;
in = true;
Edit1->Text = "enter";
if(IsHide)
{
IsHide=false;
Timer1->Enable=true;
}
else
Timer1->Enable=false;
}
void __fastcall TForm1::MouseLeave(Messages::TMessage &Message)
{
in = false;
Edit1->Text = "leave";
if(!IsHide&&Top<0)
{
IsHide=true;
Timer1->Enable=true;
}
else
Timer1->Enable=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMoveEnd(Messages::TMessage &Message)
{
if(Form1->Top < 10)
{
IsHide=true;
Timer1->Enable=true;
}
else
Timer1->Enable=false;
}
Timer(...)
{
if(IsHide)
{
//向下展开
}
else
//向上隐藏
}
Top
5 楼lcllcl987(毛爷爷)回复于 2005-06-07 14:57:37 得分 0
楼上的,谢谢,
我试一下
不过怎么要用timer啊
有点不爽Top
6 楼F117p(走两步,你走两步?)回复于 2005-06-07 15:07:47 得分 0
不用Timer用循环
for()
{
Application->PostMessage
}Top
7 楼lcllcl987(毛爷爷)回复于 2005-06-08 10:34:00 得分 0
顶Top




