Add-Type -AssemblyName System.Windows.Forms
$Form = [System.Windows.Forms.Form]::new()
$Form.TopMost = $true
$Form.ShowDialog()
如果我從 powershell.exe 運行此代碼,則表單不會成為焦點。但是如果我從 ISE 運行這段代碼,焦點就會轉移到表單上。為什么會發生這種情況,以及如何解決?我希望表單不會像 powershell.exe 那樣分散注意力。
UPD
可能是這個頁面可以在這種情況下提供幫助......
uj5u.com熱心網友回復:
使用該.ShowDialog()方法以模態呼叫表單,這意味著您的 PowerShell 腳本的執行將被阻止(無回應),直到表單關閉。
因此,您必須:
使用該
.Show()方法以非模態方式顯示表單,以確保您的 PowerShell 腳本繼續執行。- 反過來,這要求您進入一個回圈,在該回圈中
[System.Windows.Forms.Application]::DoEvents()定期呼叫以確保表單保持回應。
- 反過來,這要求您進入一個回圈,在該回圈中
為了確保表單在
.Show()被呼叫時不會獲得焦點,您必須對類進行子Forms類化 以覆寫ShowWithoutActivation屬性,正如您所發現的。- 反過來,這需要使用臨時編譯的 C# 代碼通過
Add-Type.
- 反過來,這需要使用臨時編譯的 C# 代碼通過
警告:如果您還想
.TopMost = $true為表單設定,為了始終在其他視窗的頂部顯示該表單,則需要一種解決方法以在各種主機環境中可靠運行 - 請參閱底部部分。
把它們放在一起:
- 注意:Ctrl-C啟動腳本后按將終止它并關閉表單。這有效的事實證明呼叫者的視窗保持焦點。
# Derive a custom form class from System.Windows.Forms.Form
# that doesn't activate itself when loaded.
Add-Type -ReferencedAssemblies System.Windows.Forms, System.ComponentModel.Primitives @'
public class MyForm: System.Windows.Forms.Form {
protected override bool ShowWithoutActivation { get { return true; } }
}
'@ -WarningAction Ignore
# Create an instance of the custom form class.
$form = [MyForm]::new()
# Show the form *non-modally*, with .Show() rather than
# .ShowDialog(), which is the prerequisite for not blocking this script.
$form.Show()
# Perform operations while the form is being shown.
try {
do {
# Process form events.
[System.Windows.Forms.Application]::DoEvents()
# Perform operations while the form is being displayed.
Start-Sleep -Milliseconds 200
Write-Host . -NoNewline
} while ($form.Visible)
} finally {
# Make sure that the form gets closed and disposed of.
$form.Dispose()
}
對于反向用例,即如果您想確保表單確實獲得焦點- 默認情況下不會始終如一地發生- 使用以下內容:
在呼叫之前$Form.ShowDialog(),為Load事件添加一個處理程式,以確保表單在加載后接收焦點:
Add-Type -AssemblyName System.Windows.Forms
$form = [System.Windows.Forms.Form]::new()
# Ensure that the form receives the focus on loading.
# (Situationally, especially when run shortly after session startup,
# the form may otherwise end up without the focus.)
$form.add_Load({
$this.Activate()
})
$form.ShowDialog()
使表單最頂層的解決方法:
由于我不知道的原因,將表單的.TopMost屬性設定為$true可能會在(過時的)ISE 中、在 Visual Studio Code(ISE 繼任者)和 Windows 終端中的會話中的第一次呼叫中安靜地、間歇性地發生故障。
以下應該解決這些問題。請注意,在重新激活呼叫者視窗之前,視窗可能會非常短暫地激活,但在實踐中應該不會引起注意:
Add-Type -AssemblyName System.Windows.Forms
# Create a helper type for activating a window by hWnd (window handle)
Add-Type -Namespace Util -Name WinApi -MemberDefinition @'
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
'@
# Create an instance of the custom form class.
$form = [System.Windows.Forms.Form]::new()
# Get the caller's main window handle, to use it for reactivation later.
$thisHWnd = (Get-Process -Id $pid).MainWindowHandle
# Show the form *non-modally*, with .Show() rather than
# .ShowDialog(), which is the prerequisite for not blocking this script.
# Note: This *typically activates* the form (gives it the focus), though not consistently.
$form.Show()
# Perform operations while the form is being shown.
try {
# Set the workaround flags.
$makeTopMost = $true; $reactivateMe = $true
do {
# Process form events.
[System.Windows.Forms.Application]::DoEvents()
# Apply workarounds and reset the flags.
if ($reactivateMe) { $null =[Util.WinApi]::SetForegroundWindow($thisHWnd); $reactivateMe = $false }
if ($makeTopMost) { $form.TopMost = $true; $makeTopMost = $false }
# Perform operations while the form is being displayed.
Start-Sleep -Milliseconds 200
Write-Host ([Util.WinApi]::GetForegroundWindow() -eq $thisHWnd) -NoNewline
} while ($form.Visible)
} finally {
# Make sure that the form gets closed and disposed of.
$form.Dispose()
}
uj5u.com熱心網友回復:
不知道你說的“表單沒有焦點”是什么意思,但我猜你希望它成為頂級視窗。
在這種情況下,除了$Form.TopMost = $true,還要設定TopLevel屬性:
$form.TopLevel = $true
- 一個頂級的形式是沒有父的形式,或者它的父表單是桌面視窗的視窗。頂級視窗通常用作應用程式中的主要表單。
- 甲最上面的形式是重疊的所有其它(非最上面的),即使它不是活性或前景形式形式形式。最頂層的表單始終顯示在桌面上視窗的 z 順序中的最高點。您可以使用此屬性創建始終顯示在應用程式中的表單,例如查找和替換工具視窗。
- 的活性形式指該形式具有焦點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/337110.html
