RSS-Feed Impressum || Admin

[WPF] Fensterrahmen anpassen mit dem WindowChrome

Sonntag, 20. Januar 2013, 21:31 von Dennis Duda

Nach den in .NET 4.0 eingeführten taskbarbezogenen Klassen (#1; #2) im Namespace System.Windows.Shell wurde dort mit dem .NET-Framework 4.5 eine weitere Klasse eingeführt: Der WindowChrome.

Der WindowChrome wird auch als “non-client area” bezeichnet, also der Bereich des Fensters, dessen Rendering vom Programm selbst nicht gesteuert werden kann, kurz gesagt: Der Fensterrahmen. Nun ja, er lässt sich doch steuern: Die WindowChrome-Klasse bietet allerlei Möglichkeiten zur Beeinflussung oder Neuerstellung des Fensterrahmens, und verhindert WinAPI-Frickelei.

Übrigens: Der WindowChrome ist nur für die Aero/DWM-Oberfläche verfügbar, also ab Vista aufwärts. Bei Vista/7 muss Aero angeschaltet sein, bei Windows 8 ist das DWM-Desktop-Compositing immer eingeschaltet. Ist DWM/Aero ausgeschaltet, werden die betroffenen Stellen im Programm schwarz angezeigt.

Aufbau des WindowChromes

Das Hauptaugenmerk der WindowChrome-Klasse liegt auf der gleichnamigen Attached Property WindowChrome.WindowChrome. Diese fügt man – entweder per Style oder direkt – an ein Fenster an, erstellt in dieser ein <WindowChrome /> und kann dort die wichtigsten Einstellungen vornehmen.

Zunächst ist allerdings zu beachten, dass durch das alleinige Hinzufügen von diesem Objekt die Renderfläche (die client-area) des Fensters auf die gesamte Breite und Höhe – inklusive Fensterrahmen – vergrößert wird. Deshalb sieht man bei folgendem Code nur ein weißes Fenster, denn die Standardhintergrundfarbe ist weiß. Darüber hinaus wird der Fenstertitel ausgeblendet. Weiterlesen… »

Geschrieben in WPF | Tags:
Shortlink | 2 Kommentare/TBs/PBs »

[WPF] Layout-Rounding: Unschärfe verhindern

Sonntag, 26. August 2012, 18:23 von Dennis Duda

Wichtig: Der Inhalt dieses Artikels funktioniert nur ab .NET 4 aufwärts.

Wie Sie sicher wissen, ist WPF vektorbasiert und auflösungsunabhängig. Dies wird dadurch erreicht, dass die Größeneinheit in WPF nicht aus “normalen” Gerätepixeln besteht, sondern aus einer logischen Einheit, die 1/96 Zoll groß ist. Das bedeutet, bei der in Windows standardmäßig eingestellten Auflösung von 96 dpi (dots per inch) eine logische Einheit genau ein Pixel groß ist, bei höheren Auflösungen dementsprechend mehr, bei niedrigeren weniger. Die Werte müssen daher keine ganzen Zahlen sein.

Testbild für das Layout-Rounding

Liegt nun ein Wert in der logischen Einheit umgerechnet zwischen zwei Gerätepixeln, müssen diese per Anti-Aliasing verrechnet werden, was in Fällen, in welchen es auf pixelgenaue Positionierung ankommt, zu mehr oder minder starker Unschärfe und Farbveränderungen kommt. Als Beispiel habe ich ein Bild mit pixeldünnen schwarzen und weißen Linien genommen. Liegt dieses auch nur minimal neben einem Gerätepixel, verwaschen die Linien ins Graue. Wenn dies in WPF geschieht ‒ in diesem Fall genau zwischen zwei Pixeln, also 0,5 zu viel oder zu wenig ‒ sieht es aus wie auf dem Bild rechts.

Von einem Muster, geschweige denn von Linien kann man hier nicht mehr sprechen. Schwarz und weiß werden vermischt und ergeben die Durchschnittsfarbe grau (#808080). Verändert man die Fenstergröße dahingehend, dass das Bild auf ganzen Pixeln zentriert wird, wird das Bild wieder korrekt angezeigt.

Ein ähnliches Problem bekommt man, wenn man ein Grid in drei *-Spalten aufteilt, der horizontale Platz also gleichermaßen unter allen drei Spalten aufgeteilt wird, und das Fenster eine Breite von 100 Einheiten hat. Jede Spalte ist dann 33,33… Einheiten breit, bei 96 dpi also auch 33,33… Pixel.

Weiterlesen… »

Geschrieben in WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[WPF] Rahmenloses Fenster erstellen

Montag, 13. August 2012, 15:39 von Dennis Duda

Wollten Sie in Windows Forms ein rahmenloses Fenster erstellen, benutzten Sie FormBorderStyle = None, und schon hatten Sie ein komplett rahmenloses Fenster. Leider wurden damit auch alle fenstereigenen Möglichkeiten zur Änderung der Fenstergröße deaktiviert.

Das Pendant zu FormBorderStyle in WPF ist die Eigenschaft Window.WindowStyle. Auch dieser können Sie den Wert None zuordnen. Ähnlich zu WinForms entfernt dieser den Rahmen des Fensters, wobei er aber einen Resize-Border übrig lässt, einen dünnen Rand, mit dem man das Fenster skalieren kann, vom Aussehen her etwa wie der Rahmen bei Jumplists (“Sprunglisten”). Möchten Sie ein komplett rahmenloses Fenster, können Sie die Skalierfunktionen manuell deaktivieren. Setzen Sie dafür die Eigenschaft Window.ResizeMode auf NoResize.

Geschrieben in WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[WPF] [Win7] Eigenschaften der TaskbarItemInfo-Klasse

Sonntag, 22. Mai 2011, 17:41 von Dennis Duda

Im letzten Artikel habe ich bereits die Eigenschaften ProgressState und ProgressValue vorgestellt. In diesem Artikel werden die anderen TaskbarItemInfo-Eigenschaften behandelt.

Description

Die Eigenschaft Description bestimmt den Text im Tooltip, wenn das Thumbnail eine längere Zeit offen ist. Sie nimmt einen String an.

Weiterlesen… »

Geschrieben in Programmierung, WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[WPF] [Win7] ProgressBar/Ladebalken in der Superbar anzeigen

Sonntag, 22. Mai 2011, 15:27 von Dennis Duda
Windows 7 TaskbarItem mit Statusleiste

Windows 7 TaskbarItem mit Statusleiste

Wahrscheinlich haben Sie – sofern Sie Windows 7 benutzen – schon einmal diesen Status- beziehungsweise Ladebalken in der Superbar gesehen. Seit dem .NET Framework 4 gibt es einen entsprechenden Namespace für die Superbar für WPF: System.Windows.Shell.

In diesem findet sich unter Anderem die Klasse TaskbarItemInfo, welche für ein TaskbarItem, also im Normalfall ein Fenster, den Ladebalken-Status und dessen Fortschritt, so genannte ThubnailButtons (Buttons unter dem Thumbnail), den Thumbnailausschnitt, ein Overlay für das Programm-Icon und die Beschreibung im Tooltip des Thumbnails zuständig ist.

In diesem Artikel geht es um die Ladebalkeneigenschaften. Damit Sie auf diese zugreifen können, benötigen Sie eine TaskbarItemInfo-Instanz, welche der gleichnamigen Eigenschaft eines Windows zugeordnet ist. Dies lässt sich am leichtesten in XAML realisieren:

XAML

<Window [...]>
	<Window.TaskbarItemInfo>
		<TaskbarItemInfo/>
	</Window.TaskbarItemInfo>
</Window>

Alternativ können Sie dasselbe natürlich auch im Code-Behind machen:

Weiterlesen… »

Geschrieben in Programmierung, WPF | Tags:
Shortlink | 2 Kommentare/TBs/PBs »

[WPF] DataGrid.RowEditEnded, wo bist du?

Mittwoch, 18. Mai 2011, 20:22 von Dennis Duda

Ich wollte einfach nur eine Datenbank aktualisieren, nachdem eine Zeile im DataGrid bearbeitet wurde. Ich habe mit die Events angeguckt und RowEditEnding gefunden, aber e.Row.Item enthielt noch das “alte” Item. Nach einer kurzen Suche in der MSDN Library habe ich bemerkt, dass das Silverlight-DataGrid ein RowEditEnded-Event hat, doch dem WPF-DataGrid fehlt dieses. Dasselbe trifft auf CellEditEnded zu.

Gibt es einen anderen Weg an die “neue” Zeile zu kommen, also nachdem die Zeile bearbeitet wurde?

Bei Silverlight benutzt man einfach das RowEditEnded-Event. Um das Parallele auch in WPF hinzubekommen, muss man ein wenig in die Trickkiste greifen, indem man per Dispatcher.Invoke eine Aktion ausführen lässt, die durch die niedrige Priorität erst nach dem RowEditEnding-Event ausgeführt wird. In Codeform sieht das ganze beispielsweise so aus:

VB.NET

Private Sub dg_RowEditEnding(sender As Object, e As DataGridRowEditEndingEventArgs)
	Dispatcher.BeginInvoke(New Action(Function() MessageBox.Show(e.Row.Item.ToString())), System.Windows.Threading.DispatcherPriority.Background)
End Sub

C#

private void dg_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
	Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(e.Row.Item.ToString())), System.Windows.Threading.DispatcherPriority.Background);
}

Schon hat man ein RowEditEnded-Event-Fake.

Geschrieben in Programmierung, WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[WPF] Beim Schließen des ersten Fensters werden alle anderen auch geschlossen. Was nun?

Freitag, 6. Mai 2011, 16:36 von Dennis Duda

Frage:

Ich schließe ein WPF-Fenster mit Me.Close(), doch es werden auch alle anderen Fenster geschlossen und das Programm beendet! Was mache ich falsch?

Antwort:

Da ist wohl der falsche Modus für das Herunterfahren eingetragen. Standardmäßig ist in den Projekteinstellungen unter Modus für das Herunterfahren “Beim Schließen des letzten Fensters” eingetragen. Bei Ihnen ist das nicht so. Um dies zu ändern, folgen Sie der Anweisung:

Doppelklicken Sie auf den Eintrag My Project ihnes Projektes im Projektmappen-Explorer. In der Registerkarte Anwendung finden Sie unten die Eigenschaften des Windows-Anwendungsframeworks. Dort stellen Sie den Modus für das Herunterfahren wieder zurück auf “Beim Schließen des letzten Fensters”. Schon sollte das Problem gelöst sein.

Geschrieben in Programmierung, WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[WPF] Fenster ohne Fensterrahmen verschieben

Freitag, 6. Mai 2011, 15:57 von Dennis Duda

In Windows Forms ist es ziemlich kompliziert ein Fenster zu verschieben, welches keinen Rand hat. Das geht beispielsweise so:

VB.NET

Private ptMouseDownLocation As Point

Private Sub Form1_MouseDown(...) Handles Me.MouseDown
	If e.Button = Windows.Forms.MouseButtons.Left Then
		ptMouseDownLocation = e.Location
	End If
End Sub

Private Sub Form1_MouseMove(...) Handles Me.MouseMove
	If e.Button = Windows.Forms.MouseButtons.Left Then
		Me.Location = e.Location - CType(ptMouseDownLocation, Size) + CType(Me.Location, Size)
	End If
End Sub

C#

private Point ptMouseDownLocation;
private void Form1_MouseDown()
{
	if (e.Button == System.Windows.Forms.MouseButtons.Left) {
		ptMouseDownLocation = e.Location;
	}
}

private void Form1_MouseMove()
{
	if (e.Button == System.Windows.Forms.MouseButtons.Left) {
		this.Location = e.Location - (Size)ptMouseDownLocation + (Size)this.Location;
	}
}

Ziemlich viel Code für solch eine Aufgabe, nicht?

Zum Glück geht das in WPF viel einfacher. In das MouseLeftButtonDown-Ereignis des Fensters (oder eines Steuerelements) kommt diese eine kurze Zeile Code:

Me.DragMove()
this.DragMove();

Das wars! Das Fenster lässt sich jetzt an allen Stellen verschieben, wo kein Steuerelement im Vordergrund ist. Hat man den Code in das MouseLeftButtonDown-Ereignis eines Steuerelements eingefügt, so lässt sich das Fenster nur mit dem Steuerelement verschieben.

Geschrieben in Programmierung, WPF | Tags:
Shortlink | 1 Kommentar/TB/PB »

[WPF] AcceptButton/CancelButton in WPF?

Donnerstag, 7. April 2011, 17:33 von Dennis Duda

Die Standardknöpfe, die per Enter- und Escape-Taste gedrückt werden können, waren unter WinForms oft sehr hilfreich. Auch in der WPF gibt es dafür eine Lösung:

Setzen Sie im entsprechenden Button die Eigenschaft IsDefault für den “AcceptButton” beziehungsweise IsCancel für den “CancelButton” auf True.

Geschrieben in Programmierung, WPF | Tags:
Shortlink | Keine Kommentare/TBs/PBs »

[VS 2010] Anzahl der Codezeilen herausfinden

Freitag, 30. April 2010, 16:57 von Dennis Duda

Beim Ausprobieren der Visual Studio 2010-Funktionen bin ich zufällig auf eine Art Linecounter gekommen.

Dieser öffnet sich wie folgt: Man klickt mit der rechten Maustaste auf das Projekt bzw. sogar die Projektmappe im Projektmappen-Explorer und wählt im Kontextmenü “Codemetrik berechnen” aus. Nach kurzer Zeit klappt ein Tool-Fenster aus, in welchem die Codemetrik-Daten angezeigt werden. Zu den Codemetrik-Daten gehören Wartbarkeit, Zyklomatische Komplexität, Vererbungstiefe, Klassenkopplung und Codezeilen. Es werden nur die Codezeilen gewertet; Kommentare, XAML, XML usw.-Dateien werden nicht mitgezählt.

Nachtrag:

Codezeilen – Gibt die ungefähre Anzahl von Zeilen im Code an.Da die Anzahl auf dem IL-Code basiert, entspricht der Wert nicht der exakten Anzahl von Zeilen in der Quellcodedatei.Ein sehr hoher Wert kann darauf hinweisen, dass ein Typ oder eine Methode zu viele Aufgaben ausführt und aufgeteilt werden sollte.Er könnte auch darauf hindeuten, dass der Typ oder die Methode schwierig zu verwalten ist.

Quelle: http://msdn.microsoft.com/de-de/library/bb385914.aspx

Das heißt wohl, dass es immernoch keine vollständige, integrierte “Zeilenzählmaschine” eingebaut ist.

Geschrieben in Programmierung, Visual Studio | Tags:
Shortlink | Keine Kommentare/TBs/PBs »