【问题标题】:Removing the Title bar of external application using c#使用c#删除外部应用程序的标题栏
【发布时间】:2010-05-13 09:07:54
【问题描述】:

我的应用程序启动了另一个外部应用程序。

我想在这个外部应用程序启动后删除它的标题栏。

这是否可行,如果可行,该怎么做?

基于我正在使用下面的工作代码的 cmets

//Finds a window by class name
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

//Sets a window to be a child window of another window
[DllImport("USER32.DLL")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

//Sets window attributes
[DllImport("USER32.DLL")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

//Gets window attributes
[DllImport("USER32.DLL")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);


//assorted constants needed
public static int GWL_STYLE = -16;
public static int WS_CHILD = 0x40000000; //child window
public static int WS_BORDER = 0x00800000; //window with border
public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar

public void WindowsReStyle()
{
    Process[] Procs = Process.GetProcesses();
    foreach (Process proc in Procs)
    {
        if (proc.ProcessName.StartsWith("notepad"))
        {
            IntPtr pFoundWindow = proc.MainWindowHandle;
            int style = GetWindowLong(pFoundWindow, GWL_STYLE);
            SetWindowLong(pFoundWindow, GWL_STYLE, (style & ~WS_CAPTION));
        }
    }
}

【问题讨论】:

标签: c# winforms process pinvoke


【解决方案1】:

无需注入任何东西,您可以像使用 API 一样修改 windows 样式位,例如这适用于记事本,但 YMMV 取决于您正在玩的应用程序。

//Get current style
lCurStyle = GetWindowLong(hwnd, GWL_STYLE)

//remove titlebar elements
lCurStyle = lCurStyle And Not WS_CAPTION
lCurStyle = lCurStyle And Not WS_SYSMENU
lCurStyle = lCurStyle And Not WS_THICKFRAME
lCurStyle = lCurStyle And Not WS_MINIMIZE
lCurStyle = lCurStyle And Not WS_MAXIMIZEBOX

//apply new style
SetWindowLong hwnd, GWL_STYLE, lCurStyle

//reapply a 3d border
lCurStyle = GetWindowLong(hwnd, GWL_EXSTYLE)

SetWindowLong hwnd, GWL_EXSTYLE, lCurStyle Or WS_EX_DLGMODALFRAME

//redraw
SetWindowPos hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_FRAMECHANGED

【讨论】:

【解决方案2】:
Process[] processes = Process.GetProcessesByName("notepad");
IntPtr windowHandle = processes[0].MainWindowHandle;

const int GWL_STYLE = (-16); 
const UInt32 WS_VISIBLE = 0x10000000;
SetWindowLong(windowHandle, GWL_STYLE, (WS_VISIBLE));`

【讨论】:

    【解决方案3】:

    好吧,Alex 从来没有详细说明过代码,至少它不是一个即插即用的解决方案,但这仍然是他的主要功劳……除非你使用“SetParent”,否则它有点问题" 把它放在某种容器中(例如表单或面板)只是想我会分享结果。

    Visual Basic:

    Option Strict On
    Public Class Form1
        Const WS_BORDER As Integer = 8388608
        Const WS_DLGFRAME As Integer = 4194304
        Const WS_CAPTION As Integer = WS_BORDER Or WS_DLGFRAME
        Const WS_SYSMENU As Integer = 524288
        Const WS_THICKFRAME As Integer = 262144
        Const WS_MINIMIZE As Integer = 536870912
        Const WS_MAXIMIZEBOX As Integer = 65536
        Const GWL_STYLE As Integer = -16&
        Const GWL_EXSTYLE As Integer = -20&
        Const WS_EX_DLGMODALFRAME As Integer = &H1L
        Const SWP_NOMOVE As Integer = &H2
        Const SWP_NOSIZE As Integer = &H1
        Const SWP_FRAMECHANGED As Integer = &H20
        Const MF_BYPOSITION As UInteger = &H400
        Const MF_REMOVE As UInteger = &H1000
        Declare Auto Function GetWindowLong Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
        Declare Auto Function SetWindowLong Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        Declare Auto Function SetWindowPos Lib "user32.dll" (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 Integer) As Boolean
        Public Sub MakeExternalWindowBorderless(ByVal MainWindowHandle As IntPtr)
            Dim Style As Integer
            Style = GetWindowLong(MainWindowHandle, GWL_STYLE)
            Style = Style And Not WS_CAPTION
            Style = Style And Not WS_SYSMENU
            Style = Style And Not WS_THICKFRAME
            Style = Style And Not WS_MINIMIZE
            Style = Style And Not WS_MAXIMIZEBOX
            SetWindowLong(MainWindowHandle, GWL_STYLE, Style)
            Style = GetWindowLong(MainWindowHandle, GWL_EXSTYLE)
            SetWindowLong(MainWindowHandle, GWL_EXSTYLE, Style Or WS_EX_DLGMODALFRAME)
            SetWindowPos(MainWindowHandle, New IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_FRAMECHANGED)
        End Sub
    End Class
    

    C Sharp(C#)

    using System.Runtime.InteropServices;
    public class Form1
    {
        const int WS_BORDER = 8388608;
        const int WS_DLGFRAME = 4194304;
        const int WS_CAPTION = WS_BORDER | WS_DLGFRAME;
        const int WS_SYSMENU = 524288;
        const int WS_THICKFRAME = 262144;
        const int WS_MINIMIZE = 536870912;
        const int WS_MAXIMIZEBOX = 65536;
        const int GWL_STYLE = -16L;
        const int GWL_EXSTYLE = -20L;
        const int WS_EX_DLGMODALFRAME = 0x1L;
        const int SWP_NOMOVE = 0x2;
        const int SWP_NOSIZE = 0x1;
        const int SWP_FRAMECHANGED = 0x20;
        const uint MF_BYPOSITION = 0x400;
        const uint MF_REMOVE = 0x1000;
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
        public void MakeExternalWindowBorderless(IntPtr MainWindowHandle)
        {
            int Style = 0;
            Style = GetWindowLong(MainWindowHandle, GWL_STYLE);
            Style = Style & ~WS_CAPTION;
            Style = Style & ~WS_SYSMENU;
            Style = Style & ~WS_THICKFRAME;
            Style = Style & ~WS_MINIMIZE;
            Style = Style & ~WS_MAXIMIZEBOX;
            SetWindowLong(MainWindowHandle, GWL_STYLE, Style);
            Style = GetWindowLong(MainWindowHandle, GWL_EXSTYLE);
            SetWindowLong(MainWindowHandle, GWL_EXSTYLE, Style | WS_EX_DLGMODALFRAME);
            SetWindowPos(MainWindowHandle, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
        }
    }
    

    再次感谢亚历克斯

    【讨论】:

    • 您好,感谢您的代码,在纠正了 C# 部分中的一些错误后,它对我有用。样式 & !WS_CAPTION 不起作用。你需要写 Style & ~WS_CAPTION。
    【解决方案4】:

    这与之前提出的问题非常相似,我很确定答案是您做不到。 (或者,如果可以,您需要深入研究 Windows API,这可能具有挑战性,具体取决于您的经验。)

    How to add button to other apps window title bar (XP/Vista)

    【讨论】:

    • 这是不正确的。你可以做到,这里列出的解决方案确实有效。
    【解决方案5】:

    如果是 Syncfusion,则不会。如果没有,是的。

    VB:

    Const WS_BORDER As Integer = 8388608
    Const WS_DLGFRAME As Integer = 4194304
    Const WS_CAPTION As Integer = WS_BORDER Or WS_DLGFRAME
    Const WS_SYSMENU As Integer = 524288
    Const WS_THICKFRAME As Integer = 262144
    Const WS_MINIMIZE As Integer = 536870912
    Const WS_MAXIMIZEBOX As Integer = 65536
    Const GWL_STYLE As Integer = -16&
    Const GWL_EXSTYLE As Integer = -20&
    Const WS_EX_DLGMODALFRAME As Integer = &H1L
    Const SWP_NOMOVE As Integer = &H2
    Const SWP_NOSIZE As Integer = &H1
    Const SWP_FRAMECHANGED As Integer = &H20
    Const MF_BYPOSITION As UInteger = &H400
    Const MF_REMOVE As UInteger = &H1000
    Declare Auto Function GetWindowLong Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
    Declare Auto Function SetWindowLong Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
    Declare Auto Function SetWindowPos Lib "user32.dll" (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 Integer) As Boolean
    Public Sub MakeExternalWindowBorderless(ByVal MainWindowHandle As IntPtr)
        Dim Style As Integer
        Style = GetWindowLong(MainWindowHandle, GWL_STYLE)
        Style = Style And Not WS_CAPTION
        Style = Style And Not WS_SYSMENU
        Style = Style And Not WS_THICKFRAME
        Style = Style And Not WS_MINIMIZE
        Style = Style And Not WS_MAXIMIZEBOX
        SetWindowLong(MainWindowHandle, GWL_STYLE, Style)
        Style = GetWindowLong(MainWindowHandle, GWL_EXSTYLE)
        SetWindowLong(MainWindowHandle, GWL_EXSTYLE, Style Or WS_EX_DLGMODALFRAME)
        SetWindowPos(MainWindowHandle, New IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_FRAMECHANGED)
    End Sub
    

    C#:

    const int WS_BORDER = 8388608;
    const int WS_DLGFRAME = 4194304;
    const int WS_CAPTION = WS_BORDER | WS_DLGFRAME;
    const int WS_SYSMENU = 524288;
    const int WS_THICKFRAME = 262144;
    const int WS_MINIMIZE = 536870912;
    const int WS_MAXIMIZEBOX = 65536;
    const int GWL_STYLE = -16L;
    const int GWL_EXSTYLE = -20L;
    const int WS_EX_DLGMODALFRAME = 0x1L;
    const int SWP_NOMOVE = 0x2;
    const int SWP_NOSIZE = 0x1;
    const int SWP_FRAMECHANGED = 0x20;
    const uint MF_BYPOSITION = 0x400;
    const uint MF_REMOVE = 0x1000;
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
    public void MakeExternalWindowBorderless(IntPtr MainWindowHandle)
    {
        int Style = 0;
        Style = GetWindowLong(MainWindowHandle, GWL_STYLE);
        Style = Style & ~WS_CAPTION;
        Style = Style & ~WS_SYSMENU;
        Style = Style & ~WS_THICKFRAME;
        Style = Style & ~WS_MINIMIZE;
        Style = Style & ~WS_MAXIMIZEBOX;
        SetWindowLong(MainWindowHandle, GWL_STYLE, Style);
        Style = GetWindowLong(MainWindowHandle, GWL_EXSTYLE);
        SetWindowLong(MainWindowHandle, GWL_EXSTYLE, Style | WS_EX_DLGMODALFRAME);
        SetWindowPos(MainWindowHandle, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    }
    

    【讨论】:

      【解决方案6】:

      如果其他人需要,Alex 的 Python 版本的答案:

      import win32gui
      
      #  get a handle to the window
      windowHandle = win32gui.FindWindowEx(None, None, None, "Untitled - Notepad")
      
      GWL_STYLE = -16  #  see https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga
      
      #  get current window style
      currentStyle = win32gui.GetWindowLong(windowHandle, GWL_STYLE)
      
      #  remove titlebar elements
      currentStyle = currentStyle & ~(0x00C00000)  #  WS_CAPTION
      currentStyle = currentStyle & ~(0x00080000)  #  WS_SYSMENU
      currentStyle = currentStyle & ~(0x00040000)  #  WS_THICKFRAME
      currentStyle = currentStyle & ~(0x20000000)  #  WS_MINIMIZE
      currentStyle = currentStyle & ~(0x00010000)  #  WS_MAXIMIZEBOX
      
      #  apply new style
      win32gui.SetWindowLong(windowHandle, GWL_STYLE, currentStyle)
      

      【讨论】:

        【解决方案7】:

        一般来说,除非您正在启动的应用程序直接支持 in(例如,如果它需要命令行开关来删除标题栏),否则您不能这样做。

        您只能控制ProcessStartInfo 类中已经存在的内容(即打开一个新窗口、开始最小化/最大化等...)。

        【讨论】:

        • 有没有其他方法可以隐藏这个第三方应用的标题栏?它只有一个表单,我需要删除它。
        • @karthik - 仅当它已经支持此功能时。这不是可以直接控制的。
        • 嘿,您确实可以控制它。 Win32 用户 API (user32) 已打开,您可以使用它控制 任何 窗口。
        猜你喜欢
        • 1970-01-01
        • 2015-01-16
        • 1970-01-01
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-25
        • 1970-01-01
        相关资源
        最近更新 更多