You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为PowerShell XAML窗体添加顶部栏拖动移动功能

PowerShell XAML无标题栏窗体拖动解决方案

问题说明

窗体设置WindowStyle="None"后,默认的标题栏拖动功能失效,需手动为自定义顶部栏添加拖动逻辑。

解决步骤

通过调用Windows API实现拖动功能,需在现有代码中添加以下关键部分:

1. 引入Windows API函数

在加载XAML之前添加,用于发送系统拖动指令:

Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
    [DllImport("user32.dll")]
    public static extern bool ReleaseCapture();
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
}
"@

2. 绑定顶部栏拖动事件

在获取控件的代码段中,添加顶部栏的鼠标按下事件处理:

$topBar = $form.FindName("Top_Bar")

# 顶部栏拖动逻辑
$topBar.Add_MouseLeftButtonDown({
    [Win32]::ReleaseCapture()
    [Win32]::SendMessage($form.Handle, 0x0112, 0xF012, 0)
})

修改后的完整代码

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore

# 引入Windows API实现拖动
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
    [DllImport("user32.dll")]
    public static extern bool ReleaseCapture();
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
}
"@

# Load the XAML definition
$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="487"
        x:Name="MainWindow"
        WindowStyle="None"
        ResizeMode="NoResize"
        Background="#181735">
    <Grid>

    <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
       
        <Grid x:Name="Top_Bar" Background="#0f0f2d"
              Grid.ColumnSpan="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

          <Button x:Name="BuTClose" FontFamily="arial" Content="X" Margin="204,0,0,0" VerticalAlignment="Center" Height="25" Width="25" FontSize="16" Grid.Column="1">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="TextElement.FontFamily" Value="Arial"/>
                    <Setter Property="Background" Value="#fe6584"/>
                    <Setter Property="Cursor" Value="Hand"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#FF4c70"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Border Width="20" Height="20"
                        CornerRadius="12"
                        Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Center"
                                      HorizontalAlignment="Center"/>
                        </Border>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </Grid>
        
        <ListBox x:Name="AccountListBox" Background="#0f0f2d" Margin="152,64,151,0" Height="323" VerticalAlignment="Top" Grid.Row="1"/>
        
        <TextBlock Text="Clean AD Unlock"
                    Foreground="White"
                    Grid.Column="0"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"
                    FontFamily="Arial"
                   FontWeight="SemiBold"/>
   
        <Button x:Name="PopulateButton" Content="Check"
                    Foreground="White"
                    FontSize="14"
                    FontFamily="arial"
                    FontWeight="Medium" Margin="-97,64,239,336" Grid.Row="1">
            <Button.Style>

                <Style TargetType="Button">
                    <Setter Property="TextElement.FontFamily" Value="Arial"/>
                    <Setter Property="Background" Value="#fe6584"/>
                    <Setter Property="Cursor" Value="Hand"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#FF4c70"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Border Width="100" Height="25"
                        CornerRadius="12"
                        Background="{TemplateBinding Background}">
                        <ContentPresenter VerticalAlignment="Center"
                                      HorizontalAlignment="Center"/>
                    </Border>
                </ControlTemplate>
            </Button.Template>
        </Button>
        <Button x:Name="UnlockButton" Content="Unlock"
                    Foreground="White"
                    FontSize="14"
                    FontFamily="arial"
                    FontWeight="Medium" Margin="-97,118,239,282" Grid.Row="1">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="TextElement.FontFamily" Value="Arial"/>
                    <Setter Property="Background" Value="#fe6584"/>
                    <Setter Property="Cursor" Value="Hand"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#FF4c70"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Border Width="100" Height="25"
                        CornerRadius="12"
                        Background="{TemplateBinding Background}">
                        <ContentPresenter VerticalAlignment="Center"
                                      HorizontalAlignment="Center"/>
                    </Border>
                </ControlTemplate>
            </Button.Template>
        </Button>

         <Rectangle HorizontalAlignment="Left" Height="190" Margin="-2,234,0,0" Grid.Row="1" VerticalAlignment="Top" Width="30" RenderTransformOrigin="0.5,0.5" RadiusX="15" RadiusY="15" Fill="#FF39FF14" Opacity="0.75">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform Angle="46.572"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle HorizontalAlignment="Left" Height="207" Margin="456,23,0,0" VerticalAlignment="Top" Width="30" RenderTransformOrigin="0.5,0.5" RadiusX="15" RadiusY="15" Fill="#FF39FF14" Grid.Row="1" Opacity="0.75">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform Angle="46.572"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle HorizontalAlignment="Left" Height="182" Margin="452,-12,0,0" VerticalAlignment="Top" Width="30" RenderTransformOrigin="0.5,0.5" RadiusX="15" RadiusY="15" Fill="#FFFF10F0" Grid.RowSpan="2" Opacity="0.75">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform Angle="46.572"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle HorizontalAlignment="Left" Height="300" Margin="-47,303,0,0" VerticalAlignment="Top" Width="30" RenderTransformOrigin="0.5,0.5" RadiusX="15" RadiusY="15" Fill="#FFFF10F0" Grid.Row="1" Opacity="0.75">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform Angle="46.572"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>
    </Grid>
</Window>
"@

# Create a PowerShell XML reader and a XAML form object
$reader = [System.Xml.XmlReader]::Create([System.IO.StringReader] $xaml)
$form = [Windows.Markup.XamlReader]::Load($reader)

# Retrieve the controls from the form
$accountListBox = $form.FindName("AccountListBox")
$populateButton = $form.FindName("PopulateButton")
$unlockButton = $form.FindName("UnlockButton")
$BuTClose = $form.FindName("BuTClose")
$topBar = $form.FindName("Top_Bar")

# 顶部栏拖动逻辑
$topBar.Add_MouseLeftButtonDown({
    [Win32]::ReleaseCapture()
    [Win32]::SendMessage($form.Handle, 0x0112, 0xF012, 0)
})

# Add an event handler for the Populate Button
$populateButton.Add_Click({
    #$lockedAccounts = Get-ADUser -Filter {Enabled -eq $false} -SearchBase "OU=Stenger Users,DC=stengerlaw,DC=com" -SearchScope Subtree
    $lockedAccounts = search-adaccount -lockedout -server dc | select SamAccountName, Name
    $accountListBox.Items.Clear()
    foreach ($account in $lockedAccounts) {
        $accountListBox.Items.Add($account.SamAccountName)
    }
})

# Add an event handler for the Unlock Button
$unlockButton.Add_Click({
    $selectedAccount = $accountListBox.SelectedItem
    if ($selectedAccount) {
        $adminCreds = Get-Credential -Message "Enter your admin credentials"
        try {
            $adAccount = Get-ADUser -Identity $selectedAccount
            if ($adAccount) {
                Unlock-ADAccount -Identity $adAccount -Credential $adminCreds
                [System.Windows.MessageBox]::Show("The account '$selectedAccount' has been unlocked.", "Account Unlocked", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information)
            } else {
                [System.Windows.MessageBox]::Show("The account '$selectedAccount' was not found.", "Account Not Found", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
            }
        } catch {
            [System.Windows.MessageBox]::Show("An error occurred while unlocking the account. Error: $($_.Exception.Message)", "Error", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
        }
    } else {
        [System.Windows.MessageBox]::Show("No account selected.", "No Account Selected", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
    }
})
$BuTClose.Add_Click( {
        $form.Close()
    }
)

# Retrieve the controls from the form
$Form = $form.FindName("MainWindow")

$form.ShowDialog() | Out-Null

关键代码解释

  • ReleaseCapture():释放当前线程的鼠标捕获,确保拖动指令能正确发送到窗体
  • SendMessage($form.Handle, 0x0112, 0xF012, 0):向窗体发送WM_SYSCOMMAND系统消息,其中0xF012对应标题栏拖动的系统指令,模拟原生拖动行为

内容的提问来源于stack exchange,提问作者Jari Carlson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:12:53