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

使用SetWindowLong无法移除外部RDP进程的滚动条

问题描述

我正在尝试通过C#代码移除启动的RDP窗口的滚动条。我的代码通过启动mstsc.exe并传入rdp文件路径打开RDP窗口,但打开后需要移除其水平和垂直滚动条。目前的样式设置可成功移除厚边框、最小化和最大化按钮,但WS_HSCROLL和WS_VSCROLL的设置似乎被忽略。

现有代码示例
Process m_proc = new Process { StartInfo = { FileName = "mstsc.exe", Arguments = rdpFullPath } };
m_proc.Start();

// 等待进程启动并创建RDP主窗口
while (m_proc.MainWindowHandle == IntPtr.Zero)
{
    Thread.Sleep(2000);
}

// 移除厚边框以禁止调整窗口大小,并移除最小化和最大化按钮
var currentStyle = UnsafeNativeMethods.GetWindowLong(m_proc.MainWindowHandle, UnsafeNativeMethods.GWL_STYLE);
currentStyle &= ~UnsafeNativeMethods.WS_THICKFRAME;
currentStyle &= ~UnsafeNativeMethods.WS_MINIMIZEBOX;
currentStyle &= ~UnsafeNativeMethods.WS_MAXIMIZEBOX;
currentStyle &= ~UnsafeNativeMethods.WS_HSCROLL;
currentStyle &= ~UnsafeNativeMethods.WS_VSCROLL;
UnsafeNativeMethods.SetWindowLong(m_proc.MainWindowHandle, UnsafeNativeMethods.GWL_STYLE, currentStyle);

UnsafeNativeMethods.SetWindowPos(m_proc.MainWindowHandle,
                                UnsafeNativeMethods.HWND_TOPMOST, 0, 0, 0, 0,
                                UnsafeNativeMethods.SWP_NOMOVE | UnsafeNativeMethods.SWP_NOSIZE | UnsafeNativeMethods.SWP_NOZORDER | UnsafeNativeMethods.SWP_NOOWNERZORDER | UnsafeNativeMethods.SWP_FRAMECHANGED);
相关定义
public const int WS_HSCROLL = 0x00100000;
public const int WS_VSCROLL = 0x00200000;

[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy,
    SetWindowPosFlags uFlags);
解决方法

你修改的是RDP主窗口的样式,但滚动条属于RDP窗口内部的子控件(显示远程桌面内容的容器),而非主窗口本身。需要找到该子控件的句柄,再修改它的窗口样式。

步骤说明

  1. 用FindWindowEx查找RDP主窗口下的子控件,类名通常为MsTscAxHost(不同系统版本可能有差异,可通过Spy++工具确认)。
  2. 对该子控件执行样式修改,移除WS_HSCROLL和WS_VSCROLL。
  3. 调用SetWindowPos刷新控件样式。

修改后的代码

Process m_proc = new Process { StartInfo = { FileName = "mstsc.exe", Arguments = rdpFullPath } };
m_proc.Start();

// 等待主窗口创建,缩短间隔避免不必要延迟
while (m_proc.MainWindowHandle == IntPtr.Zero)
{
    Thread.Sleep(500);
}

// 移除主窗口的边框和最大化/最小化按钮
var mainStyle = UnsafeNativeMethods.GetWindowLong(m_proc.MainWindowHandle, UnsafeNativeMethods.GWL_STYLE);
mainStyle &= ~UnsafeNativeMethods.WS_THICKFRAME;
mainStyle &= ~UnsafeNativeMethods.WS_MINIMIZEBOX;
mainStyle &= ~UnsafeNativeMethods.WS_MAXIMIZEBOX;
UnsafeNativeMethods.SetWindowLong(m_proc.MainWindowHandle, UnsafeNativeMethods.GWL_STYLE, mainStyle);

// 循环查找RDP子控件,确保控件已加载
IntPtr rdpChildHandle = IntPtr.Zero;
for (int i = 0; i < 10; i++)
{
    rdpChildHandle = UnsafeNativeMethods.FindWindowEx(m_proc.MainWindowHandle, IntPtr.Zero, "MsTscAxHost", null);
    if (rdpChildHandle != IntPtr.Zero)
        break;
    Thread.Sleep(500);
}

if (rdpChildHandle != IntPtr.Zero)
{
    // 移除子控件的滚动条样式
    var childStyle = UnsafeNativeMethods.GetWindowLong(rdpChildHandle, UnsafeNativeMethods.GWL_STYLE);
    childStyle &= ~UnsafeNativeMethods.WS_HSCROLL;
    childStyle &= ~UnsafeNativeMethods.WS_VSCROLL;
    UnsafeNativeMethods.SetWindowLong(rdpChildHandle, UnsafeNativeMethods.GWL_STYLE, childStyle);

    // 刷新子控件样式
    UnsafeNativeMethods.SetWindowPos(rdpChildHandle, IntPtr.Zero, 0, 0, 0, 0, 
        UnsafeNativeMethods.SWP_NOMOVE | UnsafeNativeMethods.SWP_NOSIZE | UnsafeNativeMethods.SWP_FRAMECHANGED);
}

// 刷新主窗口样式
UnsafeNativeMethods.SetWindowPos(m_proc.MainWindowHandle,
                                UnsafeNativeMethods.HWND_TOPMOST, 0, 0, 0, 0,
                                UnsafeNativeMethods.SWP_NOMOVE | UnsafeNativeMethods.SWP_NOSIZE | UnsafeNativeMethods.SWP_NOZORDER | UnsafeNativeMethods.SWP_NOOWNERZORDER | UnsafeNativeMethods.SWP_FRAMECHANGED);

补充定义

需要在UnsafeNativeMethods中添加FindWindowEx的定义:

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:35:26