4 Stimmen

Wie kann ich das Systemmenü eines Fensters per Code öffnen?

Ich habe ein C# WinForms fenster ohne Rahmen, für das ich WndProc überschreibe und die WM_NCHITTEST-Nachricht behandele. Für einen Bereich dieses Formulars gibt meine Hit-Test-Funktion HTSYSMENU zurück. Ein Doppelklick in diesem Bereich schließt das Formular erfolgreich, aber ein Rechtsklick zeigt nicht das Systemmenü des Fensters an, noch erscheint es, wenn man auf den Namen des Fensters in der Taskleiste klickt.

Dieses Formular verwendet diese Stile:

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

Und hat diese nicht-standardmäßigen Eigenschaftswerte:

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

Ich habe versucht, WM_NCRBUTTONDOWN und WM_NCRBUTTONUP zu behandeln und die WM_GETSYSMENU-Nachricht zu senden, aber es hat nicht funktioniert.

5voto

Bill Punkte 1748

Ein rahmenloses Fenster, wenn ich mich nicht irre, ist so gekennzeichnet, dass es kein Systemmenü anbietet und dass es nicht in der Taskleiste erscheint.

Die Tatsache, dass ein bestimmtes Fenster keinen Rahmen hat und nicht in der Taskleiste angezeigt wird, ist das Ergebnis der auf dem Fenster gesetzten Style-Flags. Diese speziellen Style-Flags können mit den API-Aufrufen GetWindowLong und SetWindowLong gesetzt werden. Allerdings muss man vorsichtig sein, da bestimmte Styles einfach nicht zusammenarbeiten.

Im Laufe der Jahre habe ich eine Reihe von benutzerdefinierten Steuerelementen geschrieben und bin ständig darum bemüht, dass Fenster zu etwas werden, für das sie ursprünglich nicht gedacht waren.
Zum Beispiel habe ich mein eigenes Dropdown-Steuerelement geschrieben, bei dem ich ein Fenster benötigt habe, das sich wie ein Popup verhält und nicht aktiviert wird.
Der folgende Code wird das tun. Beachten Sie, dass der Code im Ereignishandler OnHandleCreated erscheint. Dies liegt daran, dass die Flags unmittelbar nach dem Einrichten des Griffs geändert werden müssen, was anzeigt, dass Windows bereits festgelegt hat, was es für die Flags halten sollte.

using System.Runtime.InteropServices;

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

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

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

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

// Dies ist ein Fragment meines User32-Bibliothek-Wrappers, der für das vorherige Code-Segment benötigt wird.
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,
    }
}

Leider kann der SysMenu-Stil nicht ohne Verwendung des Caption-Stils gesetzt werden, daher kann ich nicht sagen, ob dies ein Problem in Ihrer Implementierung ist.

Sie können die ursprüngliche Stil-Liste und die erweiterte Stil-Liste unter diesen beiden Links überprüfen:
Fensterstile
CreateWindowEx

1 Stimmen

"WS_SYSMENU erstellt ein Fenster, das ein Fenstermenü in der Titelleiste hat. Der WS_CAPTION-Stil muss ebenfalls angegeben werden." Ja, das ist es. Es handelt sich um ein formloses und beschriftungsloses Formular.

0voto

Martin Marconcini Punkte 25006

Ich habe die gleichen Eigenschaften in meiner Anwendung und Rechtsklick funktioniert auch nicht, also ist das nicht dein Problem, es scheint die Art und Weise zu sein, wie Windows-Formulare reagieren, wenn sie keinen Rand haben.

Wenn du deinen Rand auf den normalen Wert setzt, wirst du in der Taskleiste und so weiter Rechtsklick haben.

Für Rechtsklick auf andere Steuerelemente musst du das ContextMenuStrip einstellen und dein "Menü" bereitstellen. Aber ich bin mir nicht sicher, ob das funktioniert, wenn du es ohne Rand hast. Ich konnte es nicht zum Laufen bringen.

0voto

    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())));
        }}

Dies erkennt Rechtsklick im "Bereich" der Anwendungstaskleiste..

vielleicht hilft es ?

0 Stimmen

Danke, aber ich möchte das Systemmenü nicht fälschen, ich suchte ursprünglich nach einer Antwort auf das Fehlen eines Systemmenüs (Wiederherstellen, Verschieben, Größe ändern, Minimieren, Maximieren, Schließen).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X