Eigene DLL-Control behält die Eigenschaften nicht.

  • .NET (FX) 4.5–4.8
  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Volker Bunge.

    Eigene DLL-Control behält die Eigenschaften nicht.

    Mit VB.Net ein neues Steuerelemt erstellen, auch für Office (speziell aber Access)

    Hallo zusammen,

    ich bin gerade dabei mir ein neues Steuerelemt für VB.Net und Office (speziell Access ab 2007) zu bauen. Leider habe ich nichts passendes für mein nun folgendes Problem gefunden.
    Alle Beispiele sind entweder nur auf Funktionen o.ä. ausgelegt, oder so einfach, dass diese keine eigenen Eigenschaften haben.

    Grundsätzliches:
    Mein DLL-Projekt habe ich als 'Windows-Forms-Steuerelemtbibliothek (.NET Framework)' erstellt.
    Als Netframework habe ich die 4.8 genommen.
    Die Einstellung 'Assembly COM-sichtbar machen' und 'Für COM-Interop registrieren' sind beide aktiv.
    Ziel CPU ist AnyCPU
    Erstellt wird das Ganze mit Microsoft Visual Studio Enterprise 2022 (64-Bit) - Current, Version 17.8.1 auf einem Win10 22H2 64Bit System
    Das Dll-Projekt wird als Admin ausgeführt. Das Testprojekt normal

    Jetzt habe ich mir im DLL-Projekt zwei Steuerelemente eingebaut, die später das neue Steuerelement ergeben sollen.
    Da das neue Control später neue Möglichkeiten haben soll, habe ich diese eingefügt (siehe Code).
    Mein Control soll die Möglichkeit haben, aus festgelegten Eigenschaften sich Designs auszuwählen. Klar, das die nur ich festlegen kann, aber das wahr erst einmal so ein Grundgedanke, dass man hier doch ein paar als Vorschlag festlegen könnte.

    Wenn ich die DLL mit F5 starte, dann wird auch alles so wie es soll, im Testfenster umgesetzt.

    Wird aber die DLL in das normale Projekt eingebunden (als .Net Framework-Komponente), dann funktioniert das Ändern der Eigenschaften nur in der Entwurfsansicht. Starte ich das Programm auch mit F5,
    dann werden die Änderungen von meinen neuen Eigenschaften nicht übernommen.

    Bevor ich jetzt den Code zeige, wollte ich einmal ein paar generelle Fragen stellen

    1. Ist für die Office-Anwendung die 'Windows-Forms-Steuerelemtbibliothek (.NET Framework)' überhaupt die richtige Ausgangsbasis? Wenn nein, welche wäre hier die Richtige?

    2. Kann ich so einfach zwischen den Anwendungstypen hin und her wechseln? Eigentlich wollte ich nur ein Projekt erstellen und damit VS und Office abdecken.

    3. Jedes neue DLL-Control ist doch eine Kopie aus der DLL und hat somit, was die Eigenschaften betrifft, sein eigenes "Gehirn". Nur ist hier vielleicht die Frage, wie sollte ich das Gehirn nutzen, über Variablen oder über die My.Settings?
    Aktuell arbeite ich im fast fertigen Projekt mit Variablen. Hier im Beispiel habe ich mal mit My.Settings versucht. Leider auch ohne den kpl. Erfolg.

    4. Hier habe ich ein kleines Erklärtutorial Dynamic Link Library’s (DLL’s) in vb.NET Erstellen entdeckt, welches drei interessante Zeilen für mich nennt.

    Imports System.Runtime.InteropServices ' Zugriff auf die DLL ermöglichen
    <Microsoft.VisualBasic.ComClass()>
    <System.Runtime.InteropServices.ComVisible(True)>

    Da man (siehe oben) so ein paar Grundeinstellungen vornehmen muss, würde mich interessieren, was diese drei Zeilen genau machen? Setzten Sie diese Einstellungen kpl. so, wie ich es später brauche oder ist das eine zusätzliche Absicherung.
    Wenn man die drei Zeilen als Ersatz für das Einstellen des Projektes sehen kann, dann wäre es natürlich die schönere Art die Einstellungen vorzunehmen.

    So rein vom optischen würde ich sagen, dass es die Einstellungen sind.

    4. Sollte mein Code kpl. falsch sein, könntet Ihr mir ein funktionierendes Grundgerüst nennen, auf dem ich dann aufbauen kann?

    Das nun folgende Beispiel ist eine Kopie meines bisherigen Codes und beinhaltet nur eine neue (alte) Eigenschaft 'Checked'. Da das Projekt noch 2 Grafiken hat, soll je nach Wert von Checked die eine oder andere Grafik angezeigt werden.
    Was aber leider nicht so klappt wie ich mir das denke bzw. wünsche.

    Es wäre also toll, wenn sich jemand mal den Code bzw. die beiden Projekte ansehen könnte und mir meine Fehler aufzeigen könnte.

    Vielen Dank

    Volker

    Spoiler anzeigen

    Quellcode

    1. Imports System.ComponentModel ' Wird für die Kategorisierung der neuen Eigenschaften benötigt. Ohne diese Zeile bekommen wir in den Zeilen <Category> eine Fehlermeldung
    2. Imports System.Runtime.InteropServices ' Zugriff auf die DLL ermöglichen
    3. <Microsoft.VisualBasic.ComClass()>
    4. Public Class TestDLL
    5. ' OT MS: Bewirkt, dass die aktuelle Klasse oder Schnittstelle die Attribute, Variablen, Eigenschaften, Prozeduren und Ereignisse von einer
    6. ' anderen Klasse oder Gruppe von Schnittstellen erbt.
    7. ' Dies bedeut also, dass man die Eigenschaften, die bei allen hier verwendeten Steuerelemten gleich sind, auch direkt nutzen kann.
    8. ' Diese Eigenschaften müssen alle nicht extra eingebaut werden, sondern werden "durchgeschleift" und an alle Steuerelemente dieses Controls weitergeleitet.
    9. ' Es sind also nur neue Aktionen hinzuzufügen, die es noch nicht gibt bzw. bei denen etwas anderes passieren soll.
    10. ' Multiline bspw. gibt es bei der Textbox, aber nicht bei der Picturebox. Also muss diese Eigenschaft wieder eingebaut werden und auch die Ansteuerung der Textbox muss erfolgen.
    11. Inherits UserControl ' Nimmt uns schon einmal sehr viel Arbeit ab.
    12. ' Hier werden die Aufrufe für die ggf. einzelnen Aktionen deklariert
    13. Public Event Standard_Aktion_ausfuehren As EventHandler
    14. Sub New()
    15. ' ****************************************************************
    16. ' Hier werden ein paar Grundeinstellungen für die neuen Eigenschaften festgelegt,
    17. ' sobald das neue Steuerelement in die Hauptform eingefügt wird
    18. ' ****************************************************************
    19. ' Dieser Aufruf ist für den Designer erforderlich.
    20. InitializeComponent()
    21. My.Settings.Checked = True
    22. My.Settings.Save()
    23. ' Wenn der Checked-Wert auf False steht,
    24. If My.Settings.Checked = False Then
    25. ' dann die passende Grafik für Aus anzeigen
    26. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Aus")
    27. Else
    28. ' andernfalls für Ein
    29. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Ein")
    30. End If
    31. End Sub
    32. ' Ein Versuch, dass die Grafik richtig beim neuzeichnen angezeigt wird.
    33. Shadows Sub paint()
    34. ' Wenn der Checked-Wert auf False steht,
    35. If My.Settings.Checked = False Then
    36. ' dann die passende Grafik für Aus anzeigen
    37. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Aus")
    38. Else
    39. ' andernfalls für Ein
    40. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Ein")
    41. End If
    42. End Sub
    43. #Region "Neue Eigenschaften"
    44. ' *************************************************************************
    45. ' Die nachfolgenden Zeilen stellen die sichtbaren neuen Eigenschaften dar.
    46. ' *************************************************************************
    47. ' Über <Category ...> kann man für jede folgende neue Eigenschaft eine bestehende oder neue Kategorie festlegen, unter der dann diese Eigenschaft zu finden ist.
    48. ' Ich habe mich hier für eine durch den Buchstaben A anfangne Kategorie entschieden. Dadurch stehen die neuen Eigenschaften ganz oben. Lässt man die Zeile weg, so gibt es eine Kategorie 'Sonstige'
    49. ' Da die folgenden Eigenschaften immer gleich aufgebaut sind, habe ich mir die Beschriftung nur in die erste eingetragen.
    50. <Category("Alternative Eigenschaften")>
    51. <System.Runtime.InteropServices.ComVisible(True)>
    52. Public Property Checked As Boolean
    53. ' Wenn der Wert der Eigenschaft zurück gegeben werden soll,
    54. Get
    55. ' dann wird hier der aktuelle Wert zurück gegeben
    56. Return My.Settings.Checked
    57. End Get
    58. ' Soll er hingegen geändert werden,
    59. Set(value As Boolean)
    60. ' dann bekommt die interne Variable den aktuellen Wert erst einmal zugewiesen
    61. My.Settings.Checked = value
    62. My.Settings.Save()
    63. ' und danach wird die ggf. notwendige Aktion aufgerufen
    64. RaiseEvent Standard_Aktion_ausfuehren(Me, EventArgs.Empty)
    65. End Set
    66. End Property
    67. #End Region
    68. #Region "und die neuen Aktionen"
    69. Private Sub HandleStandard_Aktion_ausfuehren(sender As Object, e As EventArgs) Handles Me.Standard_Aktion_ausfuehren
    70. ' ****************************************************************
    71. ' Hier wird auf Änderungen der Eigenschaft reagieren
    72. ' ****************************************************************
    73. ' Aufgrund der neuen Einstellung wird die Anzeige der Grafik bzw. der Textbox neu durchgeführt
    74. ' Hier kommen also alle Aktionen hin, die dann auf die aktuellen Einstellungen der Eigenschaften reagieren.
    75. ' Wenn der Checked-Wert auf False steht,
    76. If My.Settings.Checked = False Then
    77. ' dann die passende Grafik für Aus anzeigen
    78. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Aus")
    79. Else
    80. ' andernfalls für Ein
    81. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Ein")
    82. End If
    83. End Sub
    84. ' Hier mal die drei Möglichkeiten, später die Umschaltung von dem Wert Checked vorzunehmen
    85. Private Sub PBox_Button_Click(sender As Object, e As EventArgs) Handles PBox_Button.Click
    86. If Checked = True Then
    87. Checked = False
    88. Else
    89. Checked = True
    90. End If
    91. End Sub
    92. Private Sub TestDLL_Click(sender As Object, e As EventArgs) Handles Me.Click
    93. If Checked = True Then
    94. Checked = False
    95. Else
    96. Checked = True
    97. End If
    98. End Sub
    99. Private Sub TextBox1_Click(sender As Object, e As EventArgs) Handles TextBox1.Click
    100. If Checked = True Then
    101. Checked = False
    102. Else
    103. Checked = True
    104. End If
    105. End Sub
    106. #End Region
    107. End Class


    Thema verschoben; Das Thema wird automatisch dort erstellt, wo man sich befindet, wenn man auf [✱ Neues Thema] klickt. ~VaporiZed
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Volker Bunge schrieb:

    Starte ich das Programm auch mit F5, dann werden die Änderungen von meinen neuen Eigenschaften nicht übernommen.
    Was ganz genau funktioniert bzw. nicht?
    =====
    Mach Dir eine Projektmappe mit beiden Projekten und füge das DLL-Projekt (nicht aber die DLL) dem GUI-Projekt als Verweis hinzu.
    Wieso liest Du den Checked-Wert aus den Settings aus und nicht aus dem Control?
    Und:

    VB.NET-Quellcode

    1. Checked = Not Checked

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo zusammen,

    erst einmal sorry, dass ich mich erst jetzt melde, aber hatte leider noch andere Dinge zu tun.

    Ich habe ja in meinem Eingangspost schon einmal den Testcode und eine gezippte Datei mit den beiden Projekten (TestDLL und Checkbox_testen) reingestellt.

    Noch einmal von vorne

    Ziel:
    Es soll eine neue Art von Checkbox werden, die neue Möglichkeiten schafft. Das Endziel ist es, diese auch in Officeanwendungen zu verwenden, hier speziell erst einmal für meine Zwecke Access 2019 aufwärts. Gerne auch später für andere schon in früheren Versionen. Da in Word und Excel nicht so oft mit Eingabemasken oder ähnlichen gearbeitet wird, muss es hier nicht unbedingt funktionieren, wäre aber auch sehr schön wenn es das würde.

    Natürlich könnte ich mir noch die ein oder andere Verbesserung vorstellen, aber das ist dann ja nicht mehr das allzu große Problem, wenn dieses Projekt läuft.

    Was habe ich schon gemacht?
    Erst einmal habe ich das Projekt soweit kpl. fertig, dass es so funktioniert, wie ich mir das vorstelle. Alle neuen Eigenschaften kann ich von außen ansteuern und es passiert auch das, was passieren soll Also meinte ich, ich wäre schon fast fertig. Dann kam aber das große ABER daher.

    Ich habe auch schon das neue Steuerelement in ein Testprojekt eingebunden und auch dort reagiert in der Entwurfsansicht der Code so, wie er soll.

    Was leider nicht funktioniert
    1. Normalerweise stellt man ja in der neuen Anwendung die Eigenschaften pro Steuerelement ein und wenn dann das Programm gestartet wird, sind die Basiseinstellungen so, wie man diese in der Entwurfsansicht eingestellt hat. Dies ist nur leider bei mir aktuell nicht der Fall.
    2. Darauf hin habe ich schon einmal ein anderen Thread Eigenes Control - Eigene Eigenschaften in eine eigene Gruppe packen eröffnet, der sich auf das selbe Projekt bezieht, aber eine andere Problemstellung hat (Hier ab Post 4). RodFromGermany Du hattes mir empfohlen, ein Testprojekt zu erstellen und es hier einzustellen. (Ja, ich habe mich bei dem anderen Post auch noch nicht zurückgemeldet, aber das kommt hoffentlich bald noch). Also habe ich mich an diese Antwort erinnert und es hier gleich so umgesetzt. Da der Testcode nur ca. 150 Zeilen lang ist, habe ich diesen auch oben mit veröffentlich.

    Ich beschreibe noch einmal möglichst genau, was nicht funktioniert bzw. was ich gemacht habe.
    - Im Testprojekt ist unter den Verweisen meine Text.DLL zu sehen. Die lokale Kopie steht auf True und der Pfad steht auf dem Bin\Debug Pfad, wo mein Test.DLL Projekt die DLL erzeugt.
    - Die Toolbox wurde über rechte Maustaste, Elemente auswählen, .NET-Framework-Komponenten, Durchsuchen, Bin\Debug\Test.DLL eingebunden. Das Steuerelement erscheint nun in der Toolbox "Alle Windows Forms" ganz unten als TestDLL
    - Nun habe ich per Doppelklick mir mein neues Steuerelement in eine leere Form eingefügt. Es erscheint mein neues Steuerelement und wird auch mit dem aktuell gültigen Checked-Wert richtig angezeigt.
    - Da ja in der Test.DLL aktuell nur der Checked-Wert die eigene Eigenschaft ist, stelle ich den nun um. Das Bild ändert sich daraufhin in das richtige Bild. Auch das mehrmalige Umschalten funktioniert in der Entwurfsansicht tadellos
    - Starte ich nun das Testprojekt mit F5, so wird mir auch immer das richtige Bild zum passenden Checked-Wert angezeigt. Auch das Umschalten des Checked-Wertes durch anklicken auf das Bild, auf den Text und auf die Zwischenflächen meines Controls funktioniert somit einwandfrei.
    - Nun wieder zurück in die Entwurfsansicht und den Checked-Wert geändert. Dann per Doppelklick in die Toolbox ein zweites TestDLL-Steuerelement eingefügt.
    - Jetzt habe ich also das Erste mit Checked = False und das Zweite mit Checked = True in der Entwurfsansicht stehen. Soweit ja alles schön. Ändere ich den Checked-Wert von zweiten Control, so ändert sich auch nur dieses.
    - Starte ich also mit Checked False und True mein Testprogramm, dann werden beide Controls gleich angezeigt. Hier True.
    - Also zurück zur Entwurfsansicht und dort beide Checked-Werte getauscht. Erst das Zweite und dann das Erste. F5 starten und es werden wieder beide im True Status angezeigt. True ist jetzt ja das Erste aber das Zweite, welches ich geändert habe.
    - Alles noch einmal anders herum: Also erst das Erste auf False und das Zweite auf True. F5 starten und wieder beide stehen auf True.
    - Stelle ich beide auf False (hier also das Zweite, Erste steht ja immer noch auf False), F5 starten und dann ist komischer Weise das Erste True und das Zweite False
    - Stelle ich nun das Erste auf True, F5 starten und dann sind beide True

    Also irgendwie alles sehr komisch.
    Ihr könnte ja gerne mal das Testprojekt ausprobieren und Euch das Ganze selbst ansehen.

    Jetzt noch einmal eine generelle Frage: Was ist eine DLL-Datei bzw. dessen Inhalt eigentlich?
    Bei Funktionen oder Subs ist es für mich eigentlich schon klar. Hier wird irgend etwas berechnet, geöffnet und irgendwie etwas zurück gegeben. Also Quassie nur eine Auslagerung von Möglichkeiten, die ich nur einmal erstellen muss, aber von diversen Stellen aus aufrufen kann. Soweit klar.

    Aber was sind DLL-Dateien wie ich sie hier versuche zu bauen? Sind es eine Kopie im Arbeitsspeicher pro Steuerelement oder ist es ein Steuerelement, welches ich falsch versuche zu duplizieren? Eigentlich müsste doch jede Kopie sein eigenes "Gehirn" haben, was deren Eigenschaften betrifft. Sei es jetzt vererbte oder eigene Eigenschaften. Nur dann kann doch jedes Steuerelement selbstständig so reagieren, wie es seine eigenen Eigenschaften es vorgeben.

    Wenn ich mein Testprogramm starte, dann sind die vorher eingestellten Werte nicht die, die ich eingestellt habe. Ändere ich jetzt durch klicken ein Steuerelement, dann reagiert auch nur dieses. Also eigentlich so, wie es sein soll.
    Klar ist auch, dass im Endprojekt die Checked-Werte durch den Code oder durch Daten aus Tabellen sich noch einmal den aktuellen Werten beim Starten anpassen. Da ich aber Eigenschaften einbauen möchte, die sich hauptsächlich auf die Optik beziehen, ist es also meist nur der Checked-Wert, der sich hier dynamisch ändert (was ja dann auch so richtig ist).

    Heißt das für mich am Ende, dass nur das Starten und sich somit das holen der im Entwurf eingestellten Werte, nicht funktioniert?

    RodfromGermany: Wieso liest Du den Checked-Wert aus den Settings aus und nicht aus dem Control?
    Antwort: Wie man ja im Code schon sieht, nutzte ich die Checkbox nicht in meinem neuen Control. Da diese Eigenschaft somit nicht vererbt werden kann, muss ich diese selbst hinzufügen. Ich habe jetzt noch nicht probiert eine später nicht sichtbare Checkbox einzubauen und somit auf die vererbte Checked-Eigenschaft zu kommen. Aber da ich das Problem auch mit meinen wirklich neuen Eigenschaften habe, steht Checked hier nur mal als Stellvertreter.

    Kann eine DLL überhaupt mit My.Settings arbeiten? Im meinem "fast fertigen" Projekt arbeite ich mit Variablen, aber auch hier leider ohne Erfolg. Daher habe ich hier mal My.Setting versucht.

    Ich hoffe, dass meine Beschreibungen nicht zu verwirrend sind, aber testet einfach mal den Code.

    Über eine positive Rückmeldung würde ich mich sehr freuen.

    Volker
    @Volker Bunge Lässt sich das ganze auch ohne COM reproduzieren?
    Ich habe keine Lust, irgend etwas registrieren zu müssen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo RodFromGermany,

    ich wüsste jetzt leider aktuell nicht, wie ich das ohne COM reproduzieren könnte.

    Wie gesagt, in der Entwurfsansicht läuft ja alles richtig.

    Schade, dass die keine Lust hast, mein Beispiel zu testen (aber auch verständlich, wenn man hier im Forum alles installieren würde, dann hätte man entweder ein sehr wirres System oder man müsste ständig ein sauberes System neu aufsetzen).

    Hast Du denn eine Idee bzw. wie würdest Du selbst so ein Problem lösen?

    Leider habe ich im Netz noch nichts passendes gefunden. Alle Beispiele sind recht einfach gehalten oder benutzen das neue Control nur einmal.

    Wie sieht es den mit meinen Fragen bzw. der DLL-Funktionsweise aus? Kannst Du mir diese ggf. beantworten?

    Vielleicht hat ja noch ein anderer Ideen, woran es liegt, dass mein Beispiel nicht so läuft, wie gedacht.

    Gruß

    Volker

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Volker Bunge“ ()

    Volker Bunge schrieb:

    wie ich das ohne COM reproduzieren könnte.
    Heißt das, dass die COM-Property Schuld an dem Dilemma ist?
    Vielleicht klärst Du das zumächst auf.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Normalerweise stellt man ja in der neuen Anwendung die Eigenschaften pro Steuerelement ein und wenn dann das Programm gestartet wird, sind die Basiseinstellungen so, wie man diese in der Entwurfsansicht eingestellt hat. Dies ist nur leider bei mir aktuell nicht der Fall.


    Siehe Post 3, der Designer speichert die einstellung nur wenn du ihm sagst das er das tun soll. Dir Fehlt bei deiner Checked Eigenschaft das Attribute. Darüber hinaus darfst du das natürlich nicht überschreiben also musst du deinen Konstruktor ändern. My.Settings.Save() fliegt raus ebenso wie My.Settings.Checked = True anstelle dessen schreibst du Checked = My.Settings.Checked.

    C#-Quellcode

    1. [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(true)]
    2. public bool Checked
    3. {
    4. get => My.Settings.Checked;
    5. set => My.Settings.Checked = value; // Speichern hab ich mir hier gespart.
    6. }


    *Edit*
    An stelle von My.Settings würde sich im getter und setter ein Backingfield besser machen.

    C#-Quellcode

    1. [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(true)]
    2. public bool Checked
    3. {
    4. get => isChecked;
    5. set => isChecked = value; // Speichern hab ich mir hier gespart.
    6. }
    7. private bool isChecked;

    Im Konstruktor könntest du dann isChecked = My.Settings.Checked schreiben.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Fakiz“ ()

    Hallo zusammen,

    vielen Dank erst einmal für die Geduld und die Antworten.

    Gestern habe ich noch einmal den Code umgestellt und auch vereinfacht (Das Wechseln der Bilder sowie das Wechseln des Checked Wertes gibt es jetzt nur einmal und dafür gibt es den passenden Aufruf. Aber diese Sache hätte ich eh noch gemacht).So, jetzt erst einmal der Code

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel ' Wird für die Kategorisierung der neuen Eigenschaften benötigt. Ohne diese Zeile bekommen wir in den Zeilen <Category> eine Fehlermeldung
    2. Imports System.Runtime.InteropServices ' Zugriff auf die DLL ermöglichen
    3. <Microsoft.VisualBasic.ComClass()>
    4. Public Class TestDLL
    5. ' OT MS: Inherits bewirkt, dass die aktuelle Klasse oder Schnittstelle die Attribute, Variablen, Eigenschaften, Prozeduren und Ereignisse von einer
    6. ' anderen Klasse oder Gruppe von Schnittstellen erbt.
    7. '
    8. ' Dies bedeut also, dass man die Eigenschaften, die bei allen hier verwendeten Steuerelemten gleich sind, auch direkt nutzen kann.
    9. ' Diese Eigenschaften müssen alle nicht extra eingebaut werden, sondern werden "durchgeschleift" und an alle Steuerelemente dieses Controls weitergeleitet.
    10. ' Es sind also nur neue Aktionen hinzuzufügen, die es noch nicht gibt bzw. bei denen etwas anderes passieren soll.
    11. ' Multiline bspw. gibt es bei der Textbox, aber nicht bei der Picturebox. Also muss diese Eigenschaft wieder eingebaut werden und auch die Ansteuerung der Textbox muss erfolgen.
    12. Inherits UserControl ' Nimmt uns schon einmal sehr viel Arbeit ab.
    13. ' Für die neuen Eigenschaften werden hier die entsprechenden Variablen festgelegt
    14. Private _Checked As Boolean
    15. ' Hier werden die Aufrufe für die ggf. einzelnen Aktionen deklariert
    16. Public Event Standard_Aktion_ausfuehren As EventHandler
    17. Sub New()
    18. ' ****************************************************************
    19. ' Hier werden ein paar Grundeinstellungen für die neuen Eigenschaften festgelegt,
    20. ' sobald das neue Steuerelement in die Hauptform eingefügt wird
    21. ' ****************************************************************
    22. ' Dieser Aufruf ist für den Designer erforderlich.
    23. InitializeComponent()
    24. ' Startwert festlegen
    25. _Checked = True
    26. ' Die richtigen Bilder anzeigen
    27. Call Bilder_wechseln()
    28. End Sub
    29. #Region "Neue Eigenschaften"
    30. ' *************************************************************************
    31. ' Die nachfolgenden Zeilen stellen die sichtbaren neuen Eigenschaften dar.
    32. ' *************************************************************************
    33. ' Über <Category ...> kann man für jede folgende neue Eigenschaft eine bestehende oder neue Kategorie festlegen, unter der dann diese Eigenschaft zu finden ist.
    34. ' Ich habe mich hier für eine durch den Buchstaben A anfangne Kategorie entschieden. Dadurch stehen die neuen Eigenschaften ganz oben. Lässt man die Zeile weg, so gibt es eine Kategorie 'Sonstige'
    35. ' Da die folgenden Eigenschaften immer gleich aufgebaut sind, habe ich mir die Beschriftung nur in die erste eingetragen.
    36. ' Browsable(True) = Die Checked-Eigenschaft ist sichtbar, False nicht sichtbar
    37. '<Category("Alternative Eigenschaften"),
    38. ' System.Runtime.InteropServices.ComVisible(True),
    39. ' Browsable(True),
    40. ' System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
    41. ' DefaultValue(True)>
    42. <Category("Alternative Eigenschaften"),
    43. System.Runtime.InteropServices.ComVisible(True)>
    44. Public Property Checked As Boolean
    45. ' Wenn der Wert der Eigenschaft zurück gegeben werden soll,
    46. Get
    47. ' dann wird hier der aktuelle Wert zurück gegeben
    48. Return _Checked
    49. End Get
    50. ' Soll er hingegen geändert werden,
    51. Set(value As Boolean)
    52. ' dann bekommt die interne Variable den aktuellen Wert erst einmal zugewiesen
    53. _Checked = value
    54. ' und danach wird die ggf. notwendige Aktion aufgerufen
    55. RaiseEvent Standard_Aktion_ausfuehren(Me, EventArgs.Empty)
    56. End Set
    57. End Property
    58. #End Region
    59. #Region "und die neuen Aktionen"
    60. Private Sub HandleStandard_Aktion_ausfuehren(sender As Object, e As EventArgs) Handles Me.Standard_Aktion_ausfuehren
    61. ' ****************************************************************
    62. ' Hier wird auf Änderungen der Eigenschaft reagieren
    63. ' ****************************************************************
    64. ' Aufgrund der neuen Einstellung wird die Anzeige der Grafik bzw. der Textbox neu durchgeführt
    65. ' Hier kommen also alle Aktionen hin, die dann auf die aktuellen Einstellungen der Eigenschaften reagieren.
    66. ' Die richtigen Bilder anzeigen
    67. Call Bilder_wechseln()
    68. End Sub
    69. ' Hier mal die drei Möglichkeiten, später die Umschaltung von dem Wert Checked vorzunehmen
    70. Private Sub PBox_Button_Click(sender As Object, e As EventArgs) Handles PBox_Button.Click
    71. Call Status_Bild_wechseln()
    72. End Sub
    73. Private Sub TestDLL_Click(sender As Object, e As EventArgs) Handles Me.Click
    74. Call Status_Bild_wechseln()
    75. End Sub
    76. Private Sub TextBox1_Click(sender As Object, e As EventArgs) Handles TextBox1.Click
    77. Call Status_Bild_wechseln()
    78. End Sub
    79. #End Region
    80. #Region "Unterroutinen"
    81. Sub Status_Bild_wechseln()
    82. ' Wechselt den Checked-Wert in das Gegenteil
    83. If _Checked = True Then
    84. _Checked = False
    85. Else
    86. _Checked = True
    87. End If
    88. ' und zeigt dann das richtige Bild an
    89. Call Bilder_wechseln()
    90. End Sub
    91. Sub Bilder_wechseln()
    92. ' Wenn der Checked-Wert auf False steht,
    93. If _Checked = False Then
    94. ' dann die passende Grafik für Aus anzeigen
    95. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Aus")
    96. Else
    97. ' andernfalls für Ein
    98. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Ein")
    99. End If
    100. End Sub
    101. Private Sub TestDLL_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    102. ' Sobald das neue Control in der Größe geändert wird, werden hier alle notwendigen Anpassungen durchgeführt.
    103. ' Zu Testzwecken hier nur das Bilderwechseln
    104. Call Bilder_wechseln()
    105. End Sub
    106. #End Region
    107. End Class


    Die Eigenschaft lässt sich jetzt ändern und entspricht beim Starten (F5) auch der Entwurfsansicht und dass egal wie ich es nun ändere. Also alles perfekt. Als nächsten werde ich mein "fertiges" Projekt hoffentlich erfolgreich so umschreiben, dass es auch so klappt wie gewünscht.

    Jetzt habe ich aber trotzdem noch ein paar Fragen.

    1. Wie man in Zeile 49-53 sieht, habe ich mal die Angaben deaktiviert. Da ich gerne einmal für mich diese Angaben verstehen würde, bräuchte ich hier mal einfache gut verständliche Erklärungen zu den einzelnen Punkten. Category habe ich sofort verstanden (Siehe Erklärung oben im Code).
    Aber die anderen Angaben habe ich zwar mal übernommen, aber selbst mit der Erklärung aus dem Internet werde ich hier nicht so recht schlau.
    Wenn ich Browsable(False) setzt, dann wird die Checked-Eigenschaft nicht mehr angezeigt.
    Bei DefaultValue(True) hatte ich eigentlich gedacht, dass man hier für die Eigenschaft Checken den Startwert festlegen kann, aber leider klappt das so nicht. Deshalb habe ich Zeile 33 eingefügt.
    Und bei System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Content) hatte ich beim Post von Fakiz gedacht, das es sich um eine Scherzantwort hielt (sorry, so kam es aber beim lesen der Antwort rüber.) Dann stellte ich aber fest, dass es tatsächlich ein Befehl ist. Aber die Erklärung im Internet brachten da ehr Verwirrung als Aufklärung. Beim ersten Versuch diese Parameter zu schreiben, bin ich davon ausgegangen, dass ich diese auch untereinander mit <> schreiben kann. Dies war leider nicht der Fall bzw. die Eigenschaften zeigten für mich keine Auswirkungen (ausser bei Browsable(True) (siehe Beschreibung im Code) tat sich nichts.

    2. Stimmt meine Erklärung bzgl. Inherits UserControl in den Zeilen 8-14? Wenn ja, dann ist der Punkt verstanden.

    Daher wäre es nett, wenn mir jemand mal die o. g. Punkte mit einfachen Worten erklären könnte?

    Was natürlich jetzt noch kpl. fehlt ist, dass ich das neue Control in Access nutzen kann. Ich habe zwar schon die TLB-Datei als Verweis eingebunden, aber als Steuerelement bekomme ist es noch nicht hin. Wenn Ihr hier einen Tipp für mich habt, dann würde ich mich sehr freuen.

    Volker

    CodeTags korrigiert; bitte zukünftig darauf achten, das richtige CodeHighlighting zu verwenden ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Mit Hilfe des Browsable-Attributes kannst du bestimmen ob eine Eigenschaft im PropertyGrid angezeigt werden soll oder nicht.

    Das DefaultValue-Attribute ist eine Sache für sich. Zum einen wird im PropertyGrid Werte die nicht dem DefaultValue entsprechen Fett hervorgehoben und zum anderem werden Eigenschaften deines Steuerelements die den Standardwert besitzen nicht in den DesignerCode Serialisiert.
    Ich hab mal 2 Bilder angehängt auf dem 1. Bild (PropertyGrid) kannst du unter Darstellung die beiden Eigenschaften Checked und CheckedEx finden. Die Checked-Eigenschaft die meine CheckBoxEx Klasse von CheckBox erbt habe ich überschrieben.
    Diese Eigenschaft wird nicht in die Designer-Datei geschrieben da ich die Eigenschaft mit dem DesignerSerializationVisibility-Attribute dekoriert und den Wert DesignerSerializationVisibility.Hidden zugewiesen habe.

    Die Eigenschaft CheckEx wird in die Designer-Datei geschrieben da sie nicht dem Standard-Wert entspricht und ich der IDE mit DesignerSerializationVisibility.Visible mitteile das der Wert der Eigenschaft gespeichert werden soll. DesignerSerializationVisibility.Visible ist also für einzelne Werte gedacht.

    Für die Eignschaft SampleStrings wird in der Designer-Datei ein Array angelegt dafür ist DesignerSerializationVisibility.Content verantwortlich.

    Wenn du dir jetzt PropertyGrid-1 ansiehst wirst du feststellen das Ich die Eigenschaft CheckedEx auf False gesetzt habe (Standard-Wert) im PropertyGrid wird der Wert nun nicht mehr Fett dargestellt ebenso findet dieser sich auch nicht mehr in der Designer-Datei.
    Bilder
    • PropertyGrid.png

      157,41 kB, 1.651×876, 11 mal angesehen
    • PropertyGrid-1.png

      80,49 kB, 540×828, 12 mal angesehen
    Bitte nutze den vb.net-tag, wenn du vb-snippets postest. Was du eingestellt hast findich komplett unleserlich. den vb.net-tag nutzen ist kein Hexenwerk:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel ' Wird für die Kategorisierung der neuen Eigenschaften benötigt. Ohne diese Zeile bekommen wir in den Zeilen <Category> eine Fehlermeldung
    2. Imports System.Runtime.InteropServices ' Zugriff auf die DLL ermöglichen
    3. <Microsoft.VisualBasic.ComClass()>
    4. Public Class TestDLL
    5. ' OT MS: Inherits bewirkt, dass die aktuelle Klasse oder Schnittstelle die Attribute, Variablen, Eigenschaften, Prozeduren und Ereignisse von einer
    6. ' anderen Klasse oder Gruppe von Schnittstellen erbt.
    7. '
    8. ' Dies bedeut also, dass man die Eigenschaften, die bei allen hier verwendeten Steuerelemten gleich sind, auch direkt nutzen kann.
    9. ' Diese Eigenschaften müssen alle nicht extra eingebaut werden, sondern werden "durchgeschleift" und an alle Steuerelemente dieses Controls weitergeleitet.
    10. ' Es sind also nur neue Aktionen hinzuzufügen, die es noch nicht gibt bzw. bei denen etwas anderes passieren soll.
    11. ' Multiline bspw. gibt es bei der Textbox, aber nicht bei der Picturebox. Also muss diese Eigenschaft wieder eingebaut werden und auch die Ansteuerung der Textbox muss erfolgen.
    12. Inherits UserControl ' Nimmt uns schon einmal sehr viel Arbeit ab.
    13. ' Für die neuen Eigenschaften werden hier die entsprechenden Variablen festgelegt
    14. Private _Checked As Boolean
    15. ' Hier werden die Aufrufe für die ggf. einzelnen Aktionen deklariert
    16. Public Event Standard_Aktion_ausfuehren As EventHandler
    17. Sub New()
    18. ' ****************************************************************
    19. ' Hier werden ein paar Grundeinstellungen für die neuen Eigenschaften festgelegt,
    20. ' sobald das neue Steuerelement in die Hauptform eingefügt wird
    21. ' ****************************************************************
    22. ' Dieser Aufruf ist für den Designer erforderlich.
    23. InitializeComponent()
    24. ' Startwert festlegen
    25. _Checked = True
    26. ' Die richtigen Bilder anzeigen
    27. Call Bilder_wechseln()
    28. End Sub
    29. #Region "Neue Eigenschaften"
    30. ' *************************************************************************
    31. ' Die nachfolgenden Zeilen stellen die sichtbaren neuen Eigenschaften dar.
    32. ' *************************************************************************
    33. ' Über <Category ...> kann man für jede folgende neue Eigenschaft eine bestehende oder neue Kategorie festlegen, unter der dann diese Eigenschaft zu finden ist.
    34. ' Ich habe mich hier für eine durch den Buchstaben A anfangne Kategorie entschieden. Dadurch stehen die neuen Eigenschaften ganz oben. Lässt man die Zeile weg, so gibt es eine Kategorie 'Sonstige'
    35. ' Da die folgenden Eigenschaften immer gleich aufgebaut sind, habe ich mir die Beschriftung nur in die erste eingetragen.
    36. ' Browsable(True) = Die Checked-Eigenschaft ist sichtbar, False nicht sichtbar
    37. '<Category("Alternative Eigenschaften"),
    38. ' System.Runtime.InteropServices.ComVisible(True),
    39. ' Browsable(True),
    40. ' System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
    41. ' DefaultValue(True)>
    42. <Category("Alternative Eigenschaften"),
    43. System.Runtime.InteropServices.ComVisible(True)>
    44. Public Property Checked As Boolean
    45. ' Wenn der Wert der Eigenschaft zurück gegeben werden soll,
    46. Get
    47. ' dann wird hier der aktuelle Wert zurück gegeben
    48. Return _Checked
    49. End Get
    50. ' Soll er hingegen geändert werden,
    51. Set(value As Boolean)
    52. ' dann bekommt die interne Variable den aktuellen Wert erst einmal zugewiesen
    53. _Checked = value
    54. ' und danach wird die ggf. notwendige Aktion aufgerufen
    55. RaiseEvent Standard_Aktion_ausfuehren(Me, EventArgs.Empty)
    56. End Set
    57. End Property
    58. #End Region
    59. #Region "und die neuen Aktionen"
    60. Private Sub HandleStandard_Aktion_ausfuehren(sender As Object, e As EventArgs) Handles Me.Standard_Aktion_ausfuehren
    61. ' ****************************************************************
    62. ' Hier wird auf Änderungen der Eigenschaft reagieren
    63. ' ****************************************************************
    64. ' Aufgrund der neuen Einstellung wird die Anzeige der Grafik bzw. der Textbox neu durchgeführt
    65. ' Hier kommen also alle Aktionen hin, die dann auf die aktuellen Einstellungen der Eigenschaften reagieren.
    66. ' Die richtigen Bilder anzeigen
    67. Call Bilder_wechseln()
    68. End Sub
    69. ' Hier mal die drei Möglichkeiten, später die Umschaltung von dem Wert Checked vorzunehmen
    70. Private Sub PBox_Button_Click(sender As Object, e As EventArgs) Handles PBox_Button.Click
    71. Call Status_Bild_wechseln()
    72. End Sub
    73. Private Sub TestDLL_Click(sender As Object, e As EventArgs) Handles Me.Click
    74. Call Status_Bild_wechseln()
    75. End Sub
    76. Private Sub TextBox1_Click(sender As Object, e As EventArgs) Handles TextBox1.Click
    77. Call Status_Bild_wechseln()
    78. End Sub
    79. #End Region
    80. #Region "Unterroutinen"
    81. Sub Status_Bild_wechseln()
    82. ' Wechselt den Checked-Wert in das Gegenteil
    83. If _Checked = True Then
    84. _Checked = False
    85. Else
    86. _Checked = True
    87. End If
    88. ' und zeigt dann das richtige Bild an
    89. Call Bilder_wechseln()
    90. End Sub
    91. Sub Bilder_wechseln()
    92. ' Wenn der Checked-Wert auf False steht,
    93. If _Checked = False Then
    94. ' dann die passende Grafik für Aus anzeigen
    95. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Aus")
    96. Else
    97. ' andernfalls für Ein
    98. PBox_Button.BackgroundImage = My.Resources.ResourceManager.GetObject("Grafik_01_Ein")
    99. End If
    100. End Sub
    101. Private Sub TestDLL_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    102. ' Sobald das neue Control in der Größe geändert wird, werden hier alle notwendigen Anpassungen durchgeführt.
    103. ' Zu Testzwecken hier nur das Bilderwechseln
    104. Call Bilder_wechseln()
    105. End Sub
    106. #End Region
    107. End Class




    Volker Bunge schrieb:

    Was natürlich jetzt noch kpl. fehlt ist, dass ich das neue Control in Access nutzen kann.
    Bei uns auf Arbeit binden wir eine .Net-Control-Lib in ein vb6-projekt ein, indem wir vom .Net eine .Net-dll und eine .Net-ocx kompilieren (und dabei in der Registry registrieren), und in vb6 einen Verweis darauf setzen.
    Wie man in msAccess einen Verweis auf so eine ocx/dll setzt weiss ich nicht - ich finde com-interOp insgesamt eine höchst anfällige Krücke auf Stelzen.
    Für so bischen KlickiBunti würde ich sowas keinesfalls anfassen.
    Hallo zusammen,

    vielen Dank erst einmal für Eure Antworten.

    Fakiz:
    Ich werde mir das Ganze noch einmal in der Praxis ansehen und dann entscheiden, ob ich welche Einstellung übernehme.

    ErfinderDesRades:
    Vielen Dank für den vb.net.rag Hinweis. Natürlich ist das kein Problem diesen zu nutzen. Ich werde mich in Zukunft bemühen, daran zu denken.

    Aber es muss doch möglich sein, ein Steuerelement auch für Officeanwendungen zu erstellen, die es aktuell noch nicht gibt bzw. dessen Optik oder Funktionalität man verbessern möchte. Ob das dann was für die breite Masse ist, ist dann noch was ganz anderes.

    Aber meine neue Checkbox würde ich schon recht oft benötigen. Daher wäre ein neuen Steuerelement natürlich was feines.

    Dein beschriebener Umweg über VB6 hört sich ja wirklich nicht gesund an. Gerade, weil es ja VS schon recht lange gibt. Aber gerade in Access sind die Steuerelemente doch in der Optik und Einstellmöglichkeiten recht alt. Klar, man kann einer Textbox oder an einer Linie nicht mehr viel ändern, aber mich würde es doch mal sehr interessieren, wie man so etwas heutzutage hinbekommt.

    Vielen Dank

    Volker