我想在C#中删除另一个进程的窗口边框;我使用RemoveMenu删除边框。它几乎可以工作,但是我还有两个问题:

  • 我需要删除两次边框,第一次菜单栏仍然
    存在。
  • 我无法还原菜单的

  • 这是我已经写的:
    public void RemoveBorders(IntPtr WindowHandle, bool Remove)
        {
            IntPtr MenuHandle = GetMenu(WindowHandle);
    
            if (Remove)
            {
                int count = GetMenuItemCount(MenuHandle);
                for (int i = 0; i < count; i++)
                    RemoveMenu(MenuHandle, 0, (0x40 | 0x10));
            }
            else
            {
                SetMenu(WindowHandle,MenuHandle);
            }
    
            int WindowStyle = GetWindowLong(WindowHandle, -16);
    
            //Redraw
            DrawMenuBar(WindowHandle);
            SetWindowLong(WindowHandle, -16, (WindowStyle & ~0x00080000));
            SetWindowLong(WindowHandle, -16, (WindowStyle & ~0x00800000 | 0x00400000));
        }
    

    有人可以告诉我我做错了什么吗?我已经尝试保存MenuHandle并在以后还原它,但这不起作用。

    最佳答案



    这是因为您的MenuHandle是本地变量。

    当对方法RemoveBorders的首次调用结束时,垃圾收集器将删除MenuHandle和可用内存。

    您调用RemoveBorders的第二次时间,将MenuHandle重新创建为新的本地变量,并重新分配给窗口菜单的当前状态-没有菜单项的菜单。

    因此:

    MenuHandle不会保存窗口菜单的先前状态,这说明了为什么无法还原窗口菜单。

    我的建议是使MenuHandle的全局变量,并在RemoveBorders方法定义之外进行定义。

    您可以将其定义为私有(private), protected 或公共(public)字段,也可以为其定义另一个属性,但这是可选的,并且而不是是必需的。如果此属性更适合您,则也可以将其定义为静态。

    以下是MenuHandle定义的一些示例:

    private IntPtr MenuHandle;
    //or
    IntPtr MenuHandle; //Defined outside of RemoveBorders, which is defined below this line, to show that MenuHandle is not local variable.
    public void RemoveBorders(IntPtr WindowHandle, bool Remove)
    //or
    protected IntPtr MenuHandle;
    //or
    public IntPtr MenuHandle
    //or
    private static IntPtr MenuHandle
    //or
    static IntPtr MenuHandle
    //etc...
    

    您必须移动这行:
    IntPtr MenuHandle = GetMenu(WindowHandle);
    

    里面:
    if (Remove)
    

    并且在调用GetMenuItemCount函数之前。

    您还必须修改该行,并至少删除IntPtr,以声明MenuHandle是而不是 本地变量,并引用MenuHandle 字段,该字段是在RemoveBorders方法之外定义的。
    IntelliSense仍会将其识别为字段,并且不会提醒您未定义的错误。

    如果MenuHandle是而不是 静态,则还可以添加this。在删除MenuHandle之前的IntPtr之后的关键字(换句话说,您可以将IntPtr替换为this.),以记住MenuHandle不再是
    本地变量,而不是
    ,因此Garbage Collector 将不再ojit_rorder删除它工作。

    当您启动程序时,MenuHandle将被分配给IntPtr.Zero作为默认值。当您在的第一个时间内调用RemoveBorders时,MenuHandle的值将设置为if (Remove)中GetMenu函数的返回值。

    当RemoveBorders在的第一个时间内完成时,不会删除MenuHandle,并且会在删除所有菜单项之前保存窗口菜单的先前状态。

    因此,当您为了恢复菜单而在的第二个时间内调用RemoveBorders时,执行程序将到达if (Remove)代码并立即跳转到else代码,因为remove = false,然后在其中调用SetMenu函数,当您将首次对RemoveBorders进行调用以来,窗口菜单的先前状态。
    这样,您将最终能够恢复窗口的菜单。

    我仍然不知道为什么您需要在第一次出现菜单栏时就删除边框两次。
    我也想帮助您解决这个问题,但是不知道。
    在这种情况下,您的代码是正确的。抱歉,但我希望其他人可以为您解决此问题,并也为您提供解决方案。

    关于c# - 删除和还原窗口边框,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10337680/

    10-11 22:59