简体   繁体   English

Powershell - 在 powershell 控制台中捕获鼠标单击事件

[英]Powershell - capture mouse click event inside a powershell console

I'm trying to do some trick with Powershell.我正在尝试使用 Powershell 做一些技巧。 I want to write a script and that script can listen to the mouse events (click, move, etc) inside the powershell console.我想编写一个脚本,该脚本可以侦听 powershell 控制台内的鼠标事件(单击、移动等)。

For example, while my script is active, when I click the mouse inside the powershell console, the console can output the position of my cursor.例如,当我的脚本处于活动状态时,当我在 powershell 控制台内单击鼠标时,控制台可以输出我的光标位置。

Is it possible?是否可以? If possible, how?如果可以,怎么做?

Thanks in advance.提前致谢。

I've found that it's possible to do this using the following:我发现可以使用以下方法来做到这一点:

[System.Windows.Forms.UserControl]::MouseButtons

Which returns a string of the currently pressed mouse buttons.它返回当前按下的鼠标按钮的字符串。 We poll this and [System.Windows.Forms.Cursor]::Position as per WorWin to keep track of where the mouse is and what buttons are pressed.我们根据 WorWin 轮询此和[System.Windows.Forms.Cursor]::Position以跟踪鼠标的位置和按下的按钮。

Keeping track of where the mouse is inside of the console window is a bit tricky, though.但是,跟踪鼠标在控制台窗口内的位置有点棘手。 I personally use a custom class for this.我个人为此使用自定义类。

Add-Type -ReferencedAssemblies System.Drawing @"
using System;
using System.Drawing;
using System.Runtime.InteropServices;
public class Window 
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();

    public RECT bounds;
    public bool isForeground;
    private IntPtr hWnd;
    public int Width;
    public int Height;

    public Window(IntPtr handle)
    {
        hWnd = handle;
        Update();
    }
    public void Update()
    {
        if(GetWindowRect(hWnd, out bounds))
        {
            Width = bounds.Right - bounds.Left;
            Height = bounds.Bottom - bounds.Top;

            if(GetForegroundWindow() == hWnd){isForeground = true;}
            else{isForeground = false;}
        }
    }
    public bool Contains(Point pt)
    {
        return bounds.Contains(pt);
    }
}
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;

    public Boolean Contains(Point pt)
    {
        if( (pt.X >= Left) && (pt.X < Right) && (pt.Y >= Top) && (pt.Y < Bottom) ){ return true;}
        return false;
    }
}
public struct POINT
{
    public int X;
    public int Y;
    public static implicit operator Point(POINT point)
    {
        return new Point(point.X, point.Y);
    }
}
"@

To get the Powershell console window:要获取 Powershell 控制台窗口:

$ourID = (get-process -id (Get-WmiObject -class win32_process -Filter ("ProcessID = $pid")).parentprocessid).mainwindowhandle;
$win = New-Object Window($ourID);

Now, $win.bounds gives us the outer bounds of the console window, so if we want to find which buffercell the cursor is in we're going to have to do some work on our bounds.现在, $win.bounds为我们提供了控制台窗口的外部边界,因此如果我们想找到光标所在的缓冲区单元,我们将不得不在边界上做一些工作。

$innerOffsets = new-object RECT;
$innerOffsets.Top = [Windows.Forms.SystemInformation]::CaptionHeight + [Windows.Forms.SystemInformation]::HorizontalResizeBorderThickness + [Windows.Forms.SystemInformation]::Border3DSize.Height;
$innerOffsets.Bottom = -([Windows.Forms.SystemInformation]::HorizontalResizeBorderThickness + [Windows.Forms.SystemInformation]::Border3DSize.Height);    
$inneroffsets.Left = [Windows.Forms.SystemInformation]::VerticalResizeBorderThickness + [Windows.Forms.SystemInformation]::Border3DSize.Width;
$inneroffsets.Right = -([Windows.Forms.SystemInformation]::VerticalResizeBorderThickness + [Windows.Forms.SystemInformation]::Border3DSize.Width);

if([console]::bufferheight -gt [console]::windowheight)
{
    $inneroffsets.right -= [Windows.Forms.SystemInformation]::HorizontalScrollBarThumbWidth;
}
if([console]::bufferwidth -gt [console]::windowwidth)
{
    $inneroffsets.bottom -= [Windows.Forms.SystemInformation]::VerticalScrollBarThumbHeight;
}

This gives us the offsets we need to get the inner bounds of the window.这为我们提供了获取窗口内部边界所需的偏移量。 From here we can get our relative location on the window.从这里我们可以得到我们在窗口上的相对位置。

$mp = [Windows.Forms.Cursor]::Position;
$mp.x -= ($win.bounds.left + $inneroffsets.left);
$mp.y -= ($win.bounds.top + $inneroffsets.top);

Now we can convert our mouse position to buffer cell position.现在我们可以将鼠标位置转换为缓冲区单元格位置。

$innerWidth = ($win.bounds.right + $inneroffsets.right) - ($win.bounds.left + $inneroffsets.left);
$innerheight = ($win.bounds.bottom + $inneroffsets.bottom) - ($win.bounds.top + $inneroffsets.top);
$mp.x = [Math]::Floor($mp.x / ( $innerwidth / [console]::windowWidth));
$mp.y = [Math]::Floor($mp.y / ( $innerheight / [console]::windowheight));

You'll have to use $win.update() every time you check.每次检查时都必须使用$win.update() You can also use $win.isforeground and [Windows.Forms.UserControl]::MouseButtons -match "Left" to only check when the console window is clicked as well.您还可以使用$win.isforeground[Windows.Forms.UserControl]::MouseButtons -match "Left"来仅检查何时单击控制台窗口。

Not sure how all of it is going to piece together.不确定所有这些将如何拼凑在一起。 Maybe this will help.也许这会有所帮助。

<# Gets the Mouse Position #>
[System.Windows.Forms.Cursor]::Position

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM