Tipp-Upload: VB.NET 0315: Form-Design-Preferences
von Spatzenkanonier
Über den Tipp
Dieser Tippvorschlag ist noch unbewertet.
Der Vorschlag ist in den folgenden Kategorien zu finden:
- Fenster
- Menüs
- Sonstiges
- Steuerelemente
Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
IExtenderProvider,Designer,canextend
Der Vorschlag wurde erstellt am: 24.09.2008 13:17.
Die letzte Aktualisierung erfolgte am 11.01.2009 12:36.
Beschreibung
Form-Designer-Programmierung.
Die CanExtend-Methode der IExtenderProvider-Schnittstelle wird zur Designzeit aufgerufen. Das wird hier in 2-facher Weise ausgenutzt:
1) In einem HashSet (sehr schöne neue Klasse des FW3.5) werden alle Toolstrips gesammelt, also Menustrips, ContextMenustrips, Toolstrips. Beim Klick im Designer auf die "GenerateCode"-Property wird dann pro Toolstrip eine Sub generiert, die die _Click-Events aller im Toolstrip enthaltenen Buttons behandelt.
2) Bestimmte von MS eingestellte Voreinstellungen diverser Controls können evtl. nerven. Die FormPreferences-Klasse nutzt den CanExtend-Aufruf, um festzustellen, ob ein Control neu hinzugefügt wurde. Sodann stellt sie ggfs. die Voreinstellung um, auf den ihr einprogrammierten Wert.
FormPreferences ist erst nach Projekt-Erstellung in der Toolbox verfügbar.
Das ganze ist evtl. mit Makros oder AddIns besser zu lösen, aber wenn man nur VB-Express hat...
FormPreferences kann jederzeit auch wieder entfernt werden.
Schwierigkeitsgrad |
Verwendete API-Aufrufe: |
Download: |
' Dieser Source stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' ' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird. ' In den Zip-Dateien ist er jedoch zu finden. ' --------- Anfang Projektgruppe FormPreferences.sln --------- ' -------- Anfang Projektdatei FormPreferences.vbproj -------- ' ---------------- Anfang Datei Extensions.vb ---------------- ' IDE-Voreinstellungen: ' Option Strict On ' Option Explicit On ' Option Infer On ' Projekt-Voreinstellungen ' Imports System ' Imports System.Windows.Forms ' Imports System.Collections.Generic ' Imports Microsoft.VisualBasic.ControlChars ' Imports System.Linq Imports System.Runtime.CompilerServices Public Module Extensions ''' <summary> testet vor einer Zuweisung, ob der neue Wert überhaupt eine Änderung bringt </summary> ''' <remarks> ''' nützlich bei Zuweisungen an performance-intensive Properties, ''' oder wenn auf Änderungen reagiert werden muß ''' </remarks> <Extension()> _ Public Function Assign(Of T, T2 As T)(ByRef Dest As T, ByVal Src As T2) As Boolean If Object.Equals(Dest, Src) Then Return False Dest = Src Return True End Function <Extension()> _ Public Sub ForEach(Of T)(ByVal Subj As IEnumerable(Of T), ByVal Action As Action(Of T)) For Each O In Subj Action(O) Next End Sub ''' <summary> verkettet alles Strings, fügt Separator dazwischen ein </summary> <Extension()> Public Function ToStringX(ByVal Subj As IEnumerable(Of String), ByVal _ Separator As String) As String With New System.Text.StringBuilder For Each S In Subj .Append(S).Append(Separator) Next If .Length > 0 Then .Remove(.Length - Separator.Length, Separator.Length) End If Return .ToString End With End Function ''' <summary> fügt ein Object-ParamArray als einen Gesamtstring hinzu </summary> <Extension()> _ Public Sub AddX(ByVal Subj As ICollection(Of String), ByVal ParamArray Items() As Object) With New System.Text.StringBuilder Items.ForEach(Function(itm) .Append(If(itm, "##Null##"))) Subj.Add(.ToString()) End With End Sub End Module ' ----------------- Ende Datei Extensions.vb ----------------- ' ----------------- Anfang Datei frmMain.vb ----------------- Public Class frmMain ' Den Code, der hier stehen könnte, möge man sich generieren lassen ;) End Class ' ------------------ Ende Datei frmMain.vb ------------------ ' ------------- Anfang Datei FormPreferences.vb ------------- Imports System.ComponentModel Public Class FormPreferences Inherits Component Implements IExtenderProvider Private Shared _GenerateTabSize As Integer = 3 Private _ToolStrips As New HashSet(Of ToolStrip) Private _NewControls As New HashSet(Of Control) ''' <summary> ''' Doppelklick im Designer auf diese Property löst Code-Generierung für ToolstripItems aus ''' </summary> <Browsable(True)> <Category("Verhalten")> <DefaultValue(False)> Public Property _ GenerateCode() As Boolean Get Return False End Get Set(ByVal value As Boolean) If value Then ExecuteGenerateCode(_ToolStrips) End Set End Property <Browsable(True)> <Category("Verhalten")> <DefaultValue(3)> Public Property _ GenerateTabSize() As Integer Get Return _GenerateTabSize End Get Set(ByVal value As Integer) _GenerateTabSize = value End Set End Property Public Function CanExtend(ByVal extendee As Object) As Boolean Implements _ IExtenderProvider.CanExtend ' Toolstrips merken, für evtl. CodeGenerierung If TypeOf extendee Is ToolStrip Then _ToolStrips.Add(DirectCast(extendee, ToolStrip)) ' Diese OrElse-Kette arbeitet prinzipiell gleich wie eine ElseIf-Kette: sobald eine der ' definierten Bedingungen matcht wird die Kette verlassen. ' Die Bedingung besteht darin, daß TryAction prüft, ob extendee vom angegebenen Typ ist, ' und der Delegat ist die dann einmalig auszuführende Preferenz. ' z.B. bei Labels willich .AutoSize=False haben, und von .HideSelection halte ich bei ' keinem Control etwas, und der voreingestellte Split-Balken des SplitContainers ist mir ' mit 4Pix viel zu schmal. Dim Dum = TryAction(extendee, Function(Obj As SplitContainer) _ Obj.SplitterWidth.Assign(8)) OrElse TryAction(extendee, Function(Obj As Label) _ Obj.AutoSize.Assign(False)) OrElse TryAction(extendee, Function(Obj As TreeView) _ Obj.HideSelection.Assign(False)) OrElse TryAction(extendee, Function(Obj As _ TextBoxBase) Obj.HideSelection.Assign(False)) OrElse TryAction(extendee, _ Function(Obj As ListView) Obj.HideSelection.Assign(False)) End Function ''' <summary> Falls Obj vom Typ T ist wird die Action(Of T) damit ausgeführt </summary> ''' <returns> True, falls Obj vom Typ T ist </returns> Private Function TryAction(Of T As Control)( _ ByVal Obj As Object, ByVal Preference As Action(Of T)) As Boolean ' Nur für **neue** Controls dürfen die Preferenzen ausgeführt werden. ' neue Controls werden durch Test auf .Parent=Nothing identifiziert. ' leider ist für ToolstripItem keine Preferenz definierbar, da nicht von Control erbend. ' ToolstripItem hat auch keine Property mit der man neue Item identifizieren kann. TryAction = TypeOf Obj Is T If TryAction Then Dim Ctl = DirectCast(Obj, T) If Ctl.Parent Is Nothing Then _NewControls.Add(Ctl) Else If _NewControls.Remove(Ctl) Then Preference(Ctl) End If End If End Function Public Shared Sub ExecuteGenerateCode(ByVal _ToolStrips As HashSet(Of ToolStrip)) Dim AllWriter As New List(Of String) Dim Clickables As New List(Of String) For Each CustomerStrip In _ToolStrips Clickables.Clear() For Each Itm As ToolStripItem In CustomerStrip.Items CollectClickables(Itm, Clickables) Next If Clickables.Count > 0 Then Dim sHandles = Clickables.ToStringX(".Click, ") & ".Click" Dim sCase = Tab & Tab & "case Sender Is " Dim sCases = sCase & Clickables.ToStringX(NewLine & NewLine & sCase) & NewLine With AllWriter .AddX("Private Sub ", CustomerStrip.Name, "_MenuClicked(ByVal Sender " & _ "As Object, ByVal e As EventArgs) _") .AddX(Tab, Tab, "Handles ", sHandles) .AddX(Tab, "select case True") .AddX(sCases) .AddX(Tab, "End select") .AddX("End Sub") .AddX("") End With End If Next ' Die Ausgabe wird in eine TextDatei geschrieben, die dann geöffnet wird Dim S = AllWriter.ToStringX(NewLine).Replace(Tab, New String(" "c, _GenerateTabSize)) Dim FileFullName As String = Environment.CurrentDirectory & "\LaunchEditorWith.txt" My.Computer.FileSystem.WriteAllText(FileFullName, S, False) System.Diagnostics.Process.Start(FileFullName).Dispose() End Sub Private Shared Sub CollectClickables(ByVal Itm As ToolStripItem, ByVal Clickables As _ List(Of String)) If TypeOf Itm Is ToolStripDropDownItem Then With DirectCast(Itm, ToolStripDropDownItem) If .HasDropDownItems Then For Each itmRecurse As ToolStripItem In .DropDownItems CollectClickables(itmRecurse, Clickables) ' Rekursion! Next Return End If End With Clickables.Add(Itm.Name) ElseIf TypeOf Itm Is ToolStripButton Then Clickables.Add(Itm.Name) End If End Sub End Class ' -------------- Ende Datei FormPreferences.vb -------------- ' --------- Ende Projektdatei FormPreferences.vbproj --------- ' ---------- Ende Projektgruppe FormPreferences.sln ----------
Diskussion
Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.
Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.