Ich habe gesehen, dass einige Anwendungen (vielleicht nicht .NET-Anwendungen) eine zusätzliche Schaltfläche auf der linken Seite von der Minimieren-Schaltfläche in der Titelleiste des Formulars haben? Wie kann ich dies in C# erreichen?Wie fügt man der Titelleiste des Fensters eine zusätzliche Schaltfläche hinzu?
Antwort
UPDATE: eine Lösung hinzugefügt, die mit Aero aktiviert für Windows Vista und Windows 7
Nicht-Aero-Lösung
Der Nicht-Client-Bereich eines Fensters Interaktion arbeiten wird von einer Reihe von nicht kundenspezifischen Nachrichten verwaltet. Zum Beispiel wird eine WM_NCPAINT-Nachricht an die Fensterprozedur gesendet, um den Nicht-Client-Bereich zu zeichnen.
Ich habe das nie von .NET gemacht, aber ich vermute, Sie können die WndProc überlagern und die WM_NC * Nachrichten behandeln, um zu erreichen, was Sie wollen.
Update: Da ich das nie aus .NET versucht habe, habe ich ein paar Minuten und dachte, ich würde es versuchen.
Probieren Sie dies auf Windows 7, ich fand, dass ich die Designs für das Fenster deaktivieren musste, wenn ich OS das Basis-Rendering des Nicht-Client-Bereichs durchführen wollte. Also hier ist ein kurzer Test. Ich habe GetWindowDC verwendet, um den DC des gesamten Fensters anstelle von GetDCEx zu erhalten, das war nur, weil ich das aus dem Speicher interopieren konnte und nicht alle Flag-Konstanten für GetDcEx nachgeschlagen hatte. Und natürlich könnte der Code mit mehr Fehlerprüfung auskommen.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class CustomBorderForm : Form
{
const int WM_NCPAINT = 0x85;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("user32.dll", SetLastError = true)]
public static extern void DisableProcessWindowsGhosting();
[DllImport("UxTheme.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);
public CustomBorderForm()
{
// This could be called from main.
DisableProcessWindowsGhosting();
InitializeComponent();
}
protected override void OnHandleCreated(EventArgs e)
{
SetWindowTheme(this.Handle, "", "");
base.OnHandleCreated(e);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_NCPAINT:
{
IntPtr hdc = GetWindowDC(m.HWnd);
using (Graphics g = Graphics.FromHdc(hdc))
{
g.FillEllipse(Brushes.Red, new Rectangle((Width-20)/2, 8, 20, 20));
}
int r = ReleaseDC(m.HWnd, hdc);
}
break;
}
}
}
}
Btw. Ich rief DisableProcessWindowsGhosting
an, dies wird das OS davon abhalten, den Nicht-Client-Bereich zu zeichnen, wenn die Anwendung zu lange braucht, um auf Windows-Nachrichten zu antworten. Wenn Sie dies nicht tun, wird der Rahmen in einigen Situationen neu gerendert, aber Ihre Verzierungen werden nicht angezeigt. Es hängt also von Ihren Anforderungen ab, ob es für Sie richtig ist oder nicht.
Aero Lösung unterstützt
durch den Kommentar Angeregt von @TheCodeKing, ich dachte, ich würde in diesem anderen Blick nehmen. Es stellt sich heraus, dass dies in vollständig dokumentierter Weise durchgeführt werden kann, während Aero unterstützt wird. Aber es ist nichts für schwache Nerven. Ich werde hier keine komplette Lösung anbieten, es gibt immer noch einige Knicke zum Training, aber es macht die Grundlagen.
Dieser Code/Lösung wird das Win32-Beispiel basiert weg, die an der folgenden Position gefunden werden kann http://msdn.microsoft.com/en-us/library/bb688195(VS.85).aspx
Grundsätzlich, was Sie tun müssen, ist die folgende.
Die obigen Schritte geben Ihnen ein Fenster mit dem Standardglasrahmen, das Systemmenü (Fenstersymbol) und den Titel ausgenommen.Die Schaltflächen zum Minimieren, Maximieren und Schließen werden weiterhin gezeichnet und funktionieren. Was Sie nicht tun können, ist das Fenster zu ziehen oder seine Größe zu ändern, weil der Frame nicht wirklich da ist. Denken Sie daran, dass der Clientbereich das gesamte Fenster abdeckt. Wir haben das Betriebssystem gebeten, den Frame auf den Clientbereich zu zeichnen.
Jetzt können Sie wie gewohnt auf das Fenster zeichnen, sogar auf den Rahmen. Sie können sogar Steuerelemente im Beschriftungsbereich platzieren.
Der letzte Schritt besteht darin, die WM_NCHITTEST Nachricht zu behandeln, wo Sie die Position des Mauszeigers überprüfen und einen Indikator zurückgeben, der Windows mitteilt, welcher Bereich des Fensters die Maus über ist. Wenn Sie beispielsweise HT_CAPTION zurückgeben, verhält sich das Fenster so, als befände sich die Maus über der Beschriftung und Sie können das Fenster usw. ziehen. Diese Funktion erfordert eine vollständige Implementierung, um ein voll funktionsfähiges Fenster mit einem benutzerdefinierten Rahmen zu erhalten .
Diese Technik funktioniert leider nicht mit Aero-Glas. Ich würde mich dafür interessieren, wenn jemand den Voodoo kennt, der benötigt wird, um an Glas zu arbeiten. Bisher habe ich keine Arbeitsbeispiele gefunden. – TheCodeKing
@TheCodeKing, Ich habe die Antwort aktualisiert, um Ihre Frage zu decken. Ich habe das auch in .NET prototypisiert, nur um zu bestätigen, dass es zum Funktionieren gebracht werden kann. Hier ist der MSDN Artikel, auf den ich verwiesen habe http://msdn.microsoft.com/en-us/library/bb688195(VS.85).aspx –
Eigentlich erinnert mich das, ich weiß, wie man das macht, ich habe irgendwo Code Es hat im Design-Modus einfach nicht dargestellt, wie es zur Laufzeit aussah.Haben Sie ein C# -Beispiel für die Technik, die Sie beschrieben haben, die ich am meisten ausprobiert habe und die nicht funktioniert? – TheCodeKing
Ich denke, ein Weg, dies zu tun wäre, WM_NCPAINT Nachricht (Nicht-Client-Farbe) zu behandeln, um die Schaltfläche zu zeichnen und nicht-Client-Mausklicks zu wissen, dass jemand auf die Schaltfläche geklickt hat.
Einfache Lösung:
Schritt 1: Erstellen Sie ein Windows Form (dies wird Ihre eigenen Titel bar)
-Set Form Border Style to None
-Add whatever controls you would like to this
-I will name this custom form "TitleBarButtons"
Schritt 2. In der von Ihnen, diese benutzerdefinierten Steuerelement in Add verwenden möchten
titleBarBtn = new TitleBarButtons();
titleBarBtn.Location = new Point(this.Location.X + 100, this.Location.Y+5);
titleBarBtn.Show();
titleBarBtn.Owner = this;
Um Ihren Konstruktor ... Sie können Chaos mit den Offsets in einer schönen Lage passen diese nur für meine App
Schritt 3. den Umzug Veranstaltung zu Ihrem Hauptformular hinzufügen
private void Form14_Move(object sender, EventArgs e)
{
titleBarBtn.Location = new Point(this.Location.X + 100, this.Location.Y+5);
}
Bitte lassen Sie mich wissen, wenn Sie eine bessere Erklärung für eine der oben genannten Code möchten.
Was ist ein TitleBarButtons? Ich kann keine Referenzen dieser Klasse finden. – Borik
Es tut mir leid ich merkte, ich war nicht klar, ich glaube „TitleBarButtons“ war das benutzerdefinierte Formular im ersten Schritt gemacht. Ich überarbeite meine Antwort, um sie klarer zu machen. – hrh
@hrh ziemlich alter thread obwohl es in wpf auch möglich ist, form zu wpf window hinzuzufügen – murmansk
- 1. Schaltflächen in der Titelleiste des Fensters
- 2. Wie fügt man der MKPointAnnotation eine Schaltfläche hinzu?
- 3. Wie fügt man eine DependencyProperty zu einer Schaltfläche hinzu?
- 4. Wie fügt man dem Windows Explorer eine neue Schaltfläche hinzu?
- 5. Wie fügt man UITextField eine klare Schaltfläche hinzu?
- 6. Pandoc fügt zusätzliche Absätze hinzu
- 7. Höhe der Titelleiste eines Fensters erkennen
- 8. SimGrid. Wie fügt man dem Masterworker-Modell zusätzliche Parameter hinzu?
- 9. Wie ein Menü oben auf die Titelleiste des Fensters zeigen
- 10. Wie fügt man die schwebende Schaltfläche in PDF hinzu?
- 11. Steuerelement, das das Ziehen der Titelleiste des Fensters simuliert
- 12. Schließen Schaltfläche in der Titelleiste in MFC
- 13. Wie fügt man die schwebende Schaltfläche über dem UITableView hinzu?
- 14. Firefox fügt zusätzliche Breite mit Polsterung hinzu
- 15. WPF DataGrid fügt zusätzliche "Geister" -Zeile hinzu
- 16. Wie man eine "innerhalb des Fensters" transparente/verschwommene Titelleiste mit einer benutzerdefinierten Basisfarbe in Yosemite macht?
- 17. Wie fügt man der Benachrichtigung Sound hinzu?
- 18. Python csv Writer fügt zusätzliche Anführungszeichen hinzu
- 19. Warum fügt dieses INSERT eine zusätzliche leere Zeile hinzu?
- 20. Fügt NSNumber der Zahl, die es enthält, zusätzliche Bytes hinzu?
- 21. Wie fügt man Brotkrume hinzu?
- 22. Wie fügt man der Ruby-Variable eine Eigenschaft hinzu?
- 23. C++ mein Zähler fügt eine zusätzliche Zählung hinzu
- 24. Wie fügt man eine Schaltfläche in der nativen Umgebung ein?
- 25. jQuery Slider - Wie fügt man Navigationsschaltflächen hinzu?
- 26. Wie fügt man eine 'order by'-Schaltfläche hinzu, wenn man mit MVC-Struktur auf PHP arbeitet?
- 27. Wie fügt man dem Layout der Materialschublade Untertitel hinzu?
- 28. Java, console.readPassword fügt zusätzliche Zeile hinzu. Wie lösche ich es?
- 29. Wie fügt man Imageview zum Fragment hinzu?
- 30. Wie fügt man einer Systemmethode eine Schließung hinzu?
Beachten Sie, dass Sie dies nicht tun sollten: http://msdn.microsoft.com/en-us/library/aa974173(v=MSDN.10).aspx - »Fügen Sie keine Steuerelemente zu einem Fensterrahmen hinzu. Setze stattdessen die Steuerelemente in das Fenster. « – Joey
@Johannes, ich gebe zu, manchmal Apps, die das tun, können nervig sein, aber einige Apps machen das sehr gut. Wie Ultramon, das eine Schaltfläche zum Austauschen von Monitoren auf den Rahmen setzt, die in Windows 7 sehr nativ aussieht. Es gibt also Anwendungen, die es geschmackvoll machen. – Josh
@Josh: Office 2007 hat es auch getan (aber das ist nicht das erste Auftreten des Office-Teams, das Windows-UX-Richtlinien ignoriert). Dennoch wird dieses Dokument von UX-Profis geschrieben und nur Entwickler (oder Code-Affen) arbeiten hart daran, sie zu ignorieren. Und im Interesse der Benutzer sollten sie meiner Meinung nach nur folgen, es sei denn, sie bringen Menschen mit Erfahrung und Wissen und - was am wichtigsten ist - Usability-Tests, um das Gegenteil zu beweisen. – Joey