SCROLLINFO wie wird das eingebunden

  • VB.NET

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von -Franky-.

    SCROLLINFO wie wird das eingebunden

    Hi,

    Ich benötige informationen über den Range einer VSCROLLBAR.

    Bisher habe ich das mit

    VB.NET-Quellcode

    1. <DllImport("user32.dll")>
    2. Public Shared Function GetScrollRange(ByVal hWnd As IntPtr,
    3. ByVal nBar As Integer,
    4. ByRef lpMinPos As IntPtr,
    5. ByRef lpMaxPos As IntPtr) As Boolean
    6. End Function


    erledigt. Jetzt lese ich aber: The GetScrollRange function is provided for compatibility only. New applications should use the GetScrollInfo function.

    Also würde ich gern GetScrollInfo verwenden. Die Signatur lautet wohl:

    VB.NET-Quellcode

    1. <DllImport("user32.dll")>
    2. Public Shared Function GetScrollInfo(ByVal hWnd As IntPtr,
    3. ByVal nBar As Integer,
    4. ByRef lpsi As LPSCROLLINFO) As Boolean
    5. End Function


    Das Problem ist jetzt, dass ich nicht weiß, woher ich die Structur (Klasse) SCROLLINFO bekomme. Ich will das ungern "per Hand" zusammenfummeln. Weiß jemand wie das geht ? Das sollte doch ohne großes "Install" möglich sein ... denn es dürfte sich tatsächlich nur um eine handvoll Felder handeln.

    LG
    Peter
    @Peter329 Mit pinvoke GetScrollInfo kommst Du zur gewünschten Information:
    pinvoke.net/default.aspx/user32.getscrollinfo
    Du musst das nur noch nach VB überesetzen, aber das kannst Du ja inzwischen.
    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!

    RodFromGermany schrieb:

    Du musst das nur noch nach VB überesetzen
    Gibbet auch bei PInvoke: Link.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke erstmal ... das hatte ich gesucht ... und irgendwie nicht gefunden.

    Jetzt hab ich das versucht in .Net zu realisieren. Dabei habe ich ein Problem

    SCROLLINFO.cbSize wird als UInteger verlangt ... und da muss die Länge der SCROLLINFO eingestellt werden. Im Sample Code wird da offensichtlich mit Strict Off gearbeitet ... ich habe das dann wie folgt versucht:

    VB.NET-Quellcode

    1. si.cbSize = CUInt(Len(si))


    Das scheitert zur Laufzeit: System.ArgumentException: 'Die Datei-E/A einer Struktur mit dem Feld cbSize des Typs UInt32 ist ungültig.'

    Wie mache ich das denn richtig ?

    LG
    Peter
    Bilder
    • s 2023-03-11 15-41-538.jpg

      112,83 kB, 1.192×827, 40 mal angesehen
    @Peter329 Poste mal den betreffenden Code: Deklaration, Befüllung, Aufruf.
    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!
    @RFG: Hier der Code wie im Screenshot Anhang:

    VB.NET-Quellcode

    1. Public Enum ScrollInfoMask As UInteger
    2. SIF_RANGE = &H1
    3. SIF_PAGE = &H22
    4. SIF_POS = &H4
    5. SIF_DISABLENOSCROLL = &H88
    6. SIF_TRACKPOS = &H10
    7. SIF_ALL = (SIF_RANGE Or SIF_PAGE Or SIF_POS Or SIF_TRACKPOS)
    8. End Enum
    9. Public Enum SBOrientation As Integer
    10. SB_HORZ = &H0
    11. SB_VERT = &H1
    12. SB_CTL = &H2
    13. SB_BOTH = &H3
    14. End Enum
    15. <Serializable, StructLayout(LayoutKind.Sequential)>
    16. Structure SCROLLINFO
    17. Public cbSize As UInteger
    18. <MarshalAs(UnmanagedType.U4)> Public fMask As ScrollInfoMask
    19. Public nMin As Integer
    20. Public nMax As Integer
    21. Public nPage As UInteger
    22. Public nPos As Integer
    23. Public nTrackPos As Integer
    24. End Structure
    25. Dim si As New SCROLLINFO
    26. <DllImport("user32.dll")>
    27. Public Shared Function GetScrollInfo(ByVal hWnd As IntPtr,
    28. ByVal nBar As Integer,
    29. ByRef si As SCROLLINFO) As Boolean
    30. End Function
    31. Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
    32. With si
    33. .cbSize = CUInt(Len(si)) '<-- das scheitert zur Laufzeit
    34. .fMask = ScrollInfoMask.SIF_RANGE
    35. End With
    36. Dim retval1 = GetScrollInfo(TextBox1.Handle, SB_VERT, si)
    37. End Sub


    @DTF: also das mit dem "Marshal SizeOf" klingt mir sehr vielversprechend. Irgendwie scheint man dem Modul ein Integer als UInteger (oder umgekehrt) unterzujubeln müssen. Leider kann ich deinen Hinweis nicht umsetzen - da fehlen mir wohl die notwendigen Kenntnisse ...

    [Edit]

    Ich glaube, ich hab's herausgefunden:

    VB.NET-Quellcode

    1. .cbSize = CUInt(Marshal.SizeOf(si))


    Ich verstehe zwar offen gestanden nicht so ganz, was ich da treibe, aber es scheint zu funktionieren ! :)

    LG
    Peter

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Peter329“ ()

    DTF schrieb:

    Siehe:
    learn.microsoft.com/de-de/dotn…rshal.sizeof?view=net-7.0


    learn.microsoft.com/de-de/dotn…rshal.sizeof?view=net-7.0

    Peter329 schrieb:

    @DTF: also das mit dem "Marshal SizeOf" klingt mir sehr vielversrprechend. Irgendwie scheint man dem Modul ein Integer als UInteger (oder umgekehrt) unterzujubeln müssen. Leider kann ich deinen Hinweis nicht umsetzen - da fehlen mir wohl die notwendigen Kenntnisse ...




    Warum nicht entweder casten oder einfach die API Funktion ändern(Parameter uint zu int)? Solange ein positiver Wert reingeht der die gleiche Bitbreite hat, kein Problem.

    C#-Quellcode

    1. struct MyStruct
    2. {
    3. int a;
    4. int b;
    5. }
    6. private void Form1_Load(object sender, EventArgs e)
    7. {
    8. MyStruct myStruct = new MyStruct();
    9. Debug.WriteLine(Marshal.SizeOf(myStruct));
    10. Debug.WriteLine((uint)Marshal.SizeOf(myStruct));
    11. }




    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „DTF“ ()

    @Peter329 Im C#-Code über dem VB-Code in PInvoke steht es richtig. Die VB-Codes in PInvoke sind öfters etwas unterbelichtet, da lohnt es sich, den C#-Code zu nehmen und zu übersetzen.
    Und:
    Das mit dem UInteger bei der Länge von Strukturen ist nicht so streng zu nehmen, da Marshal.SizeOf() ein Integer zurück bringt.
    Ändere da einfach die Deklaration in Integer. ;)
    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!

    RodFromGermany schrieb:

    da lohnt es sich, den C#-Code zu nehmen und zu übersetzen.


    Noch mehr lohnt es sich, einfach im C++ Bereich bei MS nachzuschauen und auf Basis der dortigen Informationen die Funktion selbst runter zu tippen(Kenntnisse von Typen aber erforderlich). Hat den Vorteil das man auch weitere Infos bekommt, was denn zurückkommt, was zu beachten ist etc. etc....
    Auch die Infos zu den Flags für die Funktionen sind nicht immer bei Pinvoke kommentiert. Daher finde ich, das der C++ Bereich bei MS sinnvoller als Pinvoke.net ist.(Auch wenn man dort ellenlange Strukturen oder Enums einfach kopieren kann)
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Mein Problem ist gelöst. Das ist die gute Nachricht. Trotzdem würde ich jetzt die Lösung auch noch gern VERSTEHEN! :)

    Also: an dem UInteger liegt die Problematik wohl nicht. Da die Länge der Struktur gerade mal 28 Bytes beträgt spielt der Unterschied zwischen Integer und UInteger keine Rolle ... das VorzeichenBit ist in jedem Fall 0 und kommt damit gar nicht zum Tragen ... Wenn ich also die Struktur dahingehend abändere

    VB.NET-Quellcode

    1. Structure SCROLLINFO
    2. 'Public cbSize As UInteger
    3. Public cbSize As Integer


    dann kann ich mir das CUint() sparen.

    VB.NET-Quellcode

    1. With si
    2. '.cbSize = CUInt(Marshal.SizeOf(si))
    3. .cbSize = Marshal.SizeOf(si)


    Nur die Sache mit dem Marshal und dem SizeOf muss ich beibehalten. Denn

    VB.NET-Quellcode

    1. .cbSize = Len(si)


    liefert wieder den Laufzeitfehler.

    Mit Marshal kann ich nur SizeOf verwenden ... Len wird in diesem Zusammenhang nicht unterstützt.

    Kann mir jemand nachsichtig erklären, warum ich hier zwingend mit Marshal.SizeOf() arbeiten muss ? Wieso braucht es Marshal ? Warum funktioniert Len() nicht. Und was hat es mit dem Laufzeitfehler auf sich ?

    Die Microsoft Doku enthält bezügllich Marshal.SizeOf einen kryptischen Verweis, den ich leider nicht verstehe.

    LG
    Peter
    Der VB6-Befehl Len kommt einfach nicht mit Structures mit UInteger-Bestandteilen klar und kann den gewünschten Wert nicht ermitteln.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo @Peter329

    hoffe ich erzähl jetzt keinen Quatsch, aber ist es nicht so dass
    Marschall immer im Zusammenhang mit unmanaged code verwendet wird ?
    Also alles was sich außerhalb der dotNet Libs befindet.

    ​The size of the specified object in unmanaged code


    Hatte deinen Fall noch nicht, obwohl ich eine Zeit lang sehr viel mit den API rumgespielt hatte - lang ist es her.

    Würde die ganzen VB6 Befehle sowieso nicht verwenden - nimm den Verweis darauf am Besten raus.
    (Geht das überhaupt ? Oh mein Gott wie lange hab ich nicht mehr in VB programmiert !?!)

    GRuss

    mikeb69
    Exakt, sobald unmanged ins Spiel kommt, braucht man oft den Marshal der für Recht und Ordnung sorgt, ohne kippt der Stapel schon mal recht flott(StackImbalance). Gibt so einige Fälle wo man Marshal'n muss. Ein weiteres Beispiel wären Arrays mit bestimmter Länge, dann kommt MarshalAs ins Spiel mit SizeConst . Gibt auch noch viele viele weitere Sachen, wie z.B. Strukturen mit Unions(braucht man die Offsets), oder wenn man nur einen Pointer zu einer Struktur bekommt, oder einen Pointer zu einer Struktur braucht( Marshal.PtrToStructure und umgekehrt). Oder wenn ein Boolean 4 Bytes groß ist(ja es gibt solche Fälle), das muss man schon bekannt machen, "Hey das'n bool, aber der besteht aus 4 Bytes". Gibt aber noch so einiges mehr. Jedenfalls lohnt es sich damit zu befassen, wenn man oft mit der WInAPI oder C/C++ Dlls in Net arbeitet.

    @Peter329
    Mit dem aktuellen Studio bekomme ich eine Fehlermeldung wenn ich Len verwende.
    System.ArgumentException: "File I/O of a structure with field 'cbSize' of type 'UInt32' is not valid."
    System.ArgumentException: "Die Datei-E/A einer Struktur mit dem Feld cbSize des Typs UInt32 ist ungültig."
    Sowohl mit FW 4.8 wie auch NET 6.

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    Mit dem aktuellen Studio bekomme ich eine Fehlermeldung wenn ich Len verwende.

    Absolut richtig und das wird sich auch nicht ändern. Der Fehler ist praktisch gewollt, aber das hat VaporiZed im Grunde ja schon geschrieben. Len ist eine alte VB6-Style Methode und in VB6 gab es keine unsigned Datentypen.

    Bluespide schrieb:

    und in VB6 gab es keine unsigned Datentypen.
    Der Fehler kommt allein durch Verwendung des Len()-Befehls ohne Verbindung mit einem Size-Element oder einer UInteger-Variable.

    Ich denke mal, dass dieser Fehler hart an den Len()-Befehl gekoppelt ist, und erst ab Studio 2017 oder 2019 auftritt.
    Kann das mal jemand mit einem 2010er VB-Studio verifizieren?
    ====
    Moin @mikeb69 , schön, wieder mal was von Dir zu hören.
    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!
    Vielen Dank für eure Antworten.

    Dass Len() eine VB6 Funktion ist, kam mir gar nicht in den Sinn. Ich hatte si.Length versucht aber das ist nicht verfügbar. So kam ich aus Verzweiflung auf Len() ... aber diese Frage ziehe ich jetzt natürlich zurück ! :)

    Damit bleibt noch die Sache mit dem "Marshall" ... auch nach einigem Suchen in den MS docs bin ich da nicht so recht schlau geworden. Es scheint mehrere Arten von "Marshalling" zu geben, z.B. Interop Marshalling ... und es soll Einfluss haben "how data is passed in method arguments and return values between managed and unmanaged memory".

    Also offen gestanden verstehe ich nur Bahnhof ... welche Unterschiede in der Parameterübergabe, was ist "managed" und "unmanaged" Speicher ... und warum brauche ich so etwas für eine vergleichsweise "harmlose" Funktion wie "SizeOf" ... Klar ... da muss der belegte Speicher von SCROLLINFO ermittelt werden ... aber das sollte doch nicht gar so kompliziert sein. Also von Hand kann ich die 7 * 4 = 28 Bytes auch abzählen. :)

    Ich hoffe, ihr seht es mir nach, wenn ich so hartnäckig nachfrage ... aber ich habe halt ein ungutes Gefühl, wenn ich Konstrukte verwende, ohne die geringste Ahnung zu haben, was die bewirken.

    Wie mir scheint, gibt es SizeOf nur als Funktion innerhalb von Marshal ... und dieses Konstrukt muss man verwenden, wenn man auf die Länge von nicht-Standard DatenTypen zugreifen will. Warum auch immer das so ist.

    LG
    Peter

    Peter329 schrieb:

    was ist "managed" und "unmanaged" Speicher
    Managed Speicher wurde von .NET bereitgestellt und wird vom Garbage Collector verwaltet.
    Unmanaged Speicher wird in nativen DLLs per alloc() und free() oder so bereitgestellt.
    .NET hat da keinen restriktiven Zugriff zu.
    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!

    RodFromGermany schrieb:

    Der Fehler kommt allein durch Verwendung des Len()-Befehls ohne Verbindung mit einem Size-Element oder einer UInteger-Variable. […]
    Ich denke mal, dass dieser Fehler hart an den Len()-Befehl gekoppelt ist
    Kann ich so nicht verifizieren, siehe Video.

    ##########

    Peter329 schrieb:

    warum brauche ich so etwas für eine vergleichsweise "harmlose" Funktion wie "SizeOf" ... Klar ... da muss der belegte Speicher von SCROLLINFO ermittelt werden ... aber das sollte doch nicht gar so kompliziert sein. Also von Hand kann ich die 7 * 4 = 28 Bytes auch abzählen.

    Peter329 schrieb:

    Wie mir scheint, gibt es SizeOf nur als Funktion innerhalb von Marshal ... und dieses Konstrukt muss man verwenden, wenn man auf die Länge von nicht-Standard DatenTypen zugreifen will. Warum auch immer das so ist.
    Frage selbst erfolgreich beantwortet ;)
    Ich versuch das mal als C++-LaieUnwissender zu erklären: Wenn ich z.B. in DirectX Datenpakete geben oder entgegennehmen will, musste ich erst eine Größenangabe übergeben, wieviel Platz die Daten beanspruchen, wahrscheinlich, weil ein entsprechender Speicherplatz dann gesucht und reserviert wurde, um dann die gewünschten oder gesendeten Daten dort reinzustecken. Daher wird solch eine Größenangabe häufiger gebraucht, wenn man im "unmanaged-Bereich" unterwegs ist. Daher ist die Funktion SizeOf einfach in der Marshal-Klasse drinne. Wenn Du eine andere Funktion findest oder erstellst, die es hinbekommt, die benötigte Größe einer UInt32-haltigen Structure und aller anderen Sachen zu berechnen, könntest Du die aber genausogut verwenden.
    Bilder
    • Len with UInt32 In Structure.gif

      257,62 kB, 624×384, 59 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

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