Winforms 如何打开窗口';按代码显示系统菜单?
我有一个C#WinForms无边界窗口,我覆盖WndProc并处理WM#NCHITTEST消息。对于这种形式的区域,我的hit test函数返回HTSYSMENU。双击该区域可成功关闭窗体,但右键单击该区域不会显示窗口的系统菜单,右键单击任务栏中的窗口名称时也不会显示 此表单使用以下样式:Winforms 如何打开窗口';按代码显示系统菜单?,winforms,winapi,Winforms,Winapi,我有一个C#WinForms无边界窗口,我覆盖WndProc并处理WM#NCHITTEST消息。对于这种形式的区域,我的hit test函数返回HTSYSMENU。双击该区域可成功关闭窗体,但右键单击该区域不会显示窗口的系统菜单,右键单击任务栏中的窗口名称时也不会显示 此表单使用以下样式: this.SetStyle( ControlStyles.AllPaintingInWmPaint, true ); this.SetStyle( ControlStyles.UserPaint, true
this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );
并具有以下非默认属性值:
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;
我尝试过处理WM\u NCRBUTTONDOWN和WM\u NCRBUTTONUP,并发送WM\u GETSYSMENU消息,但它不起作用。我的应用程序中有相同的属性,右键单击也不起作用,所以这不是您的问题,这似乎是windows窗体在没有边框时的响应方式 如果将边框设置为正常值,则可以右键单击任务栏等
要右键单击其他控件,需要设置ContextMenuStrip并提供“菜单”。但我不确定如果你没有边界的话这是否有效。我一直无法使它工作。如果我没有弄错的话,一个无边框的窗口会被标记为不提供系统菜单,并且不会出现在任务栏中 任何给定的窗口都没有边框,并且不会出现在任务栏中,这是在窗口上设置的样式标志的结果。可以使用
GetWindowLong
和SetWindowLong
API调用来设置这些特定的样式标志。但是,你必须小心,因为某些样式不能一起工作
这些年来,我编写了许多自定义控件,我一直在哄骗windows,使其成为它们原本不打算成为的东西。例如,我编写了自己的下拉控件,其中需要一个窗口作为弹出窗口,而不是激活窗口。
下面的代码将实现这一点。请注意,代码出现在
OnHandleCreated
事件处理程序中。这是因为标志需要在句柄设置后立即更改,这表明Windows已经设置了它认为标志应该是什么
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,
}
}
不幸的是,如果不使用标题
样式,就无法设置系统菜单
样式,因此我无法确定这是否是实现中的问题
您可以通过以下两个链接查看原始样式列表和扩展样式列表:这会检测到右键单击应用程序任务栏的“区域”
也许会有帮助?谢谢,但我不想伪造系统菜单,我想首先找到一个关于缺少系统菜单(恢复、移动、大小、最小化、最大化、关闭)的答案。“WS\u SYSMENU:创建一个在标题栏上有窗口菜单的窗口。WS\u标题样式也必须指定。”是的,就是这样。这是一种无边界、无标题的形式。
protected override void WndProc( ref System.Windows.Forms.Message m )
{ // RightClickMenu
if ( m.Msg == 0x313 )
{
this.contextMenuStrip1.Show(this, this.PointToClient(new Point(m.LParam.ToInt32())));
}}