feat: 新增本地UI模型AI拾取与识别实验台
This commit is contained in:
1 parent
ee60435e2b
commit
e956ec9055
27 files changed
+1848
-525
No files matched your search
@@ -150,10 +150,15 @@ function Set-ClickThrough($form) {
|
||||
}
|
||||
|
||||
function Set-HighlightBox([int]$x, [int]$y, [int]$w, [int]$h) {
|
||||
$hl.Location = New-Object System.Drawing.Point(($x - 2), ($y - 2))
|
||||
$hl.Size = New-Object System.Drawing.Size(($w + 4), ($h + 4))
|
||||
$hl.Show()
|
||||
Set-ClickThrough $hl
|
||||
$bounds = New-Object System.Drawing.Rectangle(($x - 2), ($y - 2), ($w + 4), ($h + 4))
|
||||
if (-not $hl.Visible) {
|
||||
$hl.Bounds = $bounds
|
||||
$hl.Show()
|
||||
Set-ClickThrough $hl
|
||||
} elseif ($hl.Bounds.X -ne $bounds.X -or $hl.Bounds.Y -ne $bounds.Y -or $hl.Bounds.Width -ne $bounds.Width -or $hl.Bounds.Height -ne $bounds.Height) {
|
||||
# 不重设隐藏;同一元素内移动时不重复改窗口,避免 WinForms 分层窗体重绘闪烁
|
||||
$hl.Bounds = $bounds
|
||||
}
|
||||
}
|
||||
function Hide-Highlight { $hl.Hide() }
|
||||
function Get-DeepestAtPoint([double]$px, [double]$py) {
|
||||
@@ -187,6 +192,19 @@ $prevSpace = $false
|
||||
$prevPgUp = $false
|
||||
$prevPgDn = $false
|
||||
$prevF2 = $false
|
||||
$cacheX = [int]::MinValue
|
||||
$cacheY = [int]::MinValue
|
||||
$cacheEl = $null
|
||||
$cacheCtrlName = ""
|
||||
$cacheName = ""
|
||||
$cachePaneX = 0
|
||||
$cachePaneY = 0
|
||||
$cachePaneW = 0
|
||||
$cachePaneH = 0
|
||||
$cacheAt = [DateTime]::MinValue
|
||||
$lastQueryAt = [DateTime]::MinValue
|
||||
$queryGapMs = 45
|
||||
$cacheTtlMs = 1800
|
||||
Write-PickLog "loop start"
|
||||
while ($true) {
|
||||
try {
|
||||
@@ -199,17 +217,49 @@ while ($true) {
|
||||
if ($stage -eq "hover") {
|
||||
$ptX = [System.Windows.Forms.Cursor]::Position.X
|
||||
$ptY = [System.Windows.Forms.Cursor]::Position.Y
|
||||
$el = Get-DeepestAtPoint $ptX $ptY
|
||||
$now = [DateTime]::UtcNow
|
||||
$samePoint = ($ptX -eq $cacheX -and $ptY -eq $cacheY)
|
||||
$insideCache = $cacheEl -ne $null -and $ptX -ge $cachePaneX -and $ptX -lt ($cachePaneX + $cachePaneW) -and $ptY -ge $cachePaneY -and $ptY -lt ($cachePaneY + $cachePaneH)
|
||||
$cacheAlive = ($null -ne $cacheEl -and ($now - $cacheAt).TotalMilliseconds -le $cacheTtlMs)
|
||||
# 鼠标还在当前元素矩形内部时不丢弃缓存;UIA 查询完成后才切换,避免移动过程先隐藏再显示
|
||||
if (-not $samePoint -and -not $insideCache) { $cacheEl = $null }
|
||||
if (-not $cacheAlive -and ($now - $lastQueryAt).TotalMilliseconds -ge $queryGapMs) {
|
||||
$queryX = $ptX
|
||||
$queryY = $ptY
|
||||
$lastQueryAt = [DateTime]::UtcNow
|
||||
try { $queried = Get-DeepestAtPoint $queryX $queryY } catch { $queried = $null; Write-PickLog ("QUERY ERR: " + $_.Exception.Message) }
|
||||
$afterX = [System.Windows.Forms.Cursor]::Position.X
|
||||
$afterY = [System.Windows.Forms.Cursor]::Position.Y
|
||||
if ($afterX -ne $queryX -or $afterY -ne $queryY) {
|
||||
$queried = $null
|
||||
Write-PickLog "query stale: cursor moved"
|
||||
}
|
||||
if ($null -ne $queried) {
|
||||
$qc = $queried.Current
|
||||
$qr = $qc.BoundingRectangle
|
||||
$cacheEl = $queried
|
||||
$cacheX = $queryX
|
||||
$cacheY = $queryY
|
||||
$cacheAt = [DateTime]::UtcNow
|
||||
$cacheCtrlName = $qc.ControlType.ProgrammaticName.Replace("ControlType.", "")
|
||||
$cacheName = [string]$qc.Name
|
||||
$cachePaneX = [int]$qr.X
|
||||
$cachePaneY = [int]$qr.Y
|
||||
$cachePaneW = [int]$qr.Width
|
||||
$cachePaneH = [int]$qr.Height
|
||||
} else {
|
||||
$cacheEl = $null
|
||||
$cacheCtrlName = ""
|
||||
$cacheName = ""
|
||||
}
|
||||
}
|
||||
$el = $cacheEl
|
||||
if ($el) {
|
||||
$c = $el.Current
|
||||
$ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "")
|
||||
$r = $c.BoundingRectangle
|
||||
$paneX = [int]$r.X; $paneY = [int]$r.Y; $paneW = [int]$r.Width; $paneH = [int]$r.Height
|
||||
Set-HighlightBox $paneX $paneY $paneW $paneH
|
||||
$aiHint = if ($ctrlName -eq "Pane") { " [F2]AI识别" } else { "" }
|
||||
$infoLabel.Text = "名称: " + $c.Name + " 类型: " + $ctrlName + " [空格]锁定" + $aiHint + " [Esc]取消"
|
||||
Set-HighlightBox $cachePaneX $cachePaneY $cachePaneW $cachePaneH
|
||||
$aiHint = if ($cacheCtrlName -eq "Pane") { " [F2]AI识别" } else { "" }
|
||||
$infoLabel.Text = "名称: " + $cacheName + " 类型: " + $cacheCtrlName + " [空格]锁定" + $aiHint + " [Esc]取消"
|
||||
} else { Hide-Highlight }
|
||||
if ($f2 -and -not $prevF2 -and $el -and $ctrlName -eq "Pane") {
|
||||
if ($f2 -and -not $prevF2 -and $el -and $cacheCtrlName -eq "Pane") {
|
||||
Write-PickLog "f2 ai"
|
||||
$walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker
|
||||
$cur = $el
|
||||
@@ -218,7 +268,7 @@ while ($true) {
|
||||
$topTitle = [string]$cur.Current.Name
|
||||
$cur = $walker.GetParent($cur)
|
||||
}
|
||||
$result = @{ aiRequested = $true; cursorX = $ptX; cursorY = $ptY; window = $topTitle; name = [string]$c.Name; controlType = $ctrlName; paneX = $paneX; paneY = $paneY; paneW = $paneW; paneH = $paneH }
|
||||
$result = @{ aiRequested = $true; cursorX = $ptX; cursorY = $ptY; window = $topTitle; name = $cacheName; controlType = $cacheCtrlName; paneX = $cachePaneX; paneY = $cachePaneY; paneW = $cachePaneW; paneH = $cachePaneH }
|
||||
break
|
||||
}
|
||||
if ($space -and -not $prevSpace -and $el) {
|
||||
@@ -226,7 +276,7 @@ while ($true) {
|
||||
$stage = "locked"
|
||||
$chain = New-Object System.Collections.ArrayList
|
||||
$walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker
|
||||
$cur = $el
|
||||
$cur = $cacheEl
|
||||
while ($cur -and -not $cur.Equals([System.Windows.Automation.AutomationElement]::RootElement)) {
|
||||
$c = $cur.Current
|
||||
$r = $c.BoundingRectangle
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"do_normalize": false,
|
||||
"do_rescale": true,
|
||||
"do_resize": true,
|
||||
"feature_extractor_type": "ImageFeatureExtractor",
|
||||
"resample": 2,
|
||||
"rescale_factor": 0.00392156862745098,
|
||||
"size_divisor": 16,
|
||||
"size": {
|
||||
"longest_edge": 640
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user