如何将嵌入Panel的cmd窗口移出至桌面?
解决方案
要将嵌入Panel的CMD窗口恢复到桌面独立显示,核心是调整窗口的父句柄并恢复其原始窗口样式,以下是具体实现:
修改后的完整代码
Imports System.Runtime.InteropServices Public Class Form1 Private WithEvents proc As New Process Public Const SW_SHOWMAXIMIZED As UInt32 = 3 Public Const SW_RESTORE As Integer = 9 Public Const GWL_STYLE As Integer = -16 Public Const WS_CHILD As Integer = &H40000000 Public Const WS_POPUP As Integer = &H80000000 Public Const WS_VISIBLE As Integer = &H10000000 Private Declare Function GetParent Lib "user32" (ByVal hwnd As Int32) As Int32 Private Declare Function DwmGetWindowAttribute Lib "dwmapi" (ByVal hwnd As IntPtr, ByVal dwAttribute As Integer, ByRef pvAttribute As RECT, ByVal cbAttribute As Integer) As Integer Private Declare Function SetParent Lib "user32" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Boolean Private Declare Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrW" (ByVal hWnd As IntPtr, ByVal nIndex As Integer) As IntPtr Private Declare Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrW" (ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As IntPtr) As IntPtr Public Structure RECT Public left, top, right, bottom As Integer End Structure Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load proc.EnableRaisingEvents = True proc.StartInfo.FileName = "cmd" proc.Start() End Sub Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Shown proc.WaitForExit(200) If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then SetWindowPos(proc.MainWindowHandle, IntPtr.Zero, 0, 0, Panel1.Width, Panel1.Height, 0) ShowWindow(proc.MainWindowHandle, SW_SHOWMAXIMIZED) End If End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click If proc IsNot Nothing AndAlso Not proc.HasExited Then ' 将CMD窗口的父窗口切换为桌面(IntPtr.Zero代表桌面窗口) SetParent(proc.MainWindowHandle, IntPtr.Zero) ' 恢复窗口样式:移除子窗口属性,添加弹出式窗口属性 Dim windowStyle As IntPtr = GetWindowLongPtr(proc.MainWindowHandle, GWL_STYLE) windowStyle = windowStyle And Not WS_CHILD windowStyle = windowStyle Or WS_POPUP Or WS_VISIBLE SetWindowLongPtr(proc.MainWindowHandle, GWL_STYLE, windowStyle) ' 恢复窗口到正常显示状态,并设置初始位置和尺寸 ShowWindow(proc.MainWindowHandle, SW_RESTORE) SetWindowPos(proc.MainWindowHandle, IntPtr.Zero, 100, 100, 800, 600, 0) End If End Sub End Class
关键逻辑说明
- 切换父窗口:
SetParent(proc.MainWindowHandle, IntPtr.Zero)是核心操作,直接将CMD窗口从Panel的子窗口转为桌面的直接子窗口。 - 恢复窗口样式:嵌入Panel时CMD窗口会被标记为
WS_CHILD(子窗口)样式,移出时必须移除该属性并添加WS_POPUP(弹出式窗口)属性,才能让窗口重新显示标题栏和边框。 - 重置显示状态:通过
ShowWindow(SW_RESTORE)恢复窗口的正常显示状态,再用SetWindowPos设置合适的初始位置和大小,确保窗口在桌面正常展示。
内容的提问来源于stack exchange,提问作者Eric van Loon
相关产品推荐
相关产品推荐

