Problem mit <DllImport("gdi32.dll")>

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

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

    Problem mit <DllImport("gdi32.dll")>

    Einen schönen guten Morgen,

    ich versuche gerade ein System.Drawing.Bitmap zu einer BitmapSource zu konvertieren und habe dieses Codeschnipsel gefunden:

    VB.NET-Quellcode

    1. Public Class Deck
    2. Public Function BitmapToBitmapSource(ByVal source As System.Drawing.Bitmap) As BitmapSource
    3. Dim bitSrc As BitmapSource = Nothing
    4. Dim hBitmap = source.GetHbitmap()
    5. Try
    6. bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions())
    7. Catch __unusedWin32Exception1__ As Win32Exception
    8. bitSrc = Nothing
    9. Finally
    10. NativeMethods.DeleteObject(hBitmap)
    11. End Try
    12. Return bitSrc
    13. End Function
    14. End Class
    15. Friend Module NativeMethods
    16. <DllImport("gdi32.dll")>
    17. <MarshalAs(UnmanagedType.Bool)>
    18. Friend Function DeleteObject(ByVal hObject As IntPtr) As Boolean
    19. End Function
    20. End Module


    Da unterstreicht er mir das MarshalAs in Zeile 20 rot mit dieser Meldunng:

    Das Attribut "MarshalAsAttribute" kann nicht auf "DeleteObject" angewendet werden, da das Attribut für diesen Deklarationstyp nicht gültig ist.

    Das Original-Codeschnipsel in C# sieht so aus:

    C#-Quellcode

    1. /// <summary>
    2. /// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
    3. /// </summary>
    4. /// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
    5. /// </remarks>
    6. /// <param name="source">The source bitmap.</param>
    7. /// <returns>A BitmapSource</returns>
    8. public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
    9. {
    10. BitmapSource bitSrc = null;
    11. var hBitmap = source.GetHbitmap();
    12. try
    13. {
    14. bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    15. hBitmap,
    16. IntPtr.Zero,
    17. Int32Rect.Empty,
    18. BitmapSizeOptions.FromEmptyOptions());
    19. }
    20. catch (Win32Exception)
    21. {
    22. bitSrc = null;
    23. }
    24. finally
    25. {
    26. NativeMethods.DeleteObject(hBitmap);
    27. }
    28. return bitSrc;
    29. }
    30. /// <summary>
    31. /// FxCop requires all Marshalled functions to be in a class called NativeMethods.
    32. /// </summary>
    33. internal static class NativeMethods
    34. {
    35. [DllImport("gdi32.dll")]
    36. [return: MarshalAs(UnmanagedType.Bool)]
    37. internal static extern bool DeleteObject(IntPtr hObject);
    38. }


    Ich gehe davon aus, dass das bloss ein Übersetzungsfehler ist, aber weiss jemand wie man das behebt?
    Ich denke du machst das falsch. Du hast ein System.Drawing.Bitmap, brauchst aber BitmapSource, bau dir einen Konverter(implementiere in einer Klasse IValueConverter), den Konverter gibst du dann auch im XAML an, wenn du die Source festlegst.

    NativeMethods eine Klasse draus machen, die Funktion DeleteObject machst du public shared.


    C#-Quellcode

    1. public class MyConverter : IValueConverter
    2. {
    3. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    4. {
    5. TypDerReinkommt rein = (TypDerReinkommt)value;
    6. TypeDerRausgeht raus = //bitmap zu BitmpaSource
    7. return raus;
    8. }
    9. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    10. {
    11. }
    12. }

    Siehe auch: (Binding über Converter)
    Tutorialreihe <WPF lernen/>
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    kafffee schrieb:

    Jou ist mir klar dass man da nen Konverter machen sollte, aber soweit bin ich noch nicht.


    Wie gesagt, mach aus NativeMethods eine Klasse, die Funktionen da drin public shared, fertig. Die Funtion BitmapToBitmapSource könnte man in irgendeine "Utils" Klasse auslagern, dann in einem Konverter verwenden.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    kafffee schrieb:

    Public Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As IntPtr) As Long


    Warum denn eine VB-6 Deklaration? Nach dazu as Long? Ey sachma.......
    learn.microsoft.com/en-us/wind…di/nf-wingdi-deleteobject

    Es reicht nicht hunderte von Codes einfach vom irgendwo zu kopieren und einzufügen und dabei zu beten das das gut geht. Wenn du schon so eifrig Kopierst und einfügst, such dir eine bessere Quelle, wenn du dich nicht mit ein wenig Hintergrund auseinander setzen willst. Hier NET(FX)-Konform:(Muss man dann halt als public deklarieren, wenn man von ausserhalb der Klasse dran will.
    pinvoke.net/default.aspx/gdi32.DeleteObject

    Wenn du hier nicht eine Klasse aus dem Modul machen kannst, die Funktionen mit den passenden Zugriffsmodifier einbauen kannst, stattdessen lieber irgendwo nach C&P Ready Code suchst, dann mit einer VB-Klassik Deklaration um die Ecke kommst, die nicht mal den richtigen Typ zurückgibt, lass ich dich lieber weiter suchen. Machst ja eh was du willst, da ist meine Hilfe ja Sinnlos.

    Du hättest lieber fragen sollen, wenn was unverständlich ist.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    ich fang nochma von vorne an. Also da scheint es ein Übersetzungs-Problem zu geben, nämlich diese c#-Zeile

    C#-Quellcode

    1. [return: MarshalAs(UnmanagedType.Bool)]

    Das ist ein Attribut, aber diesen return: - Prefix habich noch nie gesehen. Wahrscheinlich gibts das in vb garnet, und daher der Übersetzungs-Fehler.

    Wie du nun über Umwege herausgefunden hast, kann man das scheints auch einfach weglassen.
    Ich täte also bei der ursprünglichen Übersetzung bleiben - nur zeile#20 rauslöschen.

    Und ja: Besser wärs, du tätest den BestPractices folgen, und da ist NativMethods immer eine Klasse, - kein Modul.
    Zu beachten: Alle Methoden dieser Klasse sind Shared.


    Ansonsten von Convertern an dieser Stelle bin ich bisserl unüberzeugt.
    Umwandlung von Bildern ist üblicherweise ein teurer Prozess - da entsteht mw. aus einer Quelle von 12MB ein ebensogrosses BitmapImage.
    Da Converter aber andauernd konvertieren, werden da möglicherweise am laufenden Band Objekte erzeugt, die gleichma 12MB belegen.

    Ich hab da lieber eine Liste mit den BitmapImages drinne, die ich brauche. Da kann ich dran binden, so oft, und von wo aus ich will - es laufen keine weiteren speicher-intensiven Operationen ab.

    Meine Imagelist bezieht ihre Bilder übrigens einfach aus den Resourcen, oder aus Dateien.
    Eine Drawing.Bitmap umzuwandeln war mir noch nie nötig - System.Drawing ist doch aus der WinForms-Welt.

    DTF schrieb:

    Warum denn eine VB-6 Deklaration? Nach dazu as Long?


    Okay, dass es da nen Unterschied zu VB6 ist, wusste ich nicht. Macht das denn nen Unterschied, abgesehen von der Syntax? Ehrlich gesagt find ich da die VB6-Version schöner und übersichtlicher, ohne die ganzen "<>"... Aber ich lass mich gern eines besseren belehren...

    DTF schrieb:

    Wenn du hier nicht eine Klasse aus dem Modul machen kannst, die Funktionen mit den passenden Zugriffsmodifier einbauen kannst, stattdessen lieber irgendwo nach C&P Ready Code suchst, dann mit einer VB-Klassik Deklaration um die Ecke kommst, die nicht mal den richtigen Typ zurückgibt, lass ich dich lieber weiter suchen. Machst ja eh was du willst, da ist meine Hilfe ja Sinnlos.


    Also ich weiss nicht wie du drauf kommst, dass ich das nicht gemacht hätte, bzw. dass ich sogar zu blöd dafür bin. Denn ich habe das gemacht! Hatte das ursprüngliche Problem, nämlich ein Syntaxproblem aber nicht gelöst.

    DTF schrieb:

    Du hättest lieber fragen sollen, wenn was unverständlich ist.


    Hab ich doch gemacht mit diesem Post...?

    ErfinderDesRades schrieb:

    Ich täte also bei der ursprünglichen Übersetzung bleiben - nur zeile#20 rauslöschen.


    Nope das funtktioniert so nicht... Entweder so wie in @DTFs Link oder die VB6 Schreibweise...

    ErfinderDesRades schrieb:

    Ich hab da lieber eine Liste mit den BitmapImages drinne, die ich brauche

    Bei mir nicht möglich. Es geht um eine dynamisch erzeugte WaveForm (so ne Art Visualisierung eines Audiotracks).
    Leider stellt mir die bass.dll nur diese Funktion zur verfügung, und das eben als System.Drawing.Bitmap...

    kafffee schrieb:

    Also ich weiss nicht wie du drauf kommst, dass ich das nicht gemacht hätte, bzw. dass ich sogar zu blöd dafür bin. Denn ich habe das gemacht!


    Aha! Dann hättest du auch diesen Code posten können und meckern: Hey, hab ich gemacht, was ist da nun nicht richtig? Spätestens dann wäre mir aufgefallen, das ich was nicht erwähnt hab. Wenn in der Doku RückgabeTyp bool steht, brauchste kein MarshalAs Attribute für den RückgabeTypen wenn du den gleichen Typ verwendest.

    Willst du den RückgabeTyp Marshal'n geht das so, aber wie gesagt, hier nicht notwendig.

    VB.NET-Quellcode

    1. <DllImport("gdi32.dll")>
    2. Public Shared Function DeleteObject(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    3. End Function



    Nunja egal, nächtes mal schau bei Pinvoke.net nach den Deklarationen für Windows API Funktionen. Dort findest du für fast alle/bzw. die gängisgten Funktionen die Deklaration und mehr.(Benutzerdefiniertes, Konstanten, teils auch Beispiele, etc....)

    Wenn du nun dieses eine Bild das du immer von der Bassnet bekommst nur einmal verwendest, kannste zum Konverter greifen, aber sobald es mehrfach verwendet werden soll, muss es dort wo es gebraucht wird erneut konvertiert werden, da kann man durchaus ressourcen und RAM sparen, indem man das ohne Konverter macht und auf das bereits konvertierte weiterhin zugreifen kann. Gut in Zeiten wo 8GB und mehr Ram durchschnitt sind, kommts nicht auf ein paar MB an, aber die Masse machts.

    kafffee schrieb:

    Okay, dass es da nen Unterschied zu VB6 ist, wusste ich nicht. Macht das denn nen Unterschied, abgesehen von der Syntax? Ehrlich gesagt find ich da die VB6-Version schöner und übersichtlicher, ohne die ganzen "<>"... Aber ich lass mich gern eines besseren belehren...


    Was der Compiler anschliessend draus macht habe ich nie verglichen, aber du arbeitest mit Net(FX) dann mach es einfach NET-Konform. Auch habe ich oft alte VB-Klassik Deklarationen gesehen, wo Typen nicht stimmen. Muss kein Drama sein, aber kann Exceptions auslösen. Gut die "richtige" Variante schützt dich nicht davor, aber da habe ich solche Fehler seltener gesehen, pinvoke.net ist jedensfalls eine Seite die du dir merken solltest, bei google pinvoke.net <name_der_funktion> rein und schon solltest du fündig werden.

    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“ ()

    @kafffee

    kafffee schrieb:

    Okay, dass es da nen Unterschied zu VB6 ist, wusste ich nicht. Macht das denn nen Unterschied, abgesehen von der Syntax? Ehrlich gesagt find ich da die VB6-Version schöner und übersichtlicher, ohne die ganzen "<>"... Aber ich lass mich gern eines besseren belehren...

    Da gibt es eine ganze Menge Unterschiede zwischen VB6 und NET. Ein VB6 Long ist ein 32bit Datentyp, in NET ist ein Long ein 64bit Datentyp. Ein C++ BOOL ist <> Boolean. Daher in NET das MarshalAs. Spielt aber kaum eine Rolle da alles was <> 0 = True ist. Bitmap.GetHBitmap hat ein Problem mit (P)ARGB Bildern. Der Alphakanal geht dabei verloren. Hmm, BitmapSource. Klingt ganz nach WIC (IWICBitmapSource). Ach ja, WPF nutzt ja WIC. ;) WIC bietet bessere Alternativen als von einem hBitmap ein WIC-Bitmap (WPF) zu erstellen. Zum Beispiel IWICImagingFactory::CreateBitmapFromMemory -> IWICBitmap <- inherits from IWICBitmapSource. Da wird WPF sicher eine vergleichbare Funktion bieten um eine WinForms-Bitmap (GDI+) in ein WPF-Bitmap (WIC) zu konvertieren.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „-Franky-“ ()

    klar gibts viele Unterschiede zw. vb6 und .net.
    Aber hier gehts um die Form der Com-InterOp-Deklaration, und ob es da Funktionale Unterschiede gibt, oder nur zwei Schreibweisen für inhaltlich dasselbe sind.
    Und da denke ich letzteres.
    Mir sieht auch die vb6-Schreibe intuitiver aus als das <DllImport>-Attribute, aber wegen common-use würde ich mich doch des letzteren dienen.
    Und nu weiss ich auch, wie man des komische return: MarshallAs-Attribut richtig übersetzt.
    Davon unbenommen sollte man natürlich den richtigen Datentyp nehmen, und dazu muss man natürlcih wissen, dass was in vb6 Long genannt wird, in .net ein Integer ist.

    ErfinderDesRades schrieb:

    Davon unbenommen sollte man natürlich den richtigen Datentyp nehmen, und dazu muss man natürlcih wissen, dass was in vb6 Long genannt wird, in .net ein Integer ist.


    Den richtigen Datentyp braucht man, ja, aber man muss sich nicht an den VB6-Dingern orientieren, ich habe Kafffee schon merhmals gesagt einmal in die C++ Doku schauen, sehr oft ist dann klar, welchen Typ man braucht.

    C-Quellcode

    1. BOOL DeleteObject(
    2. [in] HGDIOBJ ho
    3. );

    Haben 2 Typen, BOOL sollte geläufig sein, HGDIOBJ ist ein Handle von einem GDI-Object, für Handles nimmt man IntPtr in NET. Das ist kein Hexenwerk, wenn man denn die richtige Signatur kennt.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    ErfinderDesRades schrieb:

    Und nu weiss ich auch, wie man des komische return: MarshallAs-Attribut richtig übersetzt.

    Intuitiv würde ich sagen das [return: MarshalAs(UnmanagedType.Bool)] angibt, wie der Return der API zu marshallen ist -> ...) As <MarshalAs(UnmanagedType.Bool)> ... Das dürfte dann Syntaktischer Zucker in C# sein, wenn VB dieses Attribut eventuell nicht kennt (ungetestet).
    Mfg -Franky-

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

    Wenn wir uns hier einmal den Bereich "Attribute Target" anschauen:(nur C#)
    learn.microsoft.com/de-de/dotn…eflection-and-attributes/

    Return target:
    return value of a method, property indexer, or get property accessor


    Dann schauen wir hier:(C# und VB)
    learn.microsoft.com/en-us/dotn…t-7.0&redirectedfrom=MSDN
    Man sieht in den Beispielen, wie man dieses MarshalAs Attribut bei einem Funktionsparameter, einem Feld einer Klasse, sowie auch auf den Returnwert anwendet. Schaltet man auf VB um auf der Seite, kommt genau sowas, wie ich oben zeigte.


    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“ ()

    Jo - könnte man mal ein schönes Tutorial drüber schreiben:
    Wo finde ich die c++-doku, wie sind die syntaktischen Feinheiten zu verstehen und zu übersetzen, was ist eigentlich "marshallen", was sind die Gefahren dieser (darf man sagen:) unmanaged Vorgehensweise, ...
    Ich zumindest tu mich damit schwer - ständig stosse ich auf geheimnisvolle Syntax-Elemente (bedeutet [in] in vn.net ByVal?). Und mal kenne ich die Datentypen, meist aber nicht, aber zum Glück ist BlaBlaXY oft einfach ein IntPtr, aber zum Pech ist das oft genug aber auch eine Structure, die erstmal nachgebaut werden will, und oft auch derbe kompliziert.

    ErfinderDesRades schrieb:

    bedeutet [in] in vn.net ByVal?

    Nicht immer. Kann auch ByRef sein (z.B. bei Strukturen, aber auch hier nicht immer). Daher ist es wichtig die MS Doku genau zu lesen.

    ErfinderDesRades schrieb:

    oft auch derbe kompliziert

    Wie ich immer sage: Kompliziert ist relativ. Die einen können es, die anderen tun sich schwer aber versuchen es und andere verweigern es sich mit der Materie zu beschäftigen. ;)
    Mfg -Franky-

    ErfinderDesRades schrieb:

    bedeutet [in] in vn.net ByVal?


    [in] bedeutet das der Parameter nach dem hereingeben nicht verändert wird, es wird also der reingehende Wert nur verwendet.
    [out] bedeutet das der Parameter nach der reingabe verändert wird
    [in][out] bedeutet das der Parameter nachdem reingehen verwendet wird, wie auch verändert.

    Beim out und in/out muss man bei den Funktionen genau die Doku lesen, kommt schon mal vor das null rein muss!

    Ich habe mal Beispiele gemacht, eine C++ DLL mit je einer Funktion für in, out und in/out. Dazu eine Winforms App in der die DLL verwendet wird.

    Beim [in] sollte ByVal eigendlich immer passen ( @-Franky- wo musstest du da was als ByRef geben, wenn es mit [in] gekennzeichnet war, kannst du dich da dran gerade erinnern? Würde das gerne genauer anschauen)
    Beim [out] wird das ja verändert, also brauchen wir die referenz, ebenso beim [in][out].

    Um das nun selbst zu testen, müsst ihr das Projekt InOutEx(Die Dll) erstellen, die DLL in den Ausgabeordner des Projektes InOutEx.App kopieren/verschieben, danach könnt ihr die WinForms-App starten und die Debugausgabe lesen.

    Ich denke, die Funktionen reichen hier aus, wer mehr will -> Anhang, ist aber nur das Default Zeug.

    C-Quellcode

    1. EXPORT int InExample(_In_ int a)
    2. {
    3. return a * a;
    4. }
    5. EXPORT int OutExample(_Out_ int& a)
    6. {
    7. a = 10;
    8. return a * a;
    9. }
    10. EXPORT int InOutExample(_In_ _Out_ int& a)
    11. {
    12. a = a * a;
    13. return a * 10;
    14. }


    VB.NET-Quellcode

    1. <DllImport("InOutEx.dll")>
    2. Private Shared Function InExample(ByVal a As Integer) As Integer
    3. End Function
    4. <DllImport("InOutEx.dll")>
    5. Private Shared Function OutExample(ByRef a As Integer) As Integer
    6. End Function
    7. <DllImport("InOutEx.dll")>
    8. Private Shared Function InOutExample(ByRef a As Integer) As Integer
    9. End Function

    Dateien
    • Example.zip

      (11,64 kB, 106 mal heruntergeladen, zuletzt: )
    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“ ()

    DTF schrieb:

    Beim [out] wird das ja verändert, also brauchen wir die referenz
    Da hab ich jetzt n Einspruch oder ne Verständnisrückfrage.
    Ich habe heute die Funktion PrivateExtractIcons zum Laufen gebracht - nach vielen Anläufen. Ein Stolperstein war, dass ich - eben weil mit out in der Doku - den 5. Parameter (ein IntPtr-Array (hat auch gedauert, bis ich das rausgefunden habe)) ByRef übergeben habe. Da kam es zu Problemen, weil versucht wurde, im geschützten Speicher zu lesen oder zu schreiben. Erst als ich das ByRef entfernt und das Array (implizit per) ByVal übergeben hatte, funktionierte es. Ist das jetzt Einspruch oder Verständisproblem meinerseits?
    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.
    Einspruch abgelehnt! Denke ich mal, zumindest vorerst. Ich denke ein verständnissproblem.

    Wenn du ein Array von Intptrs via ref reingibt kanns bei dieser Funktion nur rappeln, weil du bekommst keinen Array direkt, sondern einen Pointer zu dem Array(von Handles), was ein einzelner IntPtr ist, daher kann nicht geschrieben werden und das wird mit einer Zugriffsverletzungsausnahme quittiert. Weshalb das ohne ref geht, wenn du direkt einen Array reingibst, kann ich noch nicht nachvollziehen. Werde ich in den nächsten Tagen mal versuchen heraus zubekommen.

    ByVal heist ja es geht nicht die Referenz sondern der Wert rein, da kann ja eigendlich nicht die Referenz verändert werden, nur der Wert, das hat aber keinen Einfluss auf die Referenz bwz. dessen Wert. Das verwirrt mich gerade ein wenig.

    Nimmst du einen IntPtr, gibt diesen via ref rein kann dieser "Pointer" beschrieben werden. Hab dir dazu ein Beispiel gemacht, Code sagt manchmal mehr als einfache Worte; Es wird ein Icon extrahiert und das erste als Hintergrundbild des Forms gesetzt.

    C#-Quellcode

    1. [DllImport("User32.dll")]
    2. private static extern uint PrivateExtractIcons(string filename, int nIconIndex, int cxIcon, int cyIcon, ref IntPtr phicon, uint piconid, uint nIcons, uint flags);
    3. private void button1_Click(object sender, EventArgs e)
    4. {
    5. string filename = "F:\\Icons\\empty.ico";
    6. IntPtr ptr = IntPtr.Zero;
    7. //bei Icons (*.ico)
    8. uint iconsCount = PrivateExtractIcons(filename, 0, 0, 0, ref ptr, 0, 0, 0);
    9. //bei exe/dll z.B.
    10. //uint iconsCount = PrivateExtractIcons(filename, 0, 0, 0, ref ptr, 0, 1, 0);
    11. //um zu zeigen wie man auf die einzelnen Indexe zugreift, ein sinnloser Loop
    12. for (int i = 0; i < iconsCount; i++)
    13. {
    14. IntPtr inArrPtr = new IntPtr((ptr.ToInt64() + i * IntPtr.Size));
    15. if (i == 0)
    16. {
    17. Icon ico = Icon.FromHandle(inArrPtr);
    18. BackgroundImage = ico.ToBitmap();
    19. }
    20. }
    21. }


    Ergebnis im Anhang.

    PS.
    @VaporiZed würdest du mir deine Deklaration zeigen?
    Bilder
    • Unbenannt.png

      64 kB, 830×510, 77 mal angesehen
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    DTF schrieb:

    @-Franky- wo musstest du da was als ByRef geben, wenn es mit [in] gekennzeichnet war, kannst du dich da dran gerade erinnern?

    Nehmen wir mal als Bsp die API OleCreatePictureIndirect.

    WINOLECTLAPI OleCreatePictureIndirect(
    [in] LPPICTDESC lpPictDesc,
    [in] REFIID riid,
    [in] BOOL fOwn,
    [out] LPVOID *lplpvObj
    );

    Hier wird eine PICTDESC-Struktur und eine IID-Struktur übergeben. PICTDESC wird hier ByRef übergeben da mit LP (LongPointer) gekennzeichnet ist. Klar könnte man auch erst dem Pointer der Struktur holen und diesen ByVal übergeben. Geht in VB6 per VarPtr. In NET gibt es VarPtr aber nicht. Die Struktur IID wird ebenfalls ByRef übergeben. Dafür steht REF (Referenz) vor IID.
    Mfg -Franky-

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