DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: tino0914
今日帖子: 30
在线用户: 6
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 jackalan (nVicen) ★☆☆☆☆ -
盒子活跃会员
2021/2/28 11:05:13
标题:
FMX窗口做WINDOWS桌面边缘停靠 浏览:827
加入我的收藏
楼主: FMX窗口在WINDOWS桌面边缘停靠

在VCL窗体做这个功能非常简单,只要设定下窗口的
ScreenSnap和SnapBuffer就可以了。

但FMX因为跨平台原因,并没有提供这样的功能,尝
试自己重写WMWindowPosChanging消息,但FMX并没有
提供这种消息循环处理,所以你不会收到任何消息,
为了避免大家和我一样走弯路,下面贴出代码,这种
方式可以处理任何WINDOWS消息,这里只是用窗口在桌
面边缘停靠来演示一下FMX如何处理WINDOWS消息循环。

  protected
    {$IFDEF MSWINDOWS}
    procedure CreateHandle; override;
    procedure DestroyHandle; override;
    procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
    {$ENDIF}

.........

implementation

{$R *.fmx}

{$IFDEF MSWINDOWS}
uses
  FMX.Platform.Win, Winapi.Windows, Winapi.Commctrl;

function SubclassProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM;
  uIdSubclass: UINT_PTR; RefData: DWORD_PTR): LRESULT; stdcall;
var
  Self: TfrmMain;
  Message: TMessage;
begin
  Result := DefSubclassProc(Wnd, Msg, wParam, lParam);
  case Msg of //你可以在这里处理其它WINDOWS消息
    WM_WINDOWPOSCHANGING:
    begin
      Self := TfrmMain(RefData);
      Message.Msg := Msg;
      Message.WParam := wParam;
      Message.LParam := lParam;
      Message.Result := Result;
      Self.Dispatch(Message);
      Result := Message.Result;
    end;
  end;
end;

procedure TfrmMain.CreateHandle;
var
  Wnd: HWND;
begin
  inherited;
  Wnd := WindowHandleToPlatform(Self.Handle).Wnd;
  SetWindowSubclass(Wnd, SubclassProc, 1, DWORD_PTR(Self));
end;

procedure TfrmMain.DestroyHandle;
var
  Wnd: HWND;
begin
  Wnd := WindowHandleToPlatform(Self.Handle).Wnd;
  RemoveWindowSubclass(Wnd, SubclassProc, 1);
  inherited;
end;

procedure TfrmMain.WMWindowPosChanging(var Message: TWMWindowPosChanging);
  procedure HandleEdge(var Edge: Integer; SnapToEdge: Integer;
    SnapDistance: Integer = 0);
  begin
    if (Abs(Edge + SnapDistance - SnapToEdge) < 15) then
      Edge := SnapToEdge - SnapDistance;
  end;
begin
  inherited;

  var WindowPos : PWindowPos;
  var LRect: TRect;
  WindowPos := Message.WindowPos;
  if (not (csDesigning in ComponentState)) and
    ((WindowPos.X <> 0) or (WindowPos.Y <> 0)) and
    ((WindowPos.cx = Width) and (WindowPos.cy = Height)) then
  begin
    LRect := Screen.WorkareaRect;
    HandleEdge(WindowPos.x, LRect.Left, 0);
    HandleEdge(WindowPos.y, LRect.Top, 0);
    HandleEdge(WindowPos.x, LRect.Right, Width);
    HandleEdge(WindowPos.y, LRect.Bottom, Height);
    Message.WindowPos := WindowPos;
  end;

  if (Message.WindowPos.y + Message.WindowPos.cy  > Screen.WorkAreaHeight) then begin
    Message.WindowPos.Y := Screen.WorkAreaHeight - Height;
  end;
  if (Message.WindowPos.x + Message.WindowPos.cx > Screen.WorkAreaWidth) then begin
    Message.WindowPos.X := Screen.WorkAreaWidth - Width;
  end;

  if Message.WindowPos.x<0 then
    Message.WindowPos.x := 0;
  if Message.WindowPos.y<0 then
    Message.WindowPos.y := 0;
end;
{$ENDIF}

..........

{$IFDEF MSWINDOWS}
var
  ICC: TInitCommonControlsEx;

initialization
  ICC.dwSize := SizeOf(ICC);
  ICC.dwICC  := ICC_STANDARD_CLASSES;
  InitCommonControlsEx(ICC);
{$ENDIF}

end.
----------------------------------------------
简单做人,认真做事。
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2021/2/28 11:23:32
1楼: vcl有代码吗?
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 jackalan (nVicen) ★☆☆☆☆ -
盒子活跃会员
2021/2/28 16:32:53
2楼: @tuesdays
vcl不需要代码
设置窗口ScreenSnap为true
设置多少像素自动吸附即可,SnapBuffer设定为10-20。
----------------------------------------------
简单做人,认真做事。
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2021/2/28 19:59:53
3楼: 没这么简单吧, 我看网上的代码都写得很长啊.. 
类似QQ的自动收缩.
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2021/2/28 20:29:02
4楼: 收藏了,谢谢楼主。
----------------------------------------------
只有偏执狂才能生存!
作者:
男 xiaoxingliang1 (xiaoxingliang1) ★☆☆☆☆ -
普通会员
2021/3/1 10:39:52
5楼: 设置了ScreenSnap为true后,往左边边缘有用,右边没有效果。无边框窗体好像都没效果
----------------------------------------------
-
作者:
女 wfymqj (wfymqj) ★☆☆☆☆ -
盒子活跃会员
2021/3/1 10:45:51
5楼: 收藏了,谢谢!
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行70.3125毫秒 RSS