WPF 弹出行为
WPF popup behavior
我正在尝试调整 this WPF Popup 实现来实现消息传递系统。目标是在我需要发送消息时弹出窗口,用户可以通过双击消息关闭弹出窗口,消息也会在设定时间后消失。
我现在拥有的是这个
using assembly PresentationFramework
using assembly System.Windows.Forms
using assembly System.Drawing
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$pshome\powershell.exe")
[xml]$xaml = '<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="window" WindowStyle="None" Height="200" Width="400"
ResizeMode="NoResize" ShowInTaskbar="False">
<Grid Name="grid" Background="#313130" Height="200" Width="400">
<Label Name="label" Content="Messanger Test" Foreground="White" FontSize="18" Margin="10,10,0,15"/>
<TextBox x:Name="Message" Height = "50" FontSize="18" Margin="10,10,0,15" />
</Grid>
</Window>'
$window = [Windows.Markup.XamlReader]::Load([System.Xml.XmlNodeReader]::New($xaml))
$window.Left = [System.Windows.SystemParameters]::WorkArea.Width-$window.Width
$window.Top = 0
$message = $Window.FindName('Message')
# Close the window if it's double clicked
$window.Add_MouseDoubleClick({
$window.Hide()
})
$messageCount = 1
do {
if ((Get-Random -Minimum:0 -Maximum:100) -le 30) {
$messageString = "($messageCount) $(Get-Date -format 'HH:mm:ss')"
$message.Text = $messageString
Write-Host $messageString
$messageCount ++
$window.Show()
Start-Sleep -s:10
$window.Hide()
}
Start-Sleep -s:5
} while ($messageCount -le 5)
这部分有效,因为第一条消息会弹出,它会在 10 秒后隐藏。但是,双击隐藏不起作用,后续显示也不会发生。我知道正在满足条件,因为控制台会显示每个新的时间消息。
所以...
我的 MouseDoubleClick
活动出了什么问题,以及
是什么让第一条消息不显示?
您正在使用的 Start-Sleep
使代码等待而不处理其他事件,例如 MouseDoubleClick。
为了让一个window保持响应,同时等待一定时间,需要添加一个System.Windows.Forms.Timer
对象。
此计时器有一个 Tick
事件,您可以从 运行 停止它以继续执行代码。
我建议这样:
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$pshome\powershell.exe")
[xml]$xaml = '<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="window" WindowStyle="None" Height="200" Width="400"
ResizeMode="NoResize" ShowInTaskbar="False">
<Grid Name="grid" Background="#313130" Height="200" Width="400">
<Label Name="label" Content="Messenger Test" Foreground="White" FontSize="18" Margin="10,10,0,15"/>
<TextBox x:Name="Message" Height = "50" FontSize="18" Margin="10,10,0,15" />
</Grid>
</Window>'
$window = [Windows.Markup.XamlReader]::Load([System.Xml.XmlNodeReader]::New($xaml))
$window.Left = [System.Windows.SystemParameters]::WorkArea.Width-$window.Width
$window.Top = 0
$window.Topmost = $true
$message = $Window.FindName('Message')
# create a Timer object to use instead of Start-Sleep
# old PowerShell: $timer = New-Object System.Windows.Forms.Timer
$timer = [System.Windows.Forms.Timer]::new()
$timer.Add_Tick({
Write-Host ">> Timer Tick.."
$timer.Stop()
})
# Close the window if it's double clicked
$window.Add_MouseDoubleClick({
Write-Host ">> Mouse Double Click.."
$timer.Stop()
})
$maxLoops = 5
for ($messageCount = 1; $messageCount -le $maxLoops; $messageCount++) {
$messageString = "($messageCount) $(Get-Date -format 'HH:mm:ss')"
$message.Text = $messageString
Write-Host $messageString
$window.Show()
# start the timer to fire after 10 seconds and then disable itself
$timer.Stop()
$timer.Interval = 10000
$timer.Start()
# while the Tick event did not occur, respond to other events
# such as e mouse double-click on the window
while ($timer.Enabled) { [System.Windows.Forms.Application]::DoEvents() }
# the timer tick event happened or the user double-clicked the window
$window.Hide()
# end of the loop reached, no use waiting some more..?
if ($messageCount -ge $maxLoops) { break }
# start the timer to fire after (random) 1 - 5 seconds
$interval = (Get-Random -Minimum 1 -Maximum 5)
$timer.Stop()
$timer.Interval = $interval * 1000
$timer.Start()
Write-Host ">> Loop wait $interval seconds.."
while ($timer.Enabled) { [System.Windows.Forms.Application]::DoEvents() }
}
# we're done, clean-up
$timer.Dispose()
$window.Close()
我正在尝试调整 this WPF Popup 实现来实现消息传递系统。目标是在我需要发送消息时弹出窗口,用户可以通过双击消息关闭弹出窗口,消息也会在设定时间后消失。 我现在拥有的是这个
using assembly PresentationFramework
using assembly System.Windows.Forms
using assembly System.Drawing
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$pshome\powershell.exe")
[xml]$xaml = '<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="window" WindowStyle="None" Height="200" Width="400"
ResizeMode="NoResize" ShowInTaskbar="False">
<Grid Name="grid" Background="#313130" Height="200" Width="400">
<Label Name="label" Content="Messanger Test" Foreground="White" FontSize="18" Margin="10,10,0,15"/>
<TextBox x:Name="Message" Height = "50" FontSize="18" Margin="10,10,0,15" />
</Grid>
</Window>'
$window = [Windows.Markup.XamlReader]::Load([System.Xml.XmlNodeReader]::New($xaml))
$window.Left = [System.Windows.SystemParameters]::WorkArea.Width-$window.Width
$window.Top = 0
$message = $Window.FindName('Message')
# Close the window if it's double clicked
$window.Add_MouseDoubleClick({
$window.Hide()
})
$messageCount = 1
do {
if ((Get-Random -Minimum:0 -Maximum:100) -le 30) {
$messageString = "($messageCount) $(Get-Date -format 'HH:mm:ss')"
$message.Text = $messageString
Write-Host $messageString
$messageCount ++
$window.Show()
Start-Sleep -s:10
$window.Hide()
}
Start-Sleep -s:5
} while ($messageCount -le 5)
这部分有效,因为第一条消息会弹出,它会在 10 秒后隐藏。但是,双击隐藏不起作用,后续显示也不会发生。我知道正在满足条件,因为控制台会显示每个新的时间消息。
所以...
我的 MouseDoubleClick
活动出了什么问题,以及
是什么让第一条消息不显示?
您正在使用的 Start-Sleep
使代码等待而不处理其他事件,例如 MouseDoubleClick。
为了让一个window保持响应,同时等待一定时间,需要添加一个System.Windows.Forms.Timer
对象。
此计时器有一个 Tick
事件,您可以从 运行 停止它以继续执行代码。
我建议这样:
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$pshome\powershell.exe")
[xml]$xaml = '<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="window" WindowStyle="None" Height="200" Width="400"
ResizeMode="NoResize" ShowInTaskbar="False">
<Grid Name="grid" Background="#313130" Height="200" Width="400">
<Label Name="label" Content="Messenger Test" Foreground="White" FontSize="18" Margin="10,10,0,15"/>
<TextBox x:Name="Message" Height = "50" FontSize="18" Margin="10,10,0,15" />
</Grid>
</Window>'
$window = [Windows.Markup.XamlReader]::Load([System.Xml.XmlNodeReader]::New($xaml))
$window.Left = [System.Windows.SystemParameters]::WorkArea.Width-$window.Width
$window.Top = 0
$window.Topmost = $true
$message = $Window.FindName('Message')
# create a Timer object to use instead of Start-Sleep
# old PowerShell: $timer = New-Object System.Windows.Forms.Timer
$timer = [System.Windows.Forms.Timer]::new()
$timer.Add_Tick({
Write-Host ">> Timer Tick.."
$timer.Stop()
})
# Close the window if it's double clicked
$window.Add_MouseDoubleClick({
Write-Host ">> Mouse Double Click.."
$timer.Stop()
})
$maxLoops = 5
for ($messageCount = 1; $messageCount -le $maxLoops; $messageCount++) {
$messageString = "($messageCount) $(Get-Date -format 'HH:mm:ss')"
$message.Text = $messageString
Write-Host $messageString
$window.Show()
# start the timer to fire after 10 seconds and then disable itself
$timer.Stop()
$timer.Interval = 10000
$timer.Start()
# while the Tick event did not occur, respond to other events
# such as e mouse double-click on the window
while ($timer.Enabled) { [System.Windows.Forms.Application]::DoEvents() }
# the timer tick event happened or the user double-clicked the window
$window.Hide()
# end of the loop reached, no use waiting some more..?
if ($messageCount -ge $maxLoops) { break }
# start the timer to fire after (random) 1 - 5 seconds
$interval = (Get-Random -Minimum 1 -Maximum 5)
$timer.Stop()
$timer.Interval = $interval * 1000
$timer.Start()
Write-Host ">> Loop wait $interval seconds.."
while ($timer.Enabled) { [System.Windows.Forms.Application]::DoEvents() }
}
# we're done, clean-up
$timer.Dispose()
$window.Close()