如何通过代码打开窗口的系统菜单

如何通过代码打开窗口的系统菜单

本文介绍了如何通过代码打开窗口的系统菜单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C# WinForms 无边框窗口,为此我覆盖了 WndProc 并处理 WM_NCHITTEST 消息.对于这种形式的区域,我的命中测试函数返回 HTSYSMENU.双击该区域成功关闭窗体,但右键单击它不会显示窗口的系统菜单,也不会在任务栏中右键单击窗口名称时显示.

I have a C# WinForms borderless window, for which I override WndProc and handle the WM_NCHITTEST message. For an area of that form, my hit test function returns HTSYSMENU. Double-clicking that area successfully closes the form, but right-clicking it does not show the window's system menu, nor does it show up when right-clicking the window's name in the taskbar.

此表单使用以下样式:

this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );

并具有这些非默认属性值:

And has these non-default property values:

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;

我尝试过处理 WM_NCRBUTTONDOWN 和 WM_NCRBUTTONUP,并发送 WM_GETSYSMENU 消息,但没有奏效.

I've tried handling WM_NCRBUTTONDOWN and WM_NCRBUTTONUP, and send the WM_GETSYSMENU message, but it didn't work.

推荐答案

如果我没记错的话,一个无边框窗口被标记为不提供系统菜单,并且不会出现在任务栏中.

A borderless window, if I am not mistaken, is flagged such that it offers no system menu, and that it does not appear in the taskbar.

任何给定的窗口没有边框并且不会出现在任务栏中的事实是窗口上设置的样式标志的结果.可以使用 GetWindowLongSetWindowLong API 调用来设置这些特定的样式标志.但是,您必须小心,因为某些样式不能一起使用.

The fact that any given window does not have a border and does not appear in the taskbar is the result of the style flags set on the window. These particular Style flags can be set using the GetWindowLong and SetWindowLong API calls. However you have to be careful as certain styles just don't work together.

这些年来,我编写了许多自定义控件,并且我不断地哄骗窗口变成它们原本不打算成为的东西.
例如,我编写了自己的下拉控件,我需要一个窗口作为弹出窗口而不是激活.
下面的代码将做到这一点.请注意,代码出现在 OnHandleCreated 事件处理程序中.这是因为需要在设置句柄后立即更改标志,这表明 Windows 已经设置了它认为应该设置的标志.

I have written a number of custom controls over the years and I am constantly coaxing windows to become something they weren't originally intended to be.
For example I have written my own dropdown control where I needed a window to behave as a popup and not to activate.
The following code will do that. Note that the code appears in the OnHandleCreated event handler. This is because the flags need to be changed just after the handle is setup which indicates that Windows has already set what it thinks the flags should be.

using System.Runtime.InteropServices;

protected override void OnHandleCreated(EventArgs e) {
    uint dwWindowProperty;

    User32.SetParent(this.Handle, IntPtr.Zero);

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.EXSTYLE );
    dwWindowProperty = dwWindowProperty | (uint)User32.WSEX.TOOLWINDOW | (uint)User32.WSEX.NOACTIVATE;
    User32.SetWindowLong( this.Handle, User32.GWL.EXSTYLE, dwWindowProperty );

    dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.STYLE );
    dwWindowProperty = ( dwWindowProperty & ~(uint)User32.WS.CHILD ) | (uint)User32.WS.POPUP;
    User32.SetWindowLong( this.Handle, User32.GWL.STYLE, dwWindowProperty );
    base.OnHandleCreated (e);
}


//this is a fragment of my User32 library wrapper needed for the previous code segment.
class User32
{
    [DllImport("user32.dll", SetLastError = true)]
   static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public  static extern int SetWindowLong( IntPtr hWnd, User32.GWL gwlIndex, uint dwNewLong);

    [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
    public static extern uint GetWindowLong( IntPtr hWnd, User32.GWL gwlIndex );

    [FlagsAttribute]
    public enum WS: uint {
        POPUP = 0x80000000,
        CHILD = 0x40000000,
    }

    public enum GWL {
        STYLE   = -16,
        EXSTYLE = -20
    }

    [FlagsAttribute]
    public enum WSEX: uint {
        TOP        = 0x0,
        TOPMOST    = 0x8,
        TOOLWINDOW = 0x80,
        NOACTIVATE = 0x08000000,
    }
}

不幸的是,如果不使用 Caption 样式就无法设置 SysMenu 样式,所以我不能说这是否是您的实现中的问题.

Unfortunately the SysMenu style cannot be set without using the Caption style, so I can't say if this is a problem in your implementation.

您可以在这两个链接中查看原始样式列表和扩展样式列表:
窗口样式
CreateWindowEx

You can check out the original style list and the extend style list at these two links:
Window Styles
CreateWindowEx

这篇关于如何通过代码打开窗口的系统菜单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 14:33