批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程
[批处理文件精品]批处理版照片整理器[批处理文件精品]纯批处理备份&还原驱动在线第三方下载
返回列表 发帖

[问题求助] 如何让PowerShell创建的窗口居中显示在已打开的某窗口中央

下面的代码可以在屏幕中央显示一个窗口, 我想让窗口显示在已打开的记事本窗口中央, 如果没有记事本窗口才显示在屏幕中央, 还没搜索到相关的资料
  1. Add-Type -AssemblyName system.Windows.Forms
  2. Add-Type -AssemblyName system.Drawing
  3. $Form = New-Object windows.Forms.Form
  4. $Form.Size = New-Object drawing.Size(200, 120)
  5. $Form.startposition = "centerscreen"
  6. $Form.Text = "Test of Form"
  7. $Form.MaximizeBox = $false
  8. $Form.MinimizeBox = $false
  9. $Form.Font = New-Object drawing.Font("Times New Roman", 10, [Drawing.FontStyle]::Bold)
  10. $Form.BackColor = "LightBlue"
  11. $Form.FormBorderStyle = "FixedSingle"
  12. $Form.ShowDialog()
复制代码

用winapi
  1. cls
  2. #Windows API
  3. $code=@'
  4.     using System.Runtime.InteropServices;
  5.     public static class WinApi{
  6.         public struct Rect {
  7.             public uint left;
  8.             public uint top;
  9.             public uint right;
  10.             public uint bottom;
  11.         };
  12.         [DllImport("user32.dll")]
  13.         public static extern bool SetWindowPos(uint hwnd,uint hpart,uint x,uint y,uint cx,uint cy,uint flags);
  14.         [DllImport("user32.dll")]
  15.         public static extern bool GetWindowRect(uint hwnd,ref Rect rect);
  16.     }
  17. '@
  18. Add-Type -TypeDefinition $code
  19. Add-Type -AssemblyName system.Windows.Forms
  20. Add-Type -AssemblyName system.Drawing
  21. $Form = New-Object windows.Forms.Form
  22. $Form.Size = New-Object drawing.Size(200, 120)
  23. $Form.Text = "Test of Form"
  24. $Form.MaximizeBox = $false
  25. $Form.MinimizeBox = $false
  26. $Form.Font = New-Object drawing.Font("Times New Roman", 10, [Drawing.FontStyle]::Bold)
  27. $Form.BackColor = "LightBlue"
  28. $Form.FormBorderStyle = "FixedSingle"
  29. $rect = New-Object 'WinApi+Rect'
  30. $hwnd = (Get-Process notepad -ErrorAction SilentlyContinue| Select-Object -First 1).MainWindowHandle
  31. if($hwnd -eq $null){
  32.     $Form.StartPosition = 'CenterScreen'
  33. } else {
  34.     [void][WinApi]::GetWindowRect([int32]$hwnd,[ref]$rect)
  35.     $x = $rect.left + ($rect.right - $rect.left - $Form.Width)/2
  36.     $y = $rect.top + ($rect.bottom - $rect.top - $Form.Height)/2
  37.     [WinApi]::SetWindowPos([int32]$Form.Handle,$null,$x,$y,0,0,1)
  38. }
  39. $Form.ShowDialog()
复制代码

TOP

回复 2# went


多谢大佬,

有两个问题请教:
1. 在我理解New-Object后应该跟着已经存在的类名, 但没有这个类
$rect = New-Object 'WinApi+Rect'   

2.如果记事本窗口处于最小化时, 执行代码, 也会有响应, 但是只在任务栏上显示一个按钮, 点它也没反应,
能否加个判断, 如果有记事本程序运行着, 先激活它一下变成当前窗口,然后再执行代码?

TOP

本帖最后由 went 于 2022-11-25 10:48 编辑

回复 3# 小白龙


    Rect是自定义的结构体
    不想用结构体也可以直接传数组参数
  1. cls
  2. #Windows API
  3. $code=@'
  4.     using System.Runtime.InteropServices;
  5.     public static class WinApi{
  6.         [DllImport("user32.dll")]
  7.         public static extern bool SetWindowPos(uint hwnd,uint hpart,uint x,uint y,uint cx,uint cy,uint flags);
  8.         [DllImport("user32.dll")]
  9.         public static extern bool GetWindowRect(uint hwnd,uint[] arr);
  10.         [DllImport("user32.dll")]
  11.         public static extern bool ShowWindow(uint hwnd,uint show);
  12.     }
  13. '@
  14. Add-Type -TypeDefinition $code
  15. Add-Type -AssemblyName system.Windows.Forms
  16. Add-Type -AssemblyName system.Drawing
  17. $Form = New-Object windows.Forms.Form
  18. $Form.Size = New-Object drawing.Size(200, 120)
  19. $Form.Text = "Test of Form"
  20. $Form.MaximizeBox = $false
  21. $Form.MinimizeBox = $false
  22. $Form.Font = New-Object drawing.Font("Times New Roman", 10, [Drawing.FontStyle]::Bold)
  23. $Form.BackColor = "LightBlue"
  24. $Form.FormBorderStyle = "FixedSingle"
  25. $hwnd = (Get-Process notepad -ErrorAction SilentlyContinue| Select-Object -First 1).MainWindowHandle
  26. if($hwnd -eq $null){
  27.     $Form.StartPosition = 'CenterScreen'
  28. } else {
  29.     $arr = New-Object 'int32[]'(4)
  30.     [void][WinApi]::ShowWindow([int32]$hwnd,1)
  31.     [void][WinApi]::GetWindowRect([int32]$hwnd,$arr)
  32.     $x = $arr[0] + ($arr[2] - $arr[0] - $Form.Width)/2
  33.     $y = $arr[1] + ($arr[3] - $arr[1] - $Form.Height)/2
  34.     [void][WinApi]::SetWindowPos([int32]$Form.Handle,$null,$x,$y,0,0,1)
  35. }
  36. $Form.ShowDialog()
复制代码
1

评分人数

TOP

本帖最后由 小白龙 于 2022-11-25 13:08 编辑

回复 4# went


大佬技术666

我对C#不太懂, 但看起来还是前面的相对好理解一些,
另外, 请教大佬:
自定义的结构体,在新建其对象时, 必须要下面这种 类名+结构名 格式吗必须要+加号? 我改其它的名字都报错

'WinApi+Rect'

TOP

我是按tab自动补全出来的
试了下内部类和结构,在Powershell里都要用 [外部类名+内部类名]来表示
  1. $code=@'
  2.     public static class A{
  3.         public static class A1 {}
  4.     }
  5.     public static class B{
  6.         public struct B1 {}
  7.         public class B2{}
  8.     }
  9.     public class C{
  10.         public class C1{}
  11.     }
  12.     public struct D{}
  13. '@
  14. Add-Type -TypeDefinition $code
  15. #A & A+A1 & B 为静态类不能实例化对象
  16. New-Object 'B+B1'
  17. New-Object 'B+B2'
  18. New-Object 'C'
  19. New-Object 'C+C1'
  20. New-Object 'D'
复制代码

TOP

回复 6# went

非常感谢大佬详细解释,

我一直以为一个类里只能包含方法, 属性, 您上面的代码中, 类里又嵌套了各种类, 还包含了结构, 实在太复杂了,

下面是#2楼的第42行代码, 我把$null改成0也能运行, 我看后面也有两个0 这里用$null有什么含义吗
[WinApi]::SetWindowPos($Form.Handle, $null, $x, $y, 0, 0, 1)

[WinApi]::SetWindowPos($Form.Handle, 0, $x, $y, 0, 0, 1)

TOP

$null即0,只是类型不同,前者为指针,后者为数字,在winapi里面没有区别

TOP

回复 8# went

多谢大佬指教

TOP

返回列表