magnetic.pas

来自「下面又是翻译: 韩国人 Silhwan Hyun 改写。 TMagnetic」· PAS 代码 · 共 852 行 · 第 1/2 页

PAS
852
字号
            end;

            // verify connections
            pvCheckGlueing;

            // Success
            Result := True;
            Break;
        End;
    end;
End;

procedure TMagnetic.CheckGlueing;
begin
    // Check ALL windows for possible new *connections*.
    pvCheckGlueing;
End;


procedure TMagnetic.pvSizeRect(Handle: HWND; var rcWnd: TRECT; lfEdge: integer);
var
  rcTmp: TRECT;
  lC:    integer;

begin
  // Get a copy
  CopyMemory(@rcTmp, @rcWnd, LB_RECT);

  // Check all windows
  for lC := 0 to m_lWndCount do
  begin
    with m_rcWnd[lC] do
    begin
      // Avoid hidden window
      if lC <> 0 then  // m_rcWnd[0] has the window rect of Desktop area
        if not IsWindowVisible(m_uWndInfo[lc].h_wnd) then   // **************** Added
           continue;

      // Avoid current window
      if (m_uWndInfo[lC].h_wnd <> Handle) then
      begin
        // X magnetism
        if (rcWnd.Top < Bottom + SnapWidth) and (rcWnd.Bottom > Top - SnapWidth) then
        begin
          case lfEdge of

            WMSZ_LEFT, WMSZ_TOPLEFT, WMSZ_BOTTOMLEFT:
            begin
              //Case True of
              case Abs(rcTmp.Left - Left) < SnapWidth of
                True:
                  rcWnd.Left := Left;
              end;
              case Abs(rcTmp.Left - Right) < SnapWidth of
                True:
                  rcWnd.Left := Right;
              end;
            end;
            WMSZ_RIGHT, WMSZ_TOPRIGHT, WMSZ_BOTTOMRIGHT:
            begin
              case Abs(rcTmp.Right - Left) < SnapWidth of
                True:
                  rcWnd.Right := Left;
              end;
              case Abs(rcTmp.Right - Right) < SnapWidth of
                True:
                  rcWnd.Right := Right;
              end;
            end;
          end;
        end;

        // Y magnetism
        if (rcWnd.Left < Right + SnapWidth) and (rcWnd.Right > Left - SnapWidth) then
        begin
          case lfEdge of

            WMSZ_TOP, WMSZ_TOPLEFT, WMSZ_TOPRIGHT:
            begin
              case Abs(rcTmp.Top - Top) < SnapWidth of
                True:
                  rcWnd.Top := Top;
              end;
              case Abs(rcTmp.Top - Bottom) < SnapWidth of
                True:
                  rcWnd.Top := Bottom;
              end;
            end;

            WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT:
            begin
              case Abs(rcTmp.Bottom - Top) < SnapWidth of
                True:
                  rcWnd.Bottom := Top;
              end;
              case Abs(rcTmp.Bottom - Bottom) < SnapWidth of
                True:
                  rcWnd.Bottom := Bottom;
              end;
            end;
          end;
        end;
      end;
    end; // end of "with m_rcWnd[lC] do"
  end; // end of "for lC := 0 to m_lWndCount do"
end;

procedure TMagnetic.pvMoveRect(Handle: HWND; var rcWnd: TRECT);
var
  lc1:   integer;
  lc2:   integer;
  lWId:  integer;
  rcTmp: TRECT;
  lOffx: integer;
  lOffy: integer;
  hDWP:  integer;

begin
  // Get current cursor position
  GetCursorPos(m_ptCurr);

  // Check magnetism for current window
  // 'Move' current window
  OffsetRect(rcWnd, (m_ptCurr.x - rcWnd.Left) + m_ptOffset.x, 0);
  OffsetRect(rcWnd, 0, (m_ptCurr.y - rcWnd.Top) + m_ptOffset.y);

  lOffx := 0;
  lOffy := 0;

  // Check all windows
  for lc1 := 0 to m_lWndCount do
  begin
    // Avoid hidden window
    if lC1 <> 0 then  // m_rcWnd[0] has the window rect of Desktop area
      if not IsWindowVisible(m_uWndInfo[lc1].h_wnd) then   // **************** Added
         continue;

    // Avoid current window
    if (m_uWndInfo[lc1].h_wnd <> Handle) then
    begin
      // Avoid child windows
      if (m_uWndInfo[lc1].Glue = False) or
        (m_uWndInfo[lc1].hWndParent <> Handle) then
      begin
        with m_rcWnd[lc1] do
        begin
          // X magnetism
          if (rcWnd.Top < Bottom + SnapWidth) and (rcWnd.Bottom > Top - SnapWidth) then
          begin
            case Abs(rcWnd.Left - Left) < SnapWidth of
              True:
                lOffx := Left - rcWnd.Left;
            end;
            case Abs(rcWnd.Left - Right) < SnapWidth of
              True:
                lOffx := Right - rcWnd.Left;
            end;
            case Abs(rcWnd.Right - Left) < SnapWidth of
              True:
                lOffx := Left - rcWnd.Right;
            end;
            case Abs(rcWnd.Right - Right) < SnapWidth of
              True:
                lOffx := Right - rcWnd.Right;
            end;
          end;

          // Y magnetism
          if (rcWnd.Left < Right + SnapWidth) and (rcWnd.Right > Left - SnapWidth) then
          begin
            case Abs(rcWnd.Top - Top) < SnapWidth of
              True:
                lOffy := Top - rcWnd.Top;
            end;
            case Abs(rcWnd.Top - Bottom) < SnapWidth of
              True:
                lOffy := Bottom - rcWnd.Top;
            end;
            case Abs(rcWnd.Bottom - Top) < SnapWidth of
              True:
                lOffy := Top - rcWnd.Bottom;
            end;
            case Abs(rcWnd.Bottom - Bottom) < SnapWidth of
              True:
                lOffy := Bottom - rcWnd.Bottom;
            end;
          end;
        end;
      end;
    end;
  end;

  // Check magnetism for child windows
  for lc1 := 1 to m_lWndCount do
  begin
    // Avoid hidden window
    if not IsWindowVisible(m_uWndInfo[lc1].h_wnd) then   // **************** Added
       continue;

    // Child and connected window ?
    if (m_uWndInfo[lc1].Glue) and (m_uWndInfo[lc1].hWndParent = Handle) then
    begin
      // 'Move' child window
      CopyMemory(@rcTmp, @m_rcWnd[lc1], LB_RECT);
      OffsetRect(rcTmp, m_ptCurr.x - m_ptAnchor.x, 0);
      OffsetRect(rcTmp, 0, m_ptCurr.y - m_ptAnchor.y);

      for lc2 := 0 to m_lWndCount do
      begin
        if (lc1 <> lc2) then
        begin
          // Avoid hidden window
          if not IsWindowVisible(m_uWndInfo[lc2].h_wnd) then   // **************** Added
             continue;

          // Avoid child windows
          if (m_uWndInfo[lc2].Glue = False) and
            (m_uWndInfo[lc2].h_wnd <> Handle) then
          begin
            with m_rcWnd[lc2] do
            begin
              // X magnetism
              if (rcTmp.Top < Bottom + SnapWidth) and
                (rcTmp.Bottom > Top - SnapWidth) then
              begin
                case Abs(rcTmp.Left - Left) < SnapWidth of
                  True:
                    lOffx := Left - rcTmp.Left;
                end;
                case Abs(rcTmp.Left - Right) < SnapWidth of
                  True:
                    lOffx := Right - rcTmp.Left;
                end;
                case Abs(rcTmp.Right - Left) < SnapWidth of
                  True:
                    lOffx := Left - rcTmp.Right;
                end;
                case Abs(rcTmp.Right - Right) < SnapWidth of
                  True:
                    lOffx := Right - rcTmp.Right;
                end;
              end;

              // Y magnetism
              if (rcTmp.Left < Right + SnapWidth) and
                (rcTmp.Right > Left - SnapWidth) then
              begin
                case Abs(rcTmp.Top - Top) < SnapWidth of
                  True:
                    lOffy := Top - rcTmp.Top;
                end;
                case Abs(rcTmp.Top - Bottom) < SnapWidth of
                  True:
                    lOffy := Bottom - rcTmp.Top;
                end;
                case Abs(rcTmp.Bottom - Top) < SnapWidth of
                  True:
                    lOffy := Top - rcTmp.Bottom;
                end;
                case Abs(rcTmp.Bottom - Bottom) < SnapWidth of
                  True:
                    lOffy := Bottom - rcTmp.Bottom;
                end;
              end;
            end;
          end;
        end;
      end;
    end;
  end;

  // Apply offsets
  OffsetRect(rcWnd, lOffx, lOffy);

  // Glueing (move child windows, if any)
  hDWP := BeginDeferWindowPos(1);

  for lc1 := 1 to m_lWndCount do
  begin
    // Avoid hidden window
    if not IsWindowVisible(m_uWndInfo[lc1].h_wnd) then   // **************** Added
       continue;

    with m_uWndInfo[lc1] do
      // Is parent our current window ?
      if (hWndParent = Handle) and (Glue) then
      begin
        // Move 'child' window
        lWId := pvWndGetInfoIndex(Handle);
        with m_rcWnd[lc1] do
          DeferWindowPos(hDWP, m_uWndInfo[lc1].h_wnd, 0,
                         Left - (m_rcWnd[lWId].Left - rcWnd.Left),
                         Top - (m_rcWnd[lWId].Top - rcWnd.Top),
                         0{width}, 0{height},  // No size change
                         SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);
      end;
  end;


  EndDeferWindowPos(hDWP);
  // Store last cursor position
  m_ptLast := m_ptCurr;
end;

procedure TMagnetic.pvCheckGlueing;
var
  lcMain: integer;
  lc1:    integer;
  lc2:    integer;
  lWId:   integer;
begin
  // Get all windows rectangles / Reset glueing
  for lc1 := 1 to m_lWndCount do
  begin
    GetWindowRect(m_uWndInfo[lc1].h_wnd, m_rcWnd[lc1]);
    m_uWndInfo[lc1].Glue := False;
  end;

  // Check direct connection
  for lc1 := 1 to m_lWndCount do
  begin
    if not IsWindowVisible(m_uWndInfo[lc1].h_wnd) then   // **************** Added
       continue;

    if (m_uWndInfo[lc1].hWndParent <> 0) then
    begin
      // Get parent window info index
      lWId := pvWndParentGetInfoIndex(m_uWndInfo[lc1].hWndParent);
      // Connected ?
      m_uWndInfo[lc1].Glue := pvWndsConnected(m_rcWnd[lWId], m_rcWnd[lc1]);
    end;
  end;

  // Check indirect connection
  for lcMain := 1 to m_lWndCount do  // to check the windows snapped far lower level
  begin                              //  in multi-layer snapped structure
    for lc1 := 1 to m_lWndCount do
    begin
      // Avoid hidden window
      if not IsWindowVisible(m_uWndInfo[lc1].h_wnd) then   // **************** Added
         continue;

      if (m_uWndInfo[lc1].Glue) then
      begin
        for lc2 := 1 to m_lWndCount do
        begin
          // Avoid hidden window
          if not IsWindowVisible(m_uWndInfo[lc2].h_wnd) then   // **************** Added
             continue;
          if (lc1 <> lc2) then
          begin
            if (m_uWndInfo[lc1].hWndParent = m_uWndInfo[lc2].hWndParent) then
            begin
              // Connected ?
              if (m_uWndInfo[lc2].Glue = False) then
                  m_uWndInfo[lc2].Glue := pvWndsConnected(m_rcWnd[lc1], m_rcWnd[lc2]);
            end;
          end;
        end;  // end of for lc2
      end;
    end;   // end of for lc1
  end;   // end of for lcMain

end;

function TMagnetic.pvWndsConnected(rcWnd1: TRECT; rcWnd2: TRECT): boolean;
var
  rcUnion: TRECT;
begin
  result := false;  // assume not connected

  // Calc. union rectangle of windows
  UnionRect(rcUnion, rcWnd1, rcWnd2);

  // Bounding glue-rectangle
  if ((rcUnion.Right - rcUnion.Left) <= (rcWnd1.Right - rcWnd1.Left) +
    (rcWnd2.Right - rcWnd2.Left)) and ((rcUnion.Bottom - rcUnion.Top) <=
    (rcWnd1.Bottom - rcWnd1.Top) + (rcWnd2.Bottom - rcWnd2.Top)) then
  begin
    // Edge coincidences ?
    if (rcWnd1.Left = rcWnd2.Left) or (rcWnd1.Left = rcWnd2.Right) or
      (rcWnd1.Right = rcWnd2.Left) or (rcWnd1.Right = rcWnd2.Right) or
      (rcWnd1.Top = rcWnd2.Top) or (rcWnd1.Top = rcWnd2.Bottom) or
      (rcWnd1.Bottom = rcWnd2.Top) or (rcWnd1.Bottom = rcWnd2.Bottom) then

      pvWndsConnected := True;
  end;
end;

function TMagnetic.pvWndGetInfoIndex(Handle: HWND): integer;
var
  lC: integer;

begin
  result := -1;   // assume no matched item

  for lC := 1 to m_lWndCount do
  begin
    if (m_uWndInfo[lC].h_wnd = Handle) then
    begin
      pvWndGetInfoIndex := lC;
      break;
    end;
  end;
end;

function TMagnetic.pvWndParentGetInfoIndex(hWndParent: HWND): integer;
var
  lC: integer;
begin
  result := -1;   // assume no matched item

  for lC := 1 to m_lWndCount do
  begin
    if (m_uWndInfo[lC].h_wnd = hWndParent) then
    begin
      pvWndParentGetInfoIndex := lC;
      Break;
    end;
  end;
end;


end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?