IPicure/Disp in Icon
-
Hallo,
ich habe hier ein IPicture/Disp aus einem COM Objekt erhalten und möchte dieses nun einer ImageList hinzufügen. Im Netz finde ich hierzu nun folgendes:
public new static Image GetPictureFromIPicture(object picture) { return System.Windows.Forms.AxHost.GetPictureFromIPicture(picture); }
Nur leider endet das in der Fehlermeldung "Das Objekt des Typs System.Drawing.Icon kann nicht in Typ System.Drawing.Image umgewandelt werden.". Das ist natürlich irgendwie klar, da GetPictureFromIPicture ein Image zurückgeben will und ein Icon eben kein Image ist. Aber was mache ich jetzt am Besten?
-
Schau mal ob das Icon die Methode "ToBitmap()" hat, das könnte helfen.
-
Das Problem ist ja leider, dass ich diese Methode nicht habe. IPicture ist ein COM Objekt, das innerhalb von AxHost.GetPictureFromIPicture in ein Drawing.Icon konvertiert wird. Da das aber innerhalb passiert, kann ich dessen ToBitmap nicht aufrufen.
-
?? Du kannst doch das Ergebnis von GetPictureFromIPicture beeinflussen ?!
// Nur Pseuso
public new static Image GetPictureFromIPicture(object picture) { var icon = System.Windows.Forms.AxHost.GetPictureFromIPicture(picture); return icon.ToBitmap(); }
-
Es kommt doch aber gar kein Ergebnis, da GetPictureFromIPicture eine InvalidCastException wirft. Hätte ich ein Ergebnis gehabt, hätte ich ToBitmap längst aufgerufen.
-
Glücklicherweise kann man ein Icon ja auch aus einem HICON erstellen. Jetzt mache ich das erstmal so, scheint zu funktionieren:
public new static Image GetPictureFromIPicture(object picture) { try { return System.Windows.Forms.AxHost.GetPictureFromIPicture(picture); } catch (InvalidCastException) { Type t = picture.GetType(); IntPtr handle = (IntPtr)(Int32)t.InvokeMember("Handle", System.Reflection.BindingFlags.GetProperty, null, picture, null); return Icon.FromHandle(handle).ToBitmap(); } }
-
Oh man
Speicher doch das Ergebnis erstmal in eine Variable die von diesem Typen ist, und DANN kannst du das Ergebnis entsprechend bearbeiten.Keiner zwingt dich das du direkt ein return der Methode machst.
Wenn du das Ergebnis der Methode in eine Variable des selben Type speichern läßt, dann gibt es auch kein Invalid Cast
Was du da machst ist total schlechter und dreckiger Code.
-
CSL schrieb:
Oh man
Speicher doch das Ergebnis erstmal in eine Variable die von diesem Typen ist, und DANN kannst du das Ergebnis entsprechend bearbeiten.ES GIBT KEIN ERGEBNIS!
// InvalidCastException object o = System.Windows.Forms.AxHost.GetPictureFromIPicture(picture);
-
Dann ruf doch diese Methode gar nicht erst auf, sondern geh gleich den richtigen Weg.
-
CSL schrieb:
Dann ruf doch diese Methode gar nicht erst auf, sondern geh gleich den richtigen Weg.
Welches ist der richtige Weg?
-
Signatur ändern von
public new static Image GetPictureFromIPicture(object picture)
zu
public new static Image GetPictureFromIPicture(IPicture picture)
public new static Image GetPictureFromIPicture(IPicture picture) { return System.Windows.Forms.AxHost.GetPictureFromIPicture(picture); }
Wenn deine Methode ein IPicture erwartet, muss es das auch gegeben werden
Andere Objekte bekommen andere Methoden:public new static Image GetPictureFromHandle(object picture) { Type t = picture.GetType(); IntPtr handle = (IntPtr)(Int32)t.InvokeMember("Handle", System.Reflection.BindingFlags.GetProperty, null, picture, null); return Icon.FromHandle(handle).ToBitmap(); }
Kannst dir dann eine Helfsmethode bauen:
public new static Image GetPicture(object picture) { var iPicture = picture as IPicture; if (iPicture != null) return GetPictureFromIPicture(iPicture); else return GetPictureFromHandle(picture); }
Exceptions sind dafür da Fehlerfälle ab zu fangen, wenn bekannt ist das "picture" an der stelle auch mal kein "IPicture" sein kann, dann sollte man das beachten.
Man arbeitet nicht mit Try & Catch im normalen Programmablauf, diese sollten nur Fehlerfälle abfangen.Anm.d.R.: GetPicture ist eigentlich Falsch, du möchtest ja ein Image, also währe GetImageFrom passender
PS. das die Exception innerhalb der aufgerufenen Methode System.Windows.Forms.AxHost.GetPictureFromIPicture geworfen wird, hattest du nicht erwähnt, daher die Verwirrung, ich nahm an das der Return nicht mit der Signatur übereinstimmt. Sorry wenn ich etwas ruppig antwortete.
-
CSL schrieb:
Exceptions sind dafür da Fehlerfälle ab zu fangen, wenn bekannt ist das "picture" an der stelle auch mal kein "IPicture" sein kann, dann sollte man das beachten.
Es ist ein IPicture, immer! Ein IPicture kann Bitmaps enthalten, aber eben auch Icons und MetaFiles. In meinem Fall ist nun eben ein Icon.
CSL schrieb:
Man arbeitet nicht mit Try & Catch im normalen Programmablauf, diese sollten nur Fehlerfälle abfangen.
Ich mache das jetzt aber. In meine Augen ist es eher ein Fehler der Implemetierung von AxHost.GetPictureFromIPicture. Denn wenn der interne Cast nicht funktioniert, ist es wohl ein Leichtes, ToBitmap des Icon-Objektes aufzurufen. Und das ein Icon-Objekt bereits existiert, sagt die Exception eindeutig aus. Wer weiß, vielleichtg wird das ja irgendwann einmal nachgerüstet.
Und ja, mir ist bekannt, dass IPicture auch ein Type-Property bereithält. Aber Late-Bound Calls sind ja nun irgendwie auch nicht so der Bringer...
Aber das die Exception innerhalb von AxHost.GetPictureFromIPicture geworfen wird, hatte ich erwähnt. Jendenfalls bilde ich mir das ein.
-
Man könnte auch einfach ne Bitmap erzeugen und das IPicture mittels Render-Methode da rein zeichnen lassen, dann kann einem auch egal sein wass da nun fürn Typ drin ist...
-
Schon mal probiert über den COM
IPicture
Typ zu gehen? Wenn mich nicht alles täuscht, müsstest du das Interface zuerst selber erstellen:[GuidAttribute("7BF80980-BF32-101A-8BBB-00AA00300CAB")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] public interface IPicture
Dann alle Methoden implementieren:
http://msdn.microsoft.com/en-us/library/ms680761.aspxAm Ende hast du dann eine Methode
get_Handle
. Die sollte dir dasHICON
alsIntPtr
zurückgeben, sofern dieseIPicture
auf einHICON
verweist. MitBitmap.FromHICON
kannst du dir dann ein Bitmap erstellen.Ich weiss, da fehlen noch ein paar Informationen, allerdings müsste ich die selber zuerst noch in der MSDN nachschlagen gehen. Aber als Lösungsansatz dürfte dies reichen. Ob es wirklich funktionieren wird, kann ich aber nicht sagen, selber gemacht habe ich es noch nicht.
Grüssli
-
geeky schrieb:
Man könnte auch einfach ne Bitmap erzeugen und das IPicture mittels Render-Methode da rein zeichnen lassen, dann kann einem auch egal sein wass da nun fürn Typ drin ist...
Verliere ich dann aber nicht die Transparenz?
-
Dravere schrieb:
Schon mal probiert über den COM
IPicture
Typ zu gehen? Wenn mich nicht alles täuscht, müsstest du das Interface zuerst selber erstellen:Das ist genau das, was ich hier habe. Das Picture implementiert sowohl IPicture als auch IPictureDisp und ich habe das auch selbst implementiert (allerdings in C++).
Dravere schrieb:
[GuidAttribute("7BF80980-BF32-101A-8BBB-00AA00300CAB")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] public interface IPicture
Das ist so nicht ganz richtig. Für InterfaceIsIDispatch muss es 7BF80981-BF32-101A-8BBB-00AA00300CAB heissen, also IPicutreDisp. Oder Du änderst den Type auf InterfaceIsIUnknown.
Dravere schrieb:
Am Ende hast du dann eine Methode
get_Handle
. Die sollte dir dasHICON
alsIntPtr
zurückDas ist ein Property, keine Methode. Und genau dieses Property frage ich eben auch ab.
Dravere schrieb:
Mit
Bitmap.FromHICON
kannst du dir dann ein Bitmap erstellen.Und das mache ich nicht, diese Methode habe ich nämlich gänzlich übersehen. Da kann ich mir ja den Umweg über Icon schöne sparen. Cool, danke.