网络安全

位置:IT落伍者 >> 网络安全 >> 浏览文章

网络蚂蚁和FlashGet的悬浮窗口的实现


发布日期:2020年08月09日
 
网络蚂蚁和FlashGet的悬浮窗口的实现

最近有网友问道如何用 Delphi 实现网络蚂蚁FlashGet的悬浮窗口笔者对使用到的相关技巧做了整理如下:

悬浮窗口

Delphi 的 TFormFormStyle 具有 fsStayOnTop 属性但只是对其程序本身而言的也就是说只在此应用程序本身的窗口中是前端显示的其他的程序的窗口仍然可以覆盖此类型的窗口这是应为此窗口的父窗口是 TApplication 要让悬浮窗口独立的显示在屏幕前端应在创建窗口时将其父窗口设置为桌面

Form := TFormCreateParented(GetDesktopWindow);

允许 Client 区域拖动窗口

这只要捕获窗口的 WM_NCHITTEST 消息将客户区HitTest(HTCLIENT)变成标题栏的HitTest(HTCAPTION)就可以了

半透明

Windows/XP 给窗口增加了WS_EX_LAYERED 属性并通过 APISetLayeredWindowAttributes(); 来设置此属性的详细信息Delphi 的 Forms 单元已经支持此窗口属性

property AlphaBlend default False; // 是否使用半透明效果

property AlphaBlendValue default ; // 透明度

property TransparentColor default False; // 是否使用穿透色

property TransparentColorValue default ; // 穿透色

(*此功能仅 Windows/XP 支持不要在 Winx 尝试此特效)

接收来自 Shell 的鼠标拖拽

这将使用到 ActiveX 单元的 IDropTarget 接口并扩展你的 Form 类

TForm = class(TForm IDropTarget)

end;

并在窗口拥有句柄后用 RegisterDragDrop() 注册成为 DragDrop 接受目标

以下是实现的代码:

unit DropBin;

interface

uses

Windows Messages SysUtils Variants Classes Graphics Controls Forms

Dialogs Menus ExtCtrls ActiveX ComObj;

type

TfrmDropBin = class(TForm IDropTarget)

private

procedure WMNCHitTest(var Msg:TWMNCHitTest); message WM_NCHITTEST;

protected

procedure CreateParams(var Params: TCreateParams); override;

procedure CreateWnd; override;

procedure DestroyWnd; override;

procedure DoClose(var Action: TCloseAction); override;

// DragDrop 支持

function DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

function IDropTarget_DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

function IDropTargetDragOver = IDropTarget_DragOver; // 解决 IDropTargetDragOver 与 TFormDragOver 沖突问题

function DragLeave: HResult; stdcall;

function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

public

constructor Create(AOwner: TComponent); override;

end;

var

frmDropBin: TfrmDropBin;

procedure ShowDropBin(Sender: TMenuItem);

implementation

{$R *dfm}

type

// 虽然 Delphi 的 Windows 单元定义了 SetLayeredWindowAttributes(); ( external Userdll )

// 但为了兼容 Winx 不能直接调用

TSetLayeredWindowAttributes = function (Hwnd: THandle; crKey: COLORREF; bAlpha: Byte; dwFlags: DWORD): Boolean; stdcall;

var

UserModH: HMODULE;

SetLayeredWindowAttributes: TSetLayeredWindowAttributes = nil;

procedure ShowDropBin(Sender: TMenuItem);

begin

if Assigned(frmDropBin) then frmDropBinClose

else begin

frmDropBin := TfrmDropBinCreateParented(GetDesktopWindow);

end;

end;

constructor TfrmDropBinCreate(AOwner: TComponent);

begin

inherited Create(AOwner);

Width := ;

Height := ;

end;

procedure TfrmDropBinCreateParams(var Params: TCreateParams);

begin

inherited CreateParams(Params);

with Params do begin

Style := WS_POPUP or WS_CLIPSIBLINGS {or WS_BORDER};

ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST;

end;

end;

procedure TfrmDropBinCreateWnd;

begin

inherited CreateWnd;

Visible := True;

// 为 /XP 创建半透明穿透效果

if Assigned(SetLayeredWindowAttributes) then begin

SetWindowLong(Handle GWL_EXSTYLE GetWindowLong(Handle GWL_EXSTYLE) or WS_EX_LAYERED);

SetLayeredWindowAttributes(Handle clWhite LWA_ALPHA or LWA_COLORKEY);

end;

// 设置为接受拖拽

OleCheck(RegisterDragDrop(Handle Self));

end;

procedure TfrmDropBinDestroyWnd;

begin

if HandleAllocated then RevokeDragDrop(Handle);

inherited DestroyWnd;

end;

function TfrmDropBinDragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

begin

//

// 也可以在此判断是否接受拖拽修改 dwEffect 可以得到不同的效果

//

dwEffect := DROPEFFECT_COPY;

Result := S_OK;

end;

function TfrmDropBinIDropTarget_DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

begin

dwEffect := DROPEFFECT_COPY;

Result := S_OK;

end;

function TfrmDropBinDragLeave: HResult; stdcall;

begin

Result := S_OK;

end;

function TfrmDropBinDrop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;

begin

//

// 处理 dataObj 中包含的拖拽内容

//

dwEffect := DROPEFFECT_NONE;

Result := S_OK;

end;

procedure TfrmDropBinDoClose(var Action: TCloseAction);

begin

Action := caFree;

frmDropBin := nil;

end;

procedure TfrmDropBinWMNCHitTest(var Msg:TWMNCHitTest);

begin

// 通过 Client 区拖动窗口

DefaultHandler(Msg);

if MsgResult = HTCLIENT then

MsgResult:= HTCAPTION;

end;

initialization

OleInitialize(nil);

// 为兼容 Winx

UserModH := GetModuleHandle(Userdll);

if UserModH <> then @SetLayeredWindowAttributes := GetProcAddress(UserModH SetLayeredWindowAttributes);

finalization

OleUninitialize;

end

上一篇:使用TCP/IP协议实现聊天程序

下一篇:用修改文件时间的方法来加密文件