PRA-only-demo/resources/desktop-picker.ps1

127 lines
5.4 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

param([string]$Mode = "element")
$ErrorActionPreference = "Continue"
Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes, WindowsBase
Add-Type -AssemblyName System.Windows.Forms
Add-Type -MemberDefinition "[DllImport(`"user32.dll`")] public static extern short GetAsyncKeyState(int key); [DllImport(`"user32.dll`", CharSet = CharSet.Unicode)] public static extern int GetWindowTextW(IntPtr h, System.Text.StringBuilder sb, int max);" -Name PickW32 -Namespace RpaPick | Out-Null
if ($Mode -eq "windows") {
$wins = @()
foreach ($p in Get-Process) {
if ($p.MainWindowHandle -ne [IntPtr]::Zero -and $p.MainWindowTitle) {
$wins += @{ title = $p.MainWindowTitle; process = $p.ProcessName }
}
}
Write-Output (ConvertTo-Json $wins -Compress -AsArray)
exit 0
}
# ---- 信息窗 ----
$form = New-Object System.Windows.Forms.Form
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None
$form.TopMost = $true
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$form.Location = New-Object System.Drawing.Point(20, 20)
$form.Size = New-Object System.Drawing.Size(480, 110)
$form.BackColor = [System.Drawing.Color]::FromArgb(20, 60, 120)
$label = New-Object System.Windows.Forms.Label
$label.Dock = [System.Windows.Forms.DockStyle]::Fill
$label.ForeColor = [System.Drawing.Color]::White
$label.Font = New-Object System.Drawing.Font("Microsoft YaHei", 10)
$form.Controls.Add($label)
# ---- 高亮窗(半透明红块) ----
$hl = New-Object System.Windows.Forms.Form
$hl.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None
$hl.TopMost = $true
$hl.ShowInTaskbar = $false
$hl.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$hl.BackColor = [System.Drawing.Color]::Red
$hl.Opacity = 0.35
# ---- 状态 ----
$stage = "hover"
$chain = New-Object System.Collections.ArrayList
$selIdx = -1
$prevPageUp = $false
$prevPageDown = $false
$prevSpace = $false
function Show-Element($el) {
if ($null -eq $el) { $script:hl.Hide(); return }
$r = $el.Current.BoundingRectangle
if ($r.Width -le 0 -or $r.Height -le 0) { $script:hl.Hide(); return }
$script:hl.Location = New-Object System.Drawing.Point([int]($r.X - 2), [int]($r.Y - 2))
$script:hl.Size = New-Object System.Drawing.Size([int]($r.Width + 4), [int]($r.Height + 4))
$script:hl.Show()
}
$form.Show()
$hl.Show()
while ($true) {
$space = ([RpaPick.PickW32]::GetAsyncKeyState(32) -band 0x8000) -ne 0
$esc = ([RpaPick.PickW32]::GetAsyncKeyState(27) -band 0x8000) -ne 0
$pgUp = ([RpaPick.PickW32]::GetAsyncKeyState(33) -band 0x8000) -ne 0
$pgDn = ([RpaPick.PickW32]::GetAsyncKeyState(34) -band 0x8000) -ne 0
if ($esc) { break }
if ($stage -eq "hover") {
$ptX = [System.Windows.Forms.Cursor]::Position.X
$ptY = [System.Windows.Forms.Cursor]::Position.Y
$point = New-Object System.Windows.Automation.Point($ptX, $ptY)
$el = $null
try { $el = [System.Windows.Automation.AutomationElement]::FromPoint($point) } catch {}
if ($el) {
$c = $el.Current
$ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "")
$label.Text = "名称: " + $c.Name + [Environment]::NewLine + "类型: " + $ctrlName + [Environment]::NewLine + "空格=锁定 Esc=取消"
Show-Element $el
}
if ($space -and -not $prevSpace -and $el) {
# 进入微调:收集从根到命中的元素链
$walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker
$chain.Clear()
$cur = $el
while ($cur -and -not $cur.Equals([System.Windows.Automation.AutomationElement]::RootElement)) {
$cc = $cur.Current
$rr = $cc.BoundingRectangle
[void]$chain.Insert(0, @{ el = $cur; name = [string]$cc.Name; automationId = [string]$cc.AutomationId; controlType = $cc.ControlType.ProgrammaticName.Replace("ControlType.", ""); x = [int]$rr.X; y = [int]$rr.Y; w = [int]$rr.Width; h = [int]$rr.Height })
$cur = $walker.GetParent($cur)
}
$selIdx = $chain.Count - 1
$stage = "adjust"
$label.Text = "微调模式:PageUp/PageDown 切换层级,空格确认,Esc 取消"
}
}
if ($stage -eq "adjust") {
if ($pgUp -and -not $prevPageUp -and $selIdx -gt 0) { $selIdx -= 1 }
if ($pgDn -and -not $prevPageDown -and $selIdx -lt ($chain.Count - 1)) { $selIdx += 1 }
$item = $chain[$selIdx]
if ($item) {
$label.Text = "层级 " + ($selIdx + 1) + "/" + $chain.Count + " 名称: " + $item.name + [Environment]::NewLine + "类型: " + $item.controlType + [Environment]::NewLine + "PageUp/PageDown=切层级 空格=确认 Esc=取消"
$hl.Location = New-Object System.Drawing.Point($item.x - 2, $item.y - 2)
$hl.Size = New-Object System.Drawing.Size($item.w + 4, $item.h + 4)
$hl.Show()
}
if ($space -and -not $prevSpace) {
$item = $chain[$selIdx]
# 窗口名 = 链中第一个带窗口句柄的层
$rootName = ""
foreach ($it in $chain) { if ($it.name) { $rootName = $it.name; break } }
$result = @{ selected = $selIdx; window = $rootName; name = $item.name; automationId = $item.automationId; controlType = $item.controlType; x = $item.x; y = $item.y; w = $item.w; h = $item.h }
break
}
}
$prevPageUp = $pgUp
$prevPageDown = $pgDn
$prevSpace = $space
Start-Sleep -Milliseconds 60
}
$form.Close()
$hl.Close()
if ($result) { Write-Output (ConvertTo-Json $result -Compress) } else { Write-Output (ConvertTo-Json @{ cancelled = $true } -Compress) }