【问题标题】:Move a window on keypress + mouse (like linux ALT + mouse down)在按键 + 鼠标上移动窗口(如 linux ALT + 鼠标向下)
【发布时间】:2010-06-23 10:14:26
【问题描述】:

很简单,我想按 ALT+MOUSE 移动窗口,就像 linux os (ALT+drag)。

可以将一个win32 api(移动api)传递给有兴趣点击它的窗口吗?

我有一个按下挂钩键的 Windows 服务(特别是 ALT 按钮)。 当按下 ALT 键并验证 mouse down 事件时,我想将窗口点击移动到任何地方,而不仅仅是在标题栏上!

目前我以这种方式移动表单窗口:

using System.Runtime.InteropServices;

[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, int wParam, int lParam );
[DllImportAttribute( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
public static extern bool ReleaseCapture();

private void Form1_MouseDown( object sender, MouseEventArgs e )
{
  ReleaseCapture();
  SendMessage( this.Handle, 0xa1, 0x2, 0 );
}

如何通过单击并在调用 SendMessage() 后获取特定窗口的窗口句柄?

有可能吗?

【问题讨论】:

  • 请不要在标题中重复诸如“C#”之类的标签。这就是标签的用途。

标签: c# winforms mouse key move


【解决方案1】:

您可以通过捕获 Windows 发送的 WM_NCHITTEST 消息来执行此操作,以查看单击了窗口的哪个区域。您可以通过返回 HTCAPTION 来欺骗它,它会尽职尽责地执行您在单击窗口标题时通常会执行的鼠标操作。包括移动窗口。将此代码粘贴到您的表单中:

    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        // Trap WM_NCHITTEST when the ALT key is down
        if (m.Msg == 0x84 && (Control.ModifierKeys == Keys.Alt)) {
            // Translate HTCLIENT to HTCAPTION
            if (m.Result == (IntPtr)1) m.Result = (IntPtr)2;
        }
    }

【讨论】:

  • 嗯...这没关系,但它只移动我的表单。我需要移动其他窗口...
  • 将此代码放在一个基表单类中。从该基类继承您的其他表单。
  • 不,对不起...但我想移动系统窗口,如 calc、记事本、浏览器、任何窗口...像这样:howtogeek.com/howto/windows-vista/…
【解决方案2】:

我自己解决了这个问题,我自己计算出了一些有趣的东西,对我来说非常适合任何窗口(任何活动的前景窗口)。有点长,但如果你跟着 cmets 走,真的很容易理解,希望对你有帮助:) 它的工作方式是按下某个注册的组合键,例如 Ctrl+Alt+M 并且鼠标将停留在活动窗口的中心,您移动鼠标,窗口跟随它,再次按下 SAME 组合键即可释放,无需单击鼠标或其他任何操作。

public void MoveWindow_AfterMouse()
    {
      // 1- get a handle to the foreground window (or any window that you want to move).
      // 2- set the mouse pos to the window's center.
      // 3- let the window move with the mouse in a loop, such that:
      //    win(x) = mouse(x) - win(width)/2   
      //    win(y) = mouse(y) - win(height)/2
      // This is because the origin (point of rendering) of the window, is at its top-left corner and NOT its center!

      // 1- 
      IntPtr hWnd = WinAPIs.GetForegroundWindow();

      // 2- Then:
      // first we need to get the x, y to the center of the window.
      // to do this, we have to know the width/height of the window.
      // to do this, we could use GetWindowRect which will give us the coords of the bottom right and upper left corners of the window,
      // with some math, we could deduce the width/height of the window.
      // after we do that, we simply set the x, y coords of the mouse to that center.
      RECT wndRect = new RECT();
      WinAPIs.GetWindowRect(hWnd, out wndRect);
      int wndWidth = wndRect.right - wndRect.left;
      int wndHeight = wndRect.bottom - wndRect.top; // cuz the more you go down, the more y value increases.
      Point wndCenter = new Point(wndWidth / 2, wndHeight / 2); // this is the center of the window relative to itself.
      WinAPIs.ClientToScreen(hWnd, out wndCenter); // this will make its center relative to the screen coords.
      WinAPIs.SetCursorPos(wndCenter.X, wndCenter.Y);

      // 3- Moving :)))
      while (true)
      {
        Point cursorPos = new Point();
        WinAPIs.GetCursorPos(out cursorPos);
        int xOffset = cursorPos.X - wndWidth / 2;
        int yOffset = cursorPos.Y - wndHeight / 2;
        WinAPIs.MoveWindow(hWnd, xOffset, yOffset, wndWidth, wndHeight, true);
        Thread.Sleep(25);
      }
    }

现在:

int moveCommandToggle = 0;
protected override void WndProc(ref Message m)
{
   if (m.Msg == 0x0312)
   {
     int keyID = m.WParam.ToInt32();
     if(keyID == some_key_combo_you_registered_for_the_moving)
     {
         if (moveCommandToggle++ % 2 == 0)
         {
            mover = new Thread(() => MoveWindow_AfterMouse());
            mover.Start();
         }
         else mover.Abort();
      }
    }
 }

如果您想了解 RECT:

  public struct RECT
  {
    public int left;    // xCoor of upper left corner.
    public int top;     // yCoor of upper left corner.
    public int right;   // xCoor of lower right corner.
    public int bottom;  // yCoor of lower right corner.
  };

WinAPIs 只是我在其中执行 DllImports 的一个静态类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    相关资源
    最近更新 更多