Fonte/ Codesnippets | | | | - Page 1 - |
| Jörg Sellmeyer | Ich hab jetzt via Ole (Dank an Andreas Miethe - immer wieder) ein funktionierendes Handle per Bitmaps (auch gif, ico und diverse andere Formate) ermitteln können, das dann ganz normal auf einem Bitmapstatic angezeigt werden kann. Mit der Ermittlung der Dimensione kann ich mich in dem Fall noch nicht ganz anfreunden. Wer da eine Idee hat - im Code ist die Stelle markiert.
Hier jedenfalls erstmal der Code, um ein gültiges Handle auch per grande Bilder zu erhalten. Wenn man es im Programm häufiger verwendet, ist es sicher sinnvoller, die Init-Routine nur einmal am Anfang aufzurufen, aber so funktioniert es schon mal klaglos. Bitte mal mit File größer als 5100 Pixeln testen. Aktuell habe ich es nur mit jpg und gif probiert. Icos sind ja größenmäßig nicht das Problem.
$H windows.ph
'Konstanten
DEF &Picture_Release 8
DEF &Picture_GetHandle 12
DEF &Picture_GetType 20
DEF &Picture_Get_Width 24
DEF &Picture_Get_Height 28
DEF &Picture_Render 32
DEF &Picture_Select 44
'Globale Variablen
DECLARE IID_IPicture#
DECLARE PData#
DECLARE HMEM&
Declare OlePic#
Class OleImage = OleImage@,\
Ole_Init@,\
Ole_Free@,\
Ole_LoadImage@,\
Ole_GetType@,\
Ole_GetHandle@,\
Ole_FreeImage@,\
OLE32&,\
OLEPro32&,\
PictureObject&,\
hPic&,\
PicFormat&,\
Width&,\
Height&,\
GetSize@,\
Destroy@
Proc OleImage.OleImage
Parameters File$
.Ole_Init()
.PictureObject& = .Ole_LoadImage(File$)
.PicFormat& = .Ole_GetType(.PictureObject&)
.hPic& = .Ole_GetHandle()
Print .PictureObject&,.PicFormat&,.hpic&
EndProc
Proc OleImage.Ole_Init
.OLE32& = UseDll("OLE32")
.OLEPRO32& = UseDll("OLEPRO32")
External("OLE32","OleInitialize",0)
Dim IID_IPicture#,16
Long IID_IPicture#,0 = $7BF80980
Word IID_IPicture#,4 = $BF32
Word IID_IPicture#,6 = $101A
Byte IID_IPicture#,8 = $8B
Byte IID_IPicture#,9 = $BB
Byte IID_IPicture#,10 = $00
Byte IID_IPicture#,11 = $AA
Byte IID_IPicture#,12 = $00
Byte IID_IPicture#,13 = $30
Byte IID_IPicture#,14 = $0C
Byte IID_IPicture#,15 = $AB
EndProc
Proc OleImage.Ole_Free
~GlobalFree(Hmem&)
External("OLE32","OleUninitialize")
FreeDll .OLE32&
FreeDll .OLEPRO32&
DISPOSE IID_IPicture#
EndProc
Proc OleImage.Ole_LoadImage
Declare MemPointer&,PStream&,PictureObject&,PSize&
Parameters Picture$
'------------------------
Set("Filemode", 0)
PSIZE& = Filesize(Picture$)
Dim PData#,PSIZE&
BlockRead(Picture$,PData#,0,PSIZE&)'Daten in Bereichsvariable einlesen
'------------------------
~GlobalFree(Hmem&)
HMem& = ~GlobalAlloc($022,PSize&)'Speicher reservieren
Mempointer& = ~GlobalLock(Hmem&)'Pointer auf Speicher
~RtlMoveMemory(MemPointer&,PData#,PSize&)'Bereichsvariable in Speicher schieben
DISPOSE PData#'Bereichsvariable freigeben
~GlobalUnlock(HMem&)'Speicher zum Gebrauch freigeben
External("Ole32","CreateStreamOnHGlobal",Hmem&,1,addr(PStream&))'Stream-Pointer erstellen
External("OlePro32","OleLoadPicture",PStream&,PSIZE&,0,IID_IPicture#,ADDR(PictureObject&))'Pointer fuer Pictureobject
'------------------------
Case PictureObject& > 0 : Return PictureObject&
Case PictureObject& = 0 : Return 0
EndProc
Proc OleImage.Ole_GetType
Declare Command&,PicFormat&
Command& = Long(.PictureObject&,0)
Call(@Long(Command&,&Picture_GetType),.PictureObject&,addr(PicFormat&))
Return PicFormat&
EndProc
Proc OleImage.GetSize
Parameters DC&
Declare Command&,w&,h&,xpixels&,ypixels&
Command& = Long(.PictureObject&,0)
'hier wird die Bildschirmauflösung pro Zoll abgefragt - bei mir 96x96.
'Allerdings weiß ich nicht, welche Funktion in welcher dll da angesprochen wird.
Call(@Long(Command&,&Picture_Get_Width),.PictureObject&,addr(w&))
Call(@Long(Command&,&Picture_Get_Height),.PictureObject&,addr(h&))
'die Dimensione des Fensters wird ermittelt
xpixels& = ~GetDeviceCaps(DC&, 88)
ypixels& = ~GetDeviceCaps(DC&, 90)
'Umrechnung der Bildschirmauflösung auf die Fenstergröße.
'Ich hab allerdings keine Ahnung, wie der Wert 2540 zustande kommt.
.Width& = Round((w&*xpixels&)/2540,0)
.Height& = Round((h&*ypixels&)/2540,0)
EndProc
Proc OleImage.Ole_GetHandle
Declare Command&,PicHandle&
Command& = Long(.PictureObject&,0)
Call(@Long(Command&,&Picture_GetHandle),.PictureObject&,addr(PicHandle&))
Return PicHandle&
EndProc
Proc OleImage.Ole_FreeImage
Parameters PictureObject&
Declare Command&
Command& = Long(PictureObject&,0)
Call(@Long(Command&,&Picture_Release),PictureObject&)
EndProc
Proc OleImage.Destroy
DeleteObject .hPic&,.PictureObject&
.Ole_Free()
EndProc
Declare hbtn&,Bild$,hFont&,Anzeige&,OleAnzeige&,TestHandle&
UserMessages $10
~SetWindowLong(%hwnd,~GWL_STYLE,(~GetWindowLong(%hwnd,~GWL_STYLE) | $300000))
Window %maxx,%maxy
WindowTitle "Handle per OLE"
hFont& = Create("Font","Western ",14,0,0,0,0)
SetDialogFont hFont&
hbtn& = Create("Button",%hwnd,"Bild laden",%maxx-80,40,60,24)
WhileNot %key = 27'ESC beendet das Programm
If GetText$(%hwnd) <> "Handle per OLE"
WaitInput 4000
WindowTitle "Handle per OLE"
ShowWindow(hbtn&,5)
EndIf
WaitInput
Case %uMessage = $10:Break
If Clicked(hbtn&)
Bild$ = LoadFile$("ÖFFNE","alle unterstützten Formate|*.dib;*.bmp;*.rle;*.jpe;*.jpeg;*.jpg;*.gif;*.ico;*.cur;*.emf;*.wmf|\
Bitmap (bmp,rle,dib)|*.bmp;*.rle;*.dib|Jpeg (jpg,jpe,jpeg)|*.jpg;*.jpe;*.jpeg|Gif (gif)|*.gif|\
Enhanced Metafile (emf)|*.emf|Metafile (wmf)|*.wmf|Icons (Ico)|*.ico|Cursor (cur)|*.cur")
If Bild$ > ""
TestHandle& = Create("hPic",-1,Bild$)
'bei grande Bildern ist hier das Ergebnis 0
WindowTitle Str$(TestHandle&) + " Bei sehr grande Bildern ist das Ergebnis hier 0"
DeleteObject TestHandle&
If SizeOf(OlePic#)
DestroyWindow(OleAnzeige&)
OlePic#.Destroy()
Dispose OlePic#
EndIf
OlePic# = New(OleImage,Bild$)
If Anzeige&
DestroyWindow(Anzeige&)
waitinput
Cls
EndIf
With OlePic#
'die Handleermittlung via Ole bringt ein verwertbares Handle:
OlePic#.GetSize(%hdc2)
Print .Width&,.Height&,"Typ:",.Ole_GetType()
If .PicFormat& = 1
OleAnzeige& = Create("Bitmap",%hwnd,.hPic&,0,0)
.GetSize(%hdc2)
Print .Width&,OlePic#.Height&
ElseIf .PicFormat& = 3
Print "Icon ist Typ:",.PicFormat&,"und kann schneller mit Profanmitteln angezeigt werden."
EndIf
EndWith
EndIf
EndIf
Wend
If SizeOf(OlePic#)
OlePic#.Destroy()
Dispose OlePic#
EndIf
DeleteObject hFont&
End
Basierend auf diesem Code [...] von Andreas Methe |
| | | Windows XP SP2 XProfan X4... und hier mal was ganz anderes als Profan ... | 03.06.2020 ▲ |
| |
| | | | - Page 2 - |
| | Jörg Sellmeyer | Leider lässt du uns im Unklaren, mit welchem Code du das Bild geladen hast. Bei mir zumindest ist es mit dem Code von Matthias - also mit rein profanen Mitteln - nicht ladbar. Das è, es wird nicht angezeigt und es wird auch kein Handle erzeugt, sondern hPic& ist 0.
Mit meinem Code (mit Ole) dagegen gibt es ein gültiges Handle und das Bild wird angezeigt. Es wird naturalmente nur ein kleiner Ausschnitt angezeigt, weil der Code auch nichts weiter vorsieht.
Sollte es am zu geringen Speicher liegen, ist es ja trotzdem offensichtlich, dass die Ole-Methode die bessere ist, da die ja dann auf meinem System (mit zu wenig Speicher) funktioniert, während Create("hPic",...) da versagt. |
| | | | |
| | Matthias Arlt | 64k-Grenze wäre vielleicht ein Erklärungsversuch. Zu wenig Speicher eher nicht, ich habe aktuell 2.5GB RAM.
Jörg Sellmeyer (10.06.2020)
Sollte es am zu geringen Speicher liegen, ist es ja trotzdem offensichtlich, dass die Ole-Methode die bessere ist, da die ja dann auf meinem System (mit zu wenig Speicher) funktioniert, während Create("hPic",...) da versagt.
Das sehe ich auch so. Trotzdem wäre interessant, ob es am Speicherausbau des Rechners hängt, was ich wie gesagt eher nicht annehme, oder an der Speicherbitmap von Profan. Letzeres kann wohl nur Roland sicher beantworten. Bisher hat ja dieses Problem nicht zur Diskussion gestanden. Wohl weil es no aufgefallen ist...wann hat man schon mal solch Riesenbild. |
| | | WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia | 10.06.2020 ▲ |
| |
| | Jörg Sellmeyer | In einer Auflösung von 300 dpi kneift Profan da schon viel früher. Wenn man etwas Grafikbearbeitung macht, ist man schnell bei solchen Größen. Bisher habe ich per die Anzeige solcher Bilder immer ein Create("HTMLWin", H, S, N, X, Y, DX, DY). Da muss man dann aber bei der Ermittlung der Maße immer wieder auf andere, nichtprofane Mittel zurückgreifen, was Zeit kostet und lästig ist. Außerdem will ich eigentlich nur ungern ein Element vom Internetexplorer in mein Programm integrieren. Ein weiterer Vorteil von dem HTMLWin ist übrigens noch die problemlose Nutzung als scrollbares Element. Das ist in Profan bisher auch nur suboptimal gelöst. |
| | | Windows XP SP2 XProfan X4... und hier mal was ganz anderes als Profan ... | 11.06.2020 ▲ |
| |
| | Matthias Arlt | Jörg Sellmeyer (11.06.2020)
Außerdem will ich eigentlich nur ungern ein Element vom Internetexplorer in mein Programm integrieren.
Kann ich gut nachvollziehen...
Hier mal noch eine etwas schlankere Variante...
declare hBtn&,Pic$,GDIP_DLL&,GDPS#,GdipStatus&,PicObject&,hPic&,PicWidth&,PicHeight&,hdc&,bmp&,wChar$
GDIP_DLL& = UseDLL("GDIPLUS.DLL")
window 0,0-%maxx,%maxy
hBtn&=create("BUTTON",%hwnd,"Bild...",20,20,60,22)
proc LoadImageFile
parameters Pic$
dim GDPS#,16
long GDPS#,0 = 1
long GDPS#,4 = 0
long GDPS#,8 = 0
long GDPS#,12 = 0
external("GDIPLUS.DLL","GdiplusStartup",addr(GdipStatus&),GDPS#,0)
dispose GDPS#
wChar$ = space$((len(Pic$)*2)+1)
external("KERNEL32","MultiByteToWideChar",0,0,addr(Pic$),-1,addr(wChar$),len(wChar$)+1)
external("GDIPLUS.DLL","GdipLoadImageFromFile",addr(wChar$),addr(PicObject&))
external("GDIPLUS.DLL","GdipCreateHBITMAPFromBitmap",PicObject&,addr(hPic&),0)
external("GDIPLUS.DLL","GdipGetImageWidth",PicObject&,addr(PicWidth&))
external("GDIPLUS.DLL","GdipGetImageHeight",PicObject&,addr(PicHeight&))
hdc& = external("GDI32","CreateCompatibleDC",0)
bmp& = external("GDI32","CreateCompatibleBitmap",%hdc,PicWidth&,PicHeight&)
external("GDI32","SelectObject",hdc&,hPic&)
external("GDI32","BitBlt",%hdc,0,0,width(%hwnd),height(%hwnd),hdc&,0,0,$CC0020)
external("GDI32","BitBlt",%hdc2,0,0,width(%hwnd),height(%hwnd),hdc&,0,0,$CC0020)
external("GDI32","DeleteObject",bmp&)
external("GDI32","DeleteDC",hdc&)
external("GDIPLUS.DLL","GdipDisposeImage",PicObject&)
external("GDIPLUS.DLL","GdiplusShutdown",GdipStatus&)
endproc
while 1
waitinput
if clicked(hBtn&)
Pic$=LoadFile$("Bild laden...","*.*")
if FileExists(pic$)
UseCursor 2
LoadImageFile(Pic$)
UseCursor 0
endif
endif
wend
FreeDLL GDIP_DLL&
end
Es scheint also definitiv an der Speicherbitmap von Profan zu liegen, denn mit Workarround per API funtioniert es ja. |
| | | WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia | 11.06.2020 ▲ |
| |
| | RGH | Ich habe gerade mal nachgeschaut: Die XProfan-Befehle und -Funktionen, die Bilder aus File laden (MLoadBmp, DrawPic, DrawSizedPic und Create("hPic",...)), nutzen eine OLE-Routine, die an Andreas' Code angelehnt ist. Hier sollte es keine Probleme mit grande Bitmaps geben. Ich muss das mal näher überprüfen.
(Das gilt nicht per FreeProfan, da ich FreePascal noch nicht mit OLE-Objekten verheiraten konnte.)
Saluto Roland |
| | | XProfan X4Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 11.06.2020 ▲ |
| |
| | RGH | Ach ja: zu negativen Handles: In Windows sind die Handles unsigned Integer (ohne Vorzeichen). Der Wertebereich geht also von 0 bis etwas circa 4 Milliarden. Die Handles und Integer in XProfan sind signed Integer (mit Vorzeichen) mit einem Wertebereich von - 2 Milliarden bis + 2 Milliarden. Windows-Handles, die circa 2147483647 liegen, werden daher negativ dargestellt, was aber nichts an ihrer Funktion ändert. Handles kleiner als 0 sind also ebenso gültig.
Saluto Roland |
| | | XProfan X4Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 11.06.2020 ▲ |
| |
| | RGH | Gerade getestet: Mit Matthias' Code (reines XProfan) konnte ich meine größten Bilder (16 MPixel, Dateigröße circa 6 MB) problemlos laden. Größere Bilder habe ich nicht. Ich benutze meine aktuelle XProfan-Version.
Nachtrag: Und auch das oben verlinkte Afrika-Bild macht in höchster Auflösung (75 MPixel) keine Probleme.
Saluto Roland |
| | | Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 11.06.2020 ▲ |
| |
| | Matthias Arlt | Ich hatte mit 11.2 getestet und Jörg vmtl. mit X4. Dann scheinen da wohl noch andere Faktoren eine Rolle zu spielen...nur welche? Mir war das ja auch noch nie aufgefallen, da ich solch grande Bilder eben auch nicht habe. Ach ja...wenn FreeProfan und OLE sich nicht so recht mögen...meine "schlankere" API-Variante kommt ja ganz ohne OLE aus. |
| | | WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia | 11.06.2020 ▲ |
| |
| | Jörg Sellmeyer | RGH (11.06.2020)
Ich habe gerade mal nachgeschaut: Die XProfan-Befehle und -Funktionen, die Bilder aus File laden (MLoadBmp, DrawPic, DrawSizedPic und Create("hPic",...)), nutzen eine OLE-Routine, die an Andreas' Code angelehnt ist. Hier sollte es keine Probleme mit grande Bitmaps geben. Ich muss das mal näher überprüfen.
(Das gilt nicht per FreeProfan, da ich FreePascal noch nicht mit OLE-Objekten verheiraten konnte.)
Saluto Roland
RGH
Nachtrag: Und auch das oben verlinkte Afrika-Bild macht in höchster Auflösung (75 MPixel) keine Probleme.
Da frage ich mich aber, warum das bei mir nicht funktioniert. Ich hab zwar noch XP mit 2GB Ram aber mit meiner Variante von Andreas' Code funktioniert es ja, also kann es nicht generell am Speicher oder der Windowsversion liegen. Vielleicht kannst du nochmal schauen, was da die Unterschiede in deiner Version zu meiner sind. Der verschlankte Code von Matthias funktioniert bei mir übrigens auch nicht.
Außerdem fällt mir auf, dass Matthias print verwendet, um das Bild zu verarbeiten. Das wird in meinem Code vermieden, sondern nur durch Speicherschiebereien das Handle ermittelt. |
| | | Windows XP SP2 XProfan X4... und hier mal was ganz anderes als Profan ... | 11.06.2020 ▲ |
| |
| | Matthias Arlt | @Jörg Ich habe hier auf diesem PC ja auch XP SP2 drauf. Nachdem nun Roland keine Probleme beim Laden des Bildes hatte, hab ich das Ganze mal schnell in einem virtuellen Win 7 probiert. Und siehe da...dort gibt es auch kein Problem!
Wenn sich nun der profaninterne Code lt. Roland an das OLE-Prozedere von Andreas anlehnt, muß es aber doch Unterschiede geben, denn extern funtioniert es ja mittels OLE.
Das print in meinem Code steht dort eigentlich nur, weil ich das Handle angezeigt bekommen wollte. Warum aber diese API-Variante, die eigentlich nur GDI(+)-Funktionen nutzt, bei Dir nicht geht, ist mir nun wieder ein Rätsel.
Mysteriös...aber immerhin einen Schritt weiter... |
| | | WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia | 11.06.2020 ▲ |
| |
| | Jörg Sellmeyer | Ich habs jetzt auch auf nem Laptop mit Win7 und 4GB Ram getestet und es funktioniert mit deinem Code. Das erklärt aber immer noch nicht, warum es bei mir mit meinem Code auch auf mkeinem minderbemittelten Rechner funktioniert aber nicht mit deinem Code. |
| | | | |
| | Matthias Arlt | Das ist ja das Mysterium...
GDI+ sollte bei XP ja standardmäßig vorhanden sein. Das ist es also vmtl. nicht. Du könntest vlt. mal die Rückgabewerte schrittweise per jeden Funktionsaufruf ansehen. Eventuell führt das etwas weiter !?
Festhalten können wir jedenfalls, daß sich create("hPic" unter XP (und wohl nur dort) bei Bildern von annähernd 8000x8000 untypisch verhält. Kein Problem, wenn man das weiß oder solche Bilder nicht hat.
Den folgenden Passus kannst Du auch aus der OLE-Variante entfernen:
TestHandle& = Create("hPic",-1,Bild$) WindowTitle Str$(TestHandle&) + " Bei sehr grande Bildern ist das Ergebnis hier 0" DeleteObject TestHandle&
OLE kommt ohne ihn aus und necessario ihn nicht (systemunabhängig). Deshalb ist er dort m.E. auch nicht hilfreich (und stiftet vlt. Verwirrung). |
| | | WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia | 11.06.2020 ▲ |
| |
|
Zum QuelltextThemeninformationenDieses Thema hat 4 subscriber: |