none
Problem mit eingebettetem OCX (MsFlexGrid) RRS feed

  • Frage

  • Hallo,

    ich habe ein Problem mit einer von VB6 nach .NET migrierten Anwendung. Zur Anzeige von berichten wird in dieser Anwendung das MsFlexGrid-OCX verwendet. Das MsFlexGrid ist in ein User-Control eingebettet, von welchem weitere berichtsspezifische User-Controls abgeleitet sind. Die Anzeige der Berichte erfolgt  in einem Formular welches die Auswahl eines spezifischen Berichts über Tab-Reiter ermöglicht. Auf jeder TabPage befindet sich ein User-Control mit dem eingebetteten MsFlexGrid-OCX. Prinzipiell funktioniert das ganz gut. Wenn jedoch im Formular nicht alle Tab-Reiter ausgewählt wurden wirft die Runtime beim Schließen des Formulars eine TargetInvocationException mit dem Hinweis dass fensterlose Controls nicht unterstützt werden. Da dieser Hinweis einen Bezug zum MsFlexGrid OCX hat geht meine Vermutung dahin, dass das OCX erst dann ein Fenster-Handle erzeugt, wenn es auf dem Bildschirm sichtbar wird. Hier der Stacktrace:

    System.Reflection.TargetInvocationException: Der Fensterhandle für das Steuerelement AxMSFlexGrid konnte nicht abgerufen werden. Fensterlose ActiveX-Steuerelemente werden nicht unterstützt. ---> System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
       bei System.Windows.Forms.AxHost.DoVerb(Int32 verb)
       bei System.Windows.Forms.AxHost.MakeVisibleWithShow()
       --- Ende der internen Ausnahmestapelüberwachung ---
       bei System.Windows.Forms.AxHost.MakeVisibleWithShow()
       bei System.Windows.Forms.AxHost.OnContainerVisibleChanged(Object sender, EventArgs e)
       bei System.Windows.Forms.Control.OnVisibleChanged(EventArgs e)
       bei System.Windows.Forms.ScrollableControl.OnVisibleChanged(EventArgs e)
       bei System.Windows.Forms.Control.WmShowWindow(Message& m)
       bei System.Windows.Forms.Control.WndProc(Message& m)
       bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       bei System.Windows.Forms.ContainerControl.WndProc(Message& m)
       bei System.Windows.Forms.UserControl.WndProc(Message& m)
       bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)



    Ich habe versucht, diese Exception im Close-Event des Formulars abzufangen. Damit habe ich aber lediglich erreicht, dass die Exception später (nämlich beim Aufruf der Dispose() Methode durch den Garbage-Collector) auftritt. Dieses Verhalten tritt nur dann auf, wenn die Anwendung direkt ausgeführt wird. Läuft sie unter Kontrolle des Visual-Studio Debuggers, wird die Exception nur als First-Chance-Exception im Output-Fenster angezeigt.

    Wir sind zwar dabei, das OCX durch ein anderes Control zu ersetzen, müssen aber bis Anfang nächste Woche eine Version der Anwendung ausliefern und haben bis dahin die Umstellung noch nicht beendet. Hat jemand eine Idee, wie das beschrieben Problem umgangen werden kann?

    Vielen Dank im Voraus
    Andreas Seibt
    • Verschoben Robert BreitenhoferModerator Donnerstag, 10. Juni 2010 12:21 VB6 Interop und Upgrade (aus:Visual Basic (ab Version 2002 / .NET))
    Donnerstag, 3. September 2009 06:10

Antworten

  • Hi Andreas,
    bei Betrieb des DataGridView kannst du problemlos jede Zelle einzeln formatieren. Hier mal eine kleine Demo:

    Option Infer On ' Only VB9
    Option Strict On
    
    Public Class Form1
    
      Private WithEvents dgv As New DataGridView With {.Dock = DockStyle.Fill}
    
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {dgv})
        dgv.DataSource = (From tz In TimeZoneInfo.GetSystemTimeZones).ToList
        dgv.AutoResizeColumns()
      End Sub
    
      Private Sub dgv_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgv.CellFormatting
        If (e.ColumnIndex + e.RowIndex) Mod 5 = 0 Then
          e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        End If
      End Sub
    
    End Class
    Das geht auch weiter über Font, Farben usw.

    Im virtuellen Modus kannst du dann noch mehr Möglichkeiten.

    --
    Peter
    Donnerstag, 3. September 2009 13:47

Alle Antworten

  • Hi Andreas,
    ich würde anstelle des MsFlexGrid sofort das DataGridView im ungebundenen oder virtuellen Modus nutzen. Da ist fast keine Anpassung erforderlich. Beim MSHFlexGrid wäre es etwas komplzierter.

    Wenn das nicht möglich ist, dann würde ich die Instanzierung des AxMSFlexGrid auf der Tabpage erst beim Erhalt des Focus der Tabpage durchführen.

    --
    Peter
    Donnerstag, 3. September 2009 11:53
  • Danke für die schnelle Antwort.

    Leider ist weder die eine noch die andere Lösung schnell machbar. Das DataGridView-Control können wir nicht verwenden, da es nicht alle Formatierungsmöglichkeiten des MsFlexGrid hat (so habe ich z.B. keine Möglichkeit gefunden einzelne Zellen rechts- bzw. linksbündig zu formatieren). Da die beiden Berichtsformulare der Anwendung jeweils über 20 Tab-Reiter haben, ist auch die zweite Lösung mit einigem Codierungsaufwand verbunden. Mittlerweile haben wir begonnen, da MsFlexGrid auf das Farpoint Spread Control umzustellen (unter anderem, weil die Berichte nach Excel exportiert werden müssen was mit diesem Control durch ein einfaches SaveToExcel() erledigt ist). Da ich sowohl für die Aufbereitung der Berichte als auch für die User-Controls eine Klassenhierarchie erstellt habe hält sich der Aufwand in Grenzen. Mittlerweile bin ich guter Dinge, dass die Umstellung bis morgen abgeschlossen ist und ich meinen Termin einhalten kann.

    Gruß
    Andreas

    Donnerstag, 3. September 2009 12:27
  • Hi Andreas,
    bei Betrieb des DataGridView kannst du problemlos jede Zelle einzeln formatieren. Hier mal eine kleine Demo:

    Option Infer On ' Only VB9
    Option Strict On
    
    Public Class Form1
    
      Private WithEvents dgv As New DataGridView With {.Dock = DockStyle.Fill}
    
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {dgv})
        dgv.DataSource = (From tz In TimeZoneInfo.GetSystemTimeZones).ToList
        dgv.AutoResizeColumns()
      End Sub
    
      Private Sub dgv_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgv.CellFormatting
        If (e.ColumnIndex + e.RowIndex) Mod 5 = 0 Then
          e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        End If
      End Sub
    
    End Class
    Das geht auch weiter über Font, Farben usw.

    Im virtuellen Modus kannst du dann noch mehr Möglichkeiten.

    --
    Peter
    Donnerstag, 3. September 2009 13:47
  • Hallo Andreas,

    Hat Dir die Antwort geholfen?

    Grüße,
    Robert

    Sonntag, 13. September 2009 18:16
    Moderator
  • Hallo Andreas,

    Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert

    Montag, 21. September 2009 19:02
    Moderator