View Full Version : byref parameter
largo_winch
03-11-2011, 17:48
anybody can help to fix this example? do you get any errors or this example is running well?
uses at own risk:
' Empty GUI script created on 11-03-2011 16:21:37 by (ThinAIR)
Uses "console"
Declare Function GdipGetImageEncodersSize Lib "GDIPLUS.DLL" Alias "GdipGetImageEncodersSize" ( _
ByRef numEncoders As Long _ 'DWord
, ByRef lSize As Long _ 'DWord
) As Long
Dim vx As Long
Dim tx As Long
vx = 10
tx = 20
'---------------> error ----------------->
PrintL GdipGetImageEncodersSize(vx,tx)
'---------------> error ----------------->
WaitKey
'Expected a parameter passed BYREF but found something else.
here's a problem with "ntdll.dll" and this example isn't working fine.
bye, largo
Petr Schreiber
03-11-2011, 19:28
As the documentation of GDIPlus says, before using the library functions you need to call GdiplusStartup. I think this is why your example fails, because according to my tests with such a call it works as expected.
On more serious note, regarding "your" headers (posted in your other GDI+ related recent threads)
Issue #1:
They seem to me ripped off José Roca headers, especially because I can see some PB syntax in declarations (alignment in types, ...), original C declares in comments exactly like José does.
It would be very polite to cite the sources in comment on the beginning of the file. José does all the conversions with enormous precision manually and spends a lot of time on it.
Many of the functions are just Ctrl-C, Ctrl-V from PB, for example GdiPlusGetEncoderClsid2, where I can see PowerBASIC @ pointer syntax, which is something not present in ThinBASIC.
Issue #2:
Many of the parameter names, such as:
ByVal Bitmap As DWord
for example in GdipBitmapSetPixel will collide with ThinBASIC keywords, if it is highlighted, better to change it to something else (for example Bitmap -> pBitmap)
The example code you post lately seems to me again mostly translation of work of José, again citation of original version would be on place.
Thanks for understanding,
Petr
largo_winch
03-11-2011, 20:21
http://www.thinbasic.com/community/showthread.php?11433-thinbasic-gdiplus-experiments
hello petr. thanks for your reply! I have added a notice to my first gdip translation for thinbasic and credits to jose's website and headers. I've collected various sources (have noticed that in one of my post, I am sure) and therefore I have different issues for "gdipplus" include files for thinbasic. I know about these problems with colliding with tb commands/syntax and powerbasic language, but I was able to convert some example they are working very well.
I haven't background to convert all perfect, I am learning by doing. But I wanted to search a middle golden way for adepting powerbasic code (that I didn't know very well) to thinbasic. I was surprised how equal a lot of commands looks like! But there were a lot of commands they didn't work. Example for converting BMP into PNG with my "gdiplus_lw1a.inc" failed because of pointers and GUID's. I tried to separate different code parts to see where are the main problems. but that's not easy after some hours of exploring gdiplus headers from jose roca (he did a great job I know, I know! :) ).
I will explore and know more about these differences between powerbasic + thinbasic and my aim is to convert all examples for thinbasic about gdiplus topics.
btw: my problem remains with error. but I know there are commands they aren't working with current thinbasic issue. But I don't know what's all possible with Thinbasic power and therefore I ask here at board.
' Empty GUI script created on 11-03-2011 16:21:37 by (ThinAIR)
Uses "console", "ui"
'---------------------------->
#INCLUDE "GDIPLUS_LW1a.INC"
'---------------------------->
Dim vx, tx As Long
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
vx = 10
tx = 20
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
'---------------> error ----------------->
'PrintL GdipGetImageEncodersSize(vx, tx)
'---------------> error ----------------->
' Shutdown GDI+
GdiplusShutdown token
End Function
MsgBox 0, "end of example"
WaitKey
This is only a code part of another gdiplus example ("Converting BMP", see below). I can show a lot of other translation copy's of my work but that will cause trouble or confusion. I will proof closer what's possible and making more tests. I like that converting work.
only an experimental code part "converting bmp":
'------------------->
Sub convertingBMP()
'------------------->
Local hLib, hLib1 As Long
Local token As DWord
Local EncoderClsid As Guid
Local pImage As DWord
Local eps As EncoderParameters
Local ep As EncoderParameter
Local nWidth As DWord
Local nHeight As DWord
Local transformation As DWord
Local strFileName As String
Local hStatus As Long
Local s1 As String = Guid$
Local s2 As String = GuidTxt$(s1)
MsgBox 0, s2
hLib = LoadLibrary("Oleaut32.dll")
MsgBox 0, Str$(hLib)
' hLib1 = LoadLibrary("ntdll.dll")
' MsgBox 0, Str$(hLib1)
's1="image/png"
'Guid$={00000000-0000-0000-0000-000000000000}
strFileName = Ucode$("Metallica1.bmp")
'------------> Problemzone 1) ------------------------------->
'hStatus = GdipLoadImageFromFile(StrPtr(strFileName), pImage)
'------------> Problemzone 1) ------------------------------->
Encoderclsid = Guid$(s1)
MsgBox 0, "here's begin of converting_Bmp Sub"
' // Get the CLSID of the PNG encoder.
'------------> Problemzone 2) ------------------------------->
'a)
'EncoderClsid = Guid$(GdiPlusGetEncoderClsid("image/png"))
'b)
'EncoderClsid = Guid$(GdiPlusGetEncoderClsid(s1) )
'------------> Problemzone 2) ------------------------------->
' // Save the image.
strFileName = Ucode$("Metallica1.png")
'------------> Problemzone 3) ------------------------------->
'hStatus = GdipSaveImageToFile(pImage, StrPtr(strFileName), EncoderClsid, 0) 'ByVal %NULL
'------------> Problemzone 3) ------------------------------->
If hStatus = %StatusOk Then
PrintL "Shapes.png saved successfully"
Else
PrintL "Attempt to save Shapes.png failed"
End If
' // Cleanup
If pImage Then GdipDisposeImage(pImage)
' // Shutdown GDI+
GdiplusShutdown token
MsgBox 0, "here's end of converting_Bmp Sub"
End Sub
thanks for feedback, petr. I agree in most parts with you. but what would you recommend (for example) translation pointer problems to thinbasic ? last not least, I don't give, I like thinbasic! I know you are a very good programmer and you know my problems for converting code in general.
bye, largo
Petr Schreiber
03-11-2011, 20:49
Hi Largo,
the problem is you probably accidentaly misunderstood the program flow in the first case - it waits for keypress in the beginning, instead of the end.
Why? Because ThinBASIC, as documented, first executes global space and then jumps to TBMain, which means the order of execution is:
Uses "console", "ui"
#INCLUDE "GDIPLUS_LW1a.INC"
Dim vx, tx As Long
MsgBox 0, "end of example"
Waitkey ' -- Here it makes you think program does nothing
TBMain()
The working code listing for #1 is this:
Uses "console", "ui"
'---------------------------->
#INCLUDE "GDIPLUS_LW1a.INC"
'---------------------------->
Dim vx, tx As Long
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
vx = 10
tx = 20
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
'--------------->
PrintL GdipGetImageEncodersSize(vx, tx)
PrintL vx
PrintL tx
'--------------->
' Shutdown GDI+
GdiplusShutdown token
PrintL "Press any key to quit..."
WaitKey
End Function
To address the problem with converting pointer syntax. ThinBASIC offers these functions to work on pointer-related stuff:
PEEK/POKE
PEEK$/POKE$
VARPTR/STRPTR
DIM..AT syntax, along with SetAt, GetAt
To give example, the original code in PB:
Local pImageCodecInfo As ImageCodecInfo Ptr
...
hr = GdipGetImageEncoders(numEncoders, nSize, ByVal pImageCodecInfo)
...
Function = GuidTxt$(@pImageCodecInfo.Clsid)
becomes this in ThinBASIC (would work in PB as well):
Local myImageCodecInfo As ImageCodecInfo ' -- No need to create pointer
...
hr = GdipGetImageEncoders(numEncoders, nSize, VarPtr(myImageCodecInfo)) ' -- Passing the pointer just here, to get pointer to variable you can use VarPtr
...
Function = GuidTxt$(myImageCodecInfo.Clsid) ' -- Returning it directly, no pointer dereferencing needed
This is one particular case. In general, I like very much the Dim..At concept.
' -- Example for dynamically allocating EXT precition variable
Dim pVariable As DWord ' -- Our pointer, DWord can hold the address to -any- variable just fine
' -- Allocate memory dynamically, for the variable of type EXT
pVariable = HEAP_Alloc( SizeOf(Ext) )
' -- To write/read at that address we can create DIM..AT overlay instead of using pointers
Dim myVariable As Ext At pVariable ' -- Literally "Look at address pVariable as place for EXT variable"
myVariable = 5 ' -- In PB, you would do @pVariable = 5
MsgBox 0, myVariable ' -- In PB, you would do MSGBOX FORMAT$(@pVariable )
' -- Release memory
HEAP_Free(pVariable)
Of course, the allocations are needed only if it is your memory, you can create overlays over existing "normal" variables as well, and in such a case no such a operation is needed.
PB pointer version:
' -- Accessing 3rd array element via pointer
Dim myArray(3) As Ext
ARRAY ASSIGN myArray() = 1, 2, 3 ' -- Initial values 1, 2, 3
Dim pViewAtElement3 As Ext Pointer
pViewAtElement3 = VarPtr(myArray(3))
@pViewAtElement3 = 456 ' -- Accessing it and changing
MsgBox 0, format$(myArray(1))+","+format$(myArray(2))+","+format$(myArray(3)) ' -- Voila! It really changed 3rd index value to 456
ThinBasic Dim..At version:
' -- Accessing 3rd array cell via Dim..At
Dim myArray(3) As Ext = 1, 2, 3 ' -- Initial values 1, 2, 3
Dim myViewAtElement3 As Ext At VarPtr(myArray(3)) ' -- Overlaying logical variable over 3rd element
myViewAtElement3 = 456 ' -- Accessing it and changing
MsgBox 0, Join$(myArray, ",") ' -- Voila! It really changed 3rd index value to 456
... and as a bonus, super short variable declaration ThinBASIC version:
' -- Accessing 3rd array cell via Dim..At
Ext myArray(3) = 1, 2, 3 ' -- Initial values 1, 2, 3
Ext myViewAtElement3 At VarPtr(myArray(3)) ' -- Overlaying logical variable over 3rd element
myViewAtElement3 = 456 ' -- Accessing it and changing
MsgBox 0, Join$(myArray, ",") ' -- Voila! It really changed 3rd index value to 456
Petr
largo_winch
03-11-2011, 21:35
thanks for pointer infos and arrays, I will proof this concept petr too! :)
my second problem zone (from three, four zones!) :
...
Local hr As Long
Local i As Long
' Local pImageCodecInfo As ImageCodecInfo Ptr ''powerbasic
Local myImageCodecInfo As ImageCodecInfo ' -- No need to create pointer
Local numEncoders As DWord
'Local nSize As DWord 'powerbasic
Local nSize As Long Value 10000 'my idea: only as a test value !
Local buffer As String
'-------------------------------------------------------------------------->
hr = GdipGetImageEncoders(numEncoders, nSize, VarPtr(myImageCodecInfo))
' -- Passing the pointer just here, to get pointer to variable you can use VarPtr
'new my idea ------>
Dim MyBufferArray(Len(Buffer)) As Byte At StrPtr(Buffer) ' my idea
'new my idea ------>
'ReDim buffer(nSize - 1) As Byte 'powerbasic
ReDim MyBufferArray(nSize - 1) As Byte
'myImageCodecInfo = VarPtr(buffer(0)) 'powerbasic
myImageCodecInfo = VarPtr(MyBufferArray(1))
'pImageCodecInfo = VarPtr(bufferArray(0))'powerbasic
'-------------------------------------------------------------------------->
ReDim buffer(nSize - 1) As Byte
caused problems too. My idea was to make an array with "MyBufferArray(nSize-1) as Byte. but that's not perfect I guess. any idea for making better? (green : powerbasic, black : thinbasic)
again the original powerbasic code part for needing translation:
...
LOCAL hr AS LONG
LOCAL i AS LONG
LOCAL pImageCodecInfo AS ImageCodecInfo PTR
LOCAL numEncoders AS DWORD
LOCAL nSize AS DWORD
hr = GdipGetImageEncodersSize(numEncoders, nSize)
REDIM buffer(nSize - 1) AS BYTE
pImageCodecInfo = VARPTR(buffer(0))
...
thank's for help!, bye largo
Petr Schreiber
04-11-2011, 00:50
Local nSize As Long Value 10000 'my idea: only as a test value !
This is not necessary, the nSize parameter is actually filled by call to GdipGetImageEncodersSize.
Because nSize is number of elements (in this case BYTEs), and ThinBASIC arrays are 1 based, the correct array declaration would be:
ReDim MyBufferArray(nSize) As Byte
Otherwise you risk memory corruption.
Petr
largo_winch
04-11-2011, 20:25
thanks petr first of all for your last correction!
(use at own risk) my next problemzone concerns :
'------------> Problemzone 3) ------------------------------->
'Expected a parameter passed BYREF but found something else.
hStatus = GdipSaveImageToFile(myImage, StrPtr(strFileName), EncoderClsid, 0) 'ByVal %NULL
'------------> Problemzone 3) ------------------------------->
I am not sure if I have to use Byval %Null at the end of function (then error with saving file) or only using "0", then "EncoderClsid" (GUID) expected a parameter passed byref.
here's the whole code example part and still it isn't perfect, but very close to the correct solution:
' Empty GUI script created on 11-04-2011 18:56:29 by largo_winch (ThinAIR)
Uses "console"
Uses "UI", "console"
'---------------------------->
#INCLUDE "GDIPLUS_LW1a.INC"
'---------------------------->
Declare Function LoadLibrary Lib "KERNEL32.DLL" _
Alias "LoadLibraryA" _
(lpLibFileName As Asciiz) As Long
Dim vx, tx As Long
'---------------------------> MAIN ------------->
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
Local sx As String
vx = 10
tx = 20
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
PrintL GdiPlusGetEncoderClsid(sx)
'--------------->
PrintL GdipGetImageEncodersSize(vx, tx)
PrintL vx
PrintL tx
'--------------->
PrintL convertingBMP()
' Shutdown GDI+
GdiplusShutdown token
PrintL "Press any key to quit..."
WaitKey
End Function
'Guid variables are a special form of 16-Byte String
'that are used To contain a 128-Bit Globally Unique Identifier (Guid),
'primarily For use With COM Objects.
'-------------------> TestZone * TestZone * TestZone * TestZone * TestZone
Sub convertingBMP()
'------------------->
Local hLib, hLib1 As Long
Local token As DWord
Local EncoderClsid As Guid
Local myImage As DWord
Local pGraphics As DWord
Local pBitmap As DWord
Local eps As EncoderParameters
Local ep As EncoderParameter
Local nWidth As DWord
Local nHeight As DWord
Local transformation As DWord
Local strFileName As String
Local hStatus As Long
Local s1 As String = Guid$
Local s2 As String = GuidTxt$(s1)
Local sx As String
sx = "image/png"
MsgBox 0, s2
'hLib = LoadLibrary("Oleaut32.dll")
'MsgBox 0, Str$(hLib)
'Guid$={00000000-0000-0000-0000-000000000000}
'hStatus = GdipCreateFromHDC(Canvas_GetDC, pGraphics)
' // Create a Bitmap object from a JPEG file.
strFileName = Ucode$("Metallica1.bmp")
hStatus = GdipCreateBitmapFromFile(StrPtr(strFileName), pBitmap)
' // Draw the bitmap ---> not needed at the moment
'hStatus = GdipDrawImageI(pGraphics, pBitmap, 10, 10)
'------------> Problemzone 1) solved ------------------------------->
hStatus = GdipLoadImageFromFile(StrPtr(strFileName), myImage)
'------------> Problemzone 1) solved ------------------------------->
Encoderclsid = Guid$(s1)
MsgBox 0, "here's begin of converting_Bmp Sub"
' // Get the CLSID of the PNG encoder.
PrintL GdiPlusGetEncoderClsid(sx)
'--------------->
PrintL GdipGetImageEncodersSize(vx, tx)
PrintL vx
PrintL tx
'--------------->
'------------> Problemzone 2) solved ? ------------------------------->
'EncoderClsid = Guid$(GdiPlusGetEncoderClsid("image/png"))
EncoderClsid = GdiPlusGetEncoderClsid(sx)
' // Save the image.
strFileName = Ucode$("Metallica1.png")
EncoderClsid = GdiPlusGetEncoderClsid(sx)
'------------> Problemzone 2) solved ? ------------------------------->
'------------> Problemzone 3) ------------------------------->
'Expected a parameter passed BYREF but found something else.
hStatus = GdipSaveImageToFile(myImage, StrPtr(strFileName), EncoderClsid, 0) 'ByVal %NULL
'------------> Problemzone 3) ------------------------------->
If hStatus = %StatusOk Then
PrintL "Shapes.png saved successfully"
Else
PrintL "Attempt to save Metallica1.png failed"
End If
' // Cleanup
If myImage Then GdipDisposeImage(myImage)
' // Shutdown GDI+
GdiplusShutdown token
MsgBox 0, "here's end of converting_Bmp Sub"
End Sub
'-------------------> END OF TestZone * TestZone * TestZone * TestZone * TestZone
other two problems from beginning seems to be solved by your help :)
bye, largo
Petr Schreiber
04-11-2011, 22:38
Hi Largo,
#1)
The header file and this example you attach, which seems to be port of this code from José forum (http://www.jose.it-berater.org/smfforum/index.php?topic=1862.msg6504#msg6504), still do not give credit to José.
The tip with array is not applied as well.
#2)
GdipSaveImageToFile is declared (http://www.jose.it-berater.org/smfforum/index.php?topic=1861.0)as:
DECLARE FUNCTION GdipSaveImageToFile ( _
BYVAL pImage AS DWORD, _
BYVAL pFilename AS STRING, _
BYREF clsidEncoder AS GUID, _
BYREF encoderParams AS EncoderParameters _
) AS LONG
So the last param expects the ByRef parameter. That means, passing variable directly or passing pointer with ByVal override (which means "I pass address directly").
In this case, Byval %Null or ByVal 0 will work just fine.
Petr
largo_winch
07-11-2011, 11:39
original example: "gdip_convertingBMPtoPNG"
http://www.jose.it-berater.org/smfforum/index.php?topic=1862.0
thank you petr again for your feedback. Here's my next attempt but failed to convert *.bmp Image to *.png Image. I guess
a) problem zone is still:
EncoderClsid = Guid$(GdiPlusGetEncoderClsid("image/png")
b) my adepted code for "GdiPlusGetEncoderClsid" (my approach, see include file):
Function GdiPlusGetEncoderClsid (ByRef wszMimeType As String) As String
Local hr As Long
Local i As Long
' Local pImageCodecInfo As ImageCodecInfo Ptr ''powerbasic
Local myImageCodecInfo As ImageCodecInfo ' -- No need to create pointer
Local numEncoders As DWord
Local nSize As DWord 'powerbasic
' Local nSize As Long 'Value 10000 'my idea: only as a test value !
Local buffer As String
Local myMimeType as string
nSize = 1
'-------------------------------------------------------------------------->
hr = GdipGetImageEncoders(numEncoders, nSize, VarPtr(myImageCodecInfo))
' -- Passing the pointer just here, to get pointer to variable you can use VarPtr
'new my idea ------>
Dim MyBufferArray(Len(Buffer)) As Byte At StrPtr(Buffer) ' my idea
'new my idea ------>
'ReDim buffer(nSize - 1) As Byte 'powerbasic
ReDim MyBufferArray(nSize) As Byte 'nSize - 1
'myImageCodecInfo = VarPtr(buffer(0)) 'powerbasic
myImageCodecInfo = VarPtr(MyBufferArray(1))
'-------------------------------------------------------------------------->
hr = GdipGetImageEncoders(numEncoders, nSize, myImageCodecInfo) 'ByVal
If hr = 0 Then
For i = 1 To numEncoders '@MimeType
If InStr(Ucase$(myImageCodecInfo.myMimeType), Ucase$(wszMimeType)) Then
Function = GuidTxt$(myImageCodecInfo.Clsid)
' -- Returning it directly, no pointer dereferencing needed
' Function = GuidTxt$(@pImageCodecInfo.Clsid)
Exit For
End If
Incr myImageCodecInfo '// Increments pointer
Next
End If
End Function
'-------------------------> ORIGINAL ------------>
2) test gdip example for converting to thinbasic:
' Empty GUI script created on 11-07-2011 09:42:26 by largo_winch (ThinAIR)
' original example: http://www.jose.it-berater.org/smfforum/index.php?topic=1862.0
'
Uses "console", "ui"
#INCLUDE "gdiplus_lw1b.inc"
' ========================================================================================
' Main
' ========================================================================================
Function TBMain() As Long
Local hStatus As Long
Local token As DWord
Local StartupInput As GdiplusStartupInput
Local EncoderClsid As Guid
Local myImage As DWord
Local eps As EncoderParameters
Local ep As EncoderParameter
Local nWidth As DWord
Local nHeight As DWord
Local transformation As DWord
Local strFileName As String
Local sx As String
sx = "image/png"
' // Initialize GDI+
StartupInput.GdiplusVersion = 1
hStatus = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hStatus Then
Print "Error initializing GDI+"
Exit Function
End If
strFileName = Ucode$("Metallica1a.bmp")
hStatus = GdipLoadImageFromFile(StrPtr(strFileName), myImage)
PrintL hStatus 'ok
' // Get the CLSID of the PNG encoder.
'--------> last problem zone ------------------------------------------->
EncoderClsid = Guid$(GdiPlusGetEncoderClsid("image/png")) 'original, doesn't work
' EncoderClsid = Guid$(GdiPlusGetEncoderClsid(sx) ) 'my idea
'PrintL EncoderClsid 'only for a test , ok :)
'--------> last problem zone ------------------------------------------->
' // Save the image.
strFileName = Ucode$("Metallica1a.png")
hStatus = GdipSaveImageToFile(myImage, StrPtr(strFileName), EncoderClsid, ByVal %NULL)
If hStatus = %StatusOk Then
PrintL "Shapes.png saved successfully"
Else
PrintL "Attempt to save Metallica1a.png failed"
End If
PrintL hStatus 'ok
' // Cleanup
If myImage Then GdipDisposeImage(myImage)
' // Shutdown GDI+
GdiplusShutdown token
PrintL "end of sub, press any key to exit"
WaitKey
End Function
attachement: zip file + new include file
bye, largo
Petr Schreiber
11-11-2011, 20:18
I am checking... stay tuned.
Petr
Petr Schreiber
13-11-2011, 18:24
Hi Largo,
got it working, here is single file example, you need to place your metallica1.bmp to same directory as script of course.
I recoded it from José's original, as there was lot of redundant code in your original example.
'original example: http://www.jose.it-berater.org/smfforum/index.php?topic=1862.0
Uses "console"
' ========================================================================================
' Main
' ========================================================================================
Function TBMain() As Long
Local hStatus As Long
Local token As DWord
Local StartupInput As GdiplusStartupInput
Local EncoderClsid As Guid
Local pImage As DWord
Local eps As EncoderParameters
Local ep As EncoderParameter
Local nWidth As DWord
Local nHeight As DWord
Local transformation As DWord
Local strFileName As String
' // Initialize GDI+
StartupInput.GdiplusVersion = 1
hStatus = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hStatus Then
PrintL "Error initializing GDI+"
Exit Function
End If
strFileName = Ucode$("metallica1.bmp")
hStatus = GdipLoadImageFromFile(StrPtr(strFileName), pImage)
' // Get the CLSID of the PNG encoder.
EncoderClsid = Guid$(GdiPlusGetEncoderClsid("image/png"))
' // Save the image.
strFileName = Ucode$("metallica1.png")
hStatus = GdipSaveImageToFile(pImage, StrPtr(strFileName), EncoderClsid, ByVal %NULL)
If hStatus = %StatusOk Then
PrintL "metallica1.png saved successfully"
Else
PrintL "Attempt to save metallica1.png failed"
End If
' // Cleanup
If pImage Then GdipDisposeImage(pImage)
' // Shutdown GDI+
GdiplusShutdown token
Console_WaitKey
End Function
' -- Definitions from Josés headers
%StatusOk = 0
Type GdiplusStartupInput
GdiplusVersion As DWord
DebugEventCallback As DWord
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
If SizeOf(GdiplusStartupInput) <> 16 Then MsgBox 0, "Invalid size of GdiplusStartupInput"
Type GdiplusStartupOutput
NotificationHook As DWord
NotificationUnhook As DWord
End Type
If SizeOf(GdiplusStartupOutput) <> 8 Then MsgBox 0, "Invalid size of GdiplusStartupOutput"
Type EncoderParameter
pGuid As String * 16 ' // GUID of the parameter
NumberOfValues As DWord ' // Number of the parameter values
dwType As DWord ' // Value type, like ValueTypeLONG etc.
Value As DWord ' // A pointer to the parameter values
End Type
If SizeOf(EncoderParameter) <> 28 Then MsgBox 0, "Invalid size of EncoderParameter"
Type EncoderParameters
Count As DWord ' // Number of parameters in this structure
Parameter As EncoderParameter ' // Parameter values - variable-length array
End Type
If SizeOf(EncoderParameters) <> 32 Then MsgBox 0, "Invalid size of EncoderParameters"
Type ImageCodecInfo
Clsid As String * 16 ' CLSID
FormatID As String * 16 ' GUID
CodecName As Word Ptr ' const WCHAR*
DllName As Word Ptr ' const WCHAR*
FormatDescription As Word Ptr ' const WCHAR*
FilenameExtension As Word Ptr ' const WCHAR*
MimeType As Word Ptr ' const WCHAR*
Flags As DWord ' DWORD
Version As DWord ' DWORD
SigCount As DWord ' DWORD
SigSize As DWord ' DWORD
SigPattern As Byte Ptr ' const BYTE*
SigMask As Byte Ptr ' const BYTE*
End Type
If SizeOf(ImageCodecInfo) <> 76 Then MsgBox 0, "Invalid size of ImageCodecInfo"
Declare Function GdiplusStartup Lib "GDIPLUS.DLL" Alias "GdiplusStartup" (
ByRef token As DWord ' __out token ULONG_PTR
, ByRef input As GdiplusStartupInput ' __in input GdiplusStartupInput <record>
, ByRef output As GdiplusStartupOutput ' __out output GdiplusStartupOutput <record>
) As Long ' GpStatus
Declare Function GdipLoadImageFromFile Lib "GDIPLUS.DLL" Alias "GdipLoadImageFromFile" (
ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef Image As DWord ' __out GpImage **image
) As Long ' GpStatus
Declare Function lstrlenw Lib "KERNEL32.DLL" Alias "lstrlenW" ( _
ByVal lpString As DWord _ ' __in LPCWSTR lpString
) As Long
Declare Function GdipGetImageEncodersSize Lib "GDIPLUS.DLL" Alias "GdipGetImageEncodersSize" (
ByRef numEncoders As DWord ' __in UINT *numEncoders
, ByRef Size As DWord ' __out UINT *size
) As Long ' Status
Declare Function GdipGetImageEncoders Lib "GDIPLUS.DLL" Alias "GdipGetImageEncoders" (
ByVal numEncoders As DWord ' __in UINT numEncoders
, ByVal Size As DWord ' __in UINT size
, ByRef encoders As Any ' __out ImageCodecInfo *encoders
) As Long ' Status
Declare Function GdipSaveImageToFile Lib "GDIPLUS.DLL" Alias "GdipSaveImageToFile" (
ByVal Image As DWord ' __in GpImage *image
, ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef clsidEncoder As Guid ' __in GDIPCONST CLSID clsidEncoder
, ByRef encoderParams As EncoderParameters ' __out GDIPCONST EncoderParameters *encoderParams
) As Long
Declare Function GdipDisposeImage Lib "GDIPLUS.DLL" Alias "GdipDisposeImage" (
ByVal Image As DWord ' __in GpImage *image
) As Long ' GpStatus
Declare Sub GdiplusShutdown Lib "GDIPLUS.DLL" Alias "GdiplusShutdown" ( _
ByVal token As DWord _ ' __in token ULONG_PTR
) ' void
Function GdiPlusGetEncoderClsid (ByVal strMimeType As String) As String
Local hr As Long
Local pImageCodecInfo As DWord
Local numEncoders As DWord
Local nSize As DWord
Local i As Long
Local wstrlen As Long
Local sMimeType As String
hr = GdipGetImageEncodersSize(numEncoders, nSize)
Dim buffer(nSize) As Byte
pImageCodecInfo = VarPtr(buffer(1))
Local myImageCodecInfo As ImageCodecInfo At pImageCodecInfo
hr = GdipGetImageEncoders(numEncoders, nSize, ByVal pImageCodecInfo)
If hr = 0 Then
For i = 1 To numEncoders
wstrlen = lstrlenW(myImageCodecInfo.MimeType)
If wstrlen Then sMimeType = Acode$(Peek$(myImageCodecInfo.MimeType, wstrlen * 2))
If InStr(Ucase$(sMimeType), Ucase$(strMimeType)) Then
Function = GuidTxt$(myImageCodecInfo.Clsid)
Exit For
End If
pImageCodecInfo += SizeOf(ImageCodecInfo) '// Increments pointer
SetAt(myImageCodecInfo, pImageCodecInfo)
Next
End If
End Function
Petr
largo_winch
14-11-2011, 11:07
hi petr, thanks with reputation for you. there are only few differences between your new gdiplus encoder features, but very important and precious one, good job! I was frustrated (middle of last week) to see nearly no light for solving this example! do you get the headers of gdiplus from jose's website of the actual winapi headers?, bye largo
Petr Schreiber
14-11-2011, 11:22
Hi,
as written in the code comment, I used José's declares. Those for PB/WIN 9 to be precise. I had to modify the GUIDs, adapt the pointer syntax to TB but the rest worked fine.
Petr
largo_winch
14-11-2011, 15:47
http://www.jose.it-berater.org/smfforum/index.php?topic=1827.0
here's a new example with "tb_gdiplus create_StringFormat". only the "string" to show in rectangle box is missing. I've controlled and separated all needed gdip functions and declares in this example (like you did it in last example).
all in code example is working fine here, but the string doesn't work:
'-------------> problemzone ------------------------------------------------->
hStatus = GdipCreateStringFormat(0, %LANG_NEUTRAL, pFormat ) 'StrPtr(pFormat ) no!
'-------------> problemzone ------------------------------------------------->
' Empty GUI script created on 11-14-2011 14:33:05 by largo_winch (ThinAIR)
'--------------> GDIPLUS TEST FOR THINBASIC -------------------->
'------------------------->
' Example original from
' http://www.jose.it-berater.org/smfforum/index.php?topic=1827.0
'------------------------->
Uses "UI", "console"
'---------------------------->
'#INCLUDE "GDIPLUS_LW1b.INC"
'---------------------------->
'--------------------------------------------------------------------------------------------------
%UnitPixel = 2 ' Sets each unit to be one device pixel
'--------------------------------------------------------------------------------------------------
Begin ControlID
%Canvas_Gdip
%bClose
End ControlID
Type RectF
x As Long
y As Long
width As Long
height As Long
End Type
Type GDIP_BGRA_STRUCT Byte
blue As Byte
green As Byte
red As Byte
alpha As Byte
End Type
' // Size = 4 bytes
Union GDIP_BGRA_UNION
Color As DWord
GDIP_BGRA_STRUCT
End Union
'-------------------------->
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
Dialog New 0, "tb_gdiplus create_StringFormat",-1,-1, 420, 270, _
%WS_POPUP Or %WS_VISIBLE Or _
%WS_CLIPCHILDREN Or %WS_CAPTION Or _
%WS_SYSMENU Or %WS_MINIMIZEBOX, 0 To hDlg
Dialog Show Modal hDlg, Call dlgProc
' Shutdown GDI+
GdiplusShutdown token
End Function
' ========================================================================================
' ========================================================================================
' Main Dialog procedure
' ========================================================================================
CallBack Function DlgProc() As Long
Local cx, cy As Long, hDc As Long
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Place controls here
Dialog Pixels CBHNDL, 400, 250 To Units cx, cy
Control Add Canvas, CBHNDL, %Canvas_Gdip, "", 5, 5, cx+100, cy+100
Control Add Button, CBHNDL, %bClose, "Close", 80+cx, cy+5-84, 50, 18, Call bCloseProc
Canvas_Attach CBHNDL, %Canvas_Gdip, %TRUE
Canvas_Color Rgb(128, 255, 0), Rgb(0, 0, 0)
'Canvas_Clear(Rgb(0,0,0))
Canvas_Scale Pixels
Case %WM_PAINT
GDIP_CreateStringFormat()
Canvas_Redraw
Case %WM_COMMAND
Select Case CBCTL
Case %IDCANCEL
If CBCTLMSG = %BN_CLICKED Then Dialog End CBHNDL, 0
End Select
End Select
End Function
' -- Callback for close button
CallBack Function bCloseProc()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
'------------------------------>
Sub GDIP_CreateStringFormat()
'------------------------------>
Local hStatus As Long
Local pGraphics As DWord
Local pPen As DWord
Local pFont As DWord
Local pFontFamily As DWord
Local pFormat As DWord
Local pBlackBrush As DWord
Local strFontName As String
Local strText As String
Local rcf As RECTF
hStatus = GdipCreateFromHDC(Canvas_GetDC, pGraphics)
' // Create the font
strFontName = Ucode$("Arial")
hStatus = GdipCreateFontFamilyFromName(StrPtr(strFontName), %NULL, pFontFamily)
If hStatus = %StatusOk And pFontFamily <> %NULL Then
hStatus = GdipCreateFont(pFontFamily, 16, %FontStyleRegular, %UnitPoint, pFont)
GdipDeleteFontFamily(pFontFamily)
End If
' Note: You can use the wrapper function GdiPlusCreateFontFromName to create the font:
'hStatus = GdiPlusCreateFontFromName("Arial", 16, %FontStyleRegular, %UnitPoint, pFont)
' // Create a solid brush
hStatus = GdipCreateSolidFill(GDIP_ARGB(255, 0, 0, 0), pBlackBrush)
' // Draw the string
rcf.x = 30.0! : rcf.y = 30.0! : rcf.Width = 200.0! : rcf.Height = 25.0!
'-------------> problemzone ------------------------------------------------->
hStatus = GdipCreateStringFormat(0, %LANG_NEUTRAL, pFormat ) 'StrPtr(pFormat ) no!
'-------------> problemzone ------------------------------------------------->
hStatus = GdipSetStringFormatAlign(pFormat, %StringAlignmentCenter)
strText = Ucode$("Sample text")
hStatus = GdipDrawString(pGraphics, StrPtr(strText), Len(strText) \ 2, pFont, rcf, pFormat, pBlackBrush)
' // Create a Pen
hStatus = GdipCreatePen1(GDIP_ARGB(255,0, 0, 0), 3, %UnitPixel, pPen)
' // Draw a rectangle
hStatus = GdipDrawRectangle(pGraphics, pPen, rcf.x, rcf.y, rcf.Width, rcf.Height)
' // Cleanup
If pFont Then GdipDeleteFont(pFont)
If pBlackBrush Then GdipDeleteBrush(pBlackBrush)
If pPen Then GdipDeletePen(pPen)
If pFormat Then GdipDeleteStringFormat(pFormat)
If pGraphics Then GdipDeleteGraphics(pGraphics)
End Sub
'----------------> GDIP INCLUDE HELPERS ------------------------------------------------------>
' enum FillMode
%FillModeAlternate = 0
%FillModeWinding = 1
'---------------------------------->
%LANG_NEUTRAL = &H00??
%LANG_INVARIANT = &H7f??
'---------------------------------->
' enum StringAlignment
' // Left edge for left-to-right text,
' // right for right-to-left text,
' // and top for vertical
%StringAlignmentNear = 0
%StringAlignmentCenter = 1
%StringAlignmentFar = 2
Declare Function GdipSetStringFormatAlign Lib "GDIPLUS.DLL" Alias "GdipSetStringFormatAlign" ( _
ByVal pFormat As DWord, _
ByVal align As Long _
) As Long
Declare Function GdipCreateStringFormat Lib "GDIPLUS.DLL" Alias "GdipCreateStringFormat" ( _
ByVal formatAttributes As Long _ ' __in INT formatAttributes
, ByVal language As Word _ ' __in LANGID language
, ByRef format As DWord _ ' __out GpStringFormat **format '''[out] Pointer to a variable that receives a pointer to the new StringFormat object.
) As Long ' GpStatus
Declare Function GdipCreateFromHDC Lib "GDIPLUS.DLL" Alias "GdipCreateFromHDC" ( _
ByVal hdc As DWord _
, ByRef graphics As DWord _
) As Long
Declare Function GdipCreateFontFamilyFromName Lib "GDIPLUS.DLL" Alias "GdipCreateFontFamilyFromName" ( _
ByRef Names As String _ ' __in GDIPCONST WCHAR *name
, ByVal fontCollection As DWord _ ' __in GpFontCollection *fontCollection
, ByRef fontFamily As DWord _ ' __out GpFontFamily **fontFamily
) As Long ' GpStatus
Declare Function GdipCreateSolidFill Lib "GDIPLUS.DLL" Alias "GdipCreateSolidFill" ( _
ByVal Color As DWord _ ' __in ARGB color
, ByRef brush As DWord _ ' __out GpSolidFill **brush
) As Long ' GpStatus
Declare Function GdipDeleteFontFamily Lib "GDIPLUS.DLL" Alias "GdipDeleteFontFamily" ( _
ByVal fontFamily As DWord _ ' __in GpFontFamily *fontFamily
) As Long ' GpStatus
Declare Function GdipCreateFont Lib "GDIPLUS.DLL" Alias "GdipCreateFont" ( _
ByVal fontFamily As DWord _ ' __in GDIPCONST GpFontFamily *fontFamily
, ByVal emSize As Single _ ' __in REAL emSize
, ByVal style As Long _ ' __in INT style
, ByVal unit As Long _ ' __in GpUnit unit
, ByRef Font As DWord _ ' __out GpFont **font
) As Long ' GpStatus
'----------------------------------------------------------->
' -- Definitions from Josés headers
%StatusOk = 0
Type GdiplusStartupInput
GdiplusVersion As DWord
DebugEventCallback As DWord
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
If SizeOf(GdiplusStartupInput) <> 16 Then MsgBox 0, "Invalid size of GdiplusStartupInput"
Type GdiplusStartupOutput
NotificationHook As DWord
NotificationUnhook As DWord
End Type
If SizeOf(GdiplusStartupOutput) <> 8 Then MsgBox 0, "Invalid size of GdiplusStartupOutput"
Type EncoderParameter
pGuid As String * 16 ' // GUID of the parameter
NumberOfValues As DWord ' // Number of the parameter values
dwType As DWord ' // Value type, like ValueTypeLONG etc.
Value As DWord ' // A pointer to the parameter values
End Type
If SizeOf(EncoderParameter) <> 28 Then MsgBox 0, "Invalid size of EncoderParameter"
Type EncoderParameters
Count As DWord ' // Number of parameters in this structure
Parameter As EncoderParameter ' // Parameter values - variable-length array
End Type
If SizeOf(EncoderParameters) <> 32 Then MsgBox 0, "Invalid size of EncoderParameters"
Type ImageCodecInfo
Clsid As String * 16 ' CLSID
FormatID As String * 16 ' GUID
CodecName As Word Ptr ' const WCHAR*
DllName As Word Ptr ' const WCHAR*
FormatDescription As Word Ptr ' const WCHAR*
FilenameExtension As Word Ptr ' const WCHAR*
MimeType As Word Ptr ' const WCHAR*
Flags As DWord ' DWORD
Version As DWord ' DWORD
SigCount As DWord ' DWORD
SigSize As DWord ' DWORD
SigPattern As Byte Ptr ' const BYTE*
SigMask As Byte Ptr ' const BYTE*
End Type
If SizeOf(ImageCodecInfo) <> 76 Then MsgBox 0, "Invalid size of ImageCodecInfo"
Declare Function GdiplusStartup Lib "GDIPLUS.DLL" Alias "GdiplusStartup" (
ByRef token As DWord ' __out token ULONG_PTR
, ByRef input As GdiplusStartupInput ' __in input GdiplusStartupInput <record>
, ByRef output As GdiplusStartupOutput ' __out output GdiplusStartupOutput <record>
) As Long ' GpStatus
Declare Function GdipLoadImageFromFile Lib "GDIPLUS.DLL" Alias "GdipLoadImageFromFile" (
ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef Image As DWord ' __out GpImage **image
) As Long ' GpStatus
Declare Function lstrlenw Lib "KERNEL32.DLL" Alias "lstrlenW" ( _
ByVal lpString As DWord _ ' __in LPCWSTR lpString
) As Long
Declare Function GdipGetImageEncodersSize Lib "GDIPLUS.DLL" Alias "GdipGetImageEncodersSize" (
ByRef numEncoders As DWord ' __in UINT *numEncoders
, ByRef Size As DWord ' __out UINT *size
) As Long ' Status
Declare Function GdipGetImageEncoders Lib "GDIPLUS.DLL" Alias "GdipGetImageEncoders" (
ByVal numEncoders As DWord ' __in UINT numEncoders
, ByVal Size As DWord ' __in UINT size
, ByRef encoders As Any ' __out ImageCodecInfo *encoders
) As Long ' Status
Declare Function GdipSaveImageToFile Lib "GDIPLUS.DLL" Alias "GdipSaveImageToFile" (
ByVal Image As DWord ' __in GpImage *image
, ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef clsidEncoder As Guid ' __in GDIPCONST CLSID clsidEncoder
, ByRef encoderParams As EncoderParameters ' __out GDIPCONST EncoderParameters *encoderParams
) As Long
Declare Function GdipDisposeImage Lib "GDIPLUS.DLL" Alias "GdipDisposeImage" (
ByVal Image As DWord ' __in GpImage *image
) As Long ' GpStatus
Declare Sub GdiplusShutdown Lib "GDIPLUS.DLL" Alias "GdiplusShutdown" ( _
ByVal token As DWord _ ' __in token ULONG_PTR
)
' void
Function GdiPlusGetEncoderClsid (ByVal strMimeType As String) As String
Local hr As Long
Local pImageCodecInfo As DWord
Local numEncoders As DWord
Local nSize As DWord
Local i As Long
Local wstrlen As Long
Local sMimeType As String
hr = GdipGetImageEncodersSize(numEncoders, nSize)
Dim buffer(nSize) As Byte
pImageCodecInfo = VarPtr(buffer(1))
Local myImageCodecInfo As ImageCodecInfo At pImageCodecInfo
hr = GdipGetImageEncoders(numEncoders, nSize, ByVal pImageCodecInfo)
If hr = 0 Then
For i = 1 To numEncoders
wstrlen = lstrlenW(myImageCodecInfo.MimeType)
If wstrlen Then sMimeType = Acode$(Peek$(myImageCodecInfo.MimeType, wstrlen * 2))
If InStr(Ucase$(sMimeType), Ucase$(strMimeType)) Then
Function = GuidTxt$(myImageCodecInfo.Clsid)
Exit For
End If
pImageCodecInfo += SizeOf(ImageCodecInfo) '// Increments pointer
SetAt(myImageCodecInfo, pImageCodecInfo)
Next
End If
End Function
Function GDIP_ARGB (ByVal a As Byte, ByVal r As Byte, ByVal g As Byte, ByVal b As Byte) As DWord
Local clr As GDIP_BGRA_UNION
clr.alpha = a
clr.red = r
clr.green = g
clr.blue = b
Function = clr.Color
End Function
Declare Function GdipDrawString Lib "GDIPLUS.DLL" Alias "GdipDrawString" ( _
ByVal graphics As DWord _ ' __in GpGraphics *graphics
, ByRef Strings As String _ ' __in GDIPCONST WCHAR *string
, ByVal length As Long _ ' __in INT length
, ByVal pFont As DWord _ ' __in GDIPCONST GpFont *font
, ByRef layoutRect As RectF _ ' __in GDIPCONST GpRectF *layoutRect
, ByVal stringFormat As DWord _ ' __in GDIPCONST GpStringFormat *stringFormat
, ByVal brush As DWord _ ' __in GpBrush *brush
) As Long ' GpStatus
Declare Function GdipCreatePen1 Lib "GDIPLUS.DLL" Alias "GdipCreatePen1" ( _
ByVal pColor As DWord, _
ByVal nWidth As Single, _
ByVal unit As Long, _
ByRef pen As DWord _
) As Long
Declare Function GdipDrawRectangle Lib "GDIPLUS.DLL" Alias "GdipDrawRectangle" ( _
ByVal graphics As DWord, _
ByVal pen As DWord, _
ByVal x As Single, _
ByVal y As Single, _
ByVal nWidth As Single, _
ByVal nHeight As Single _
) As Long
Declare Function GdipDeleteBrush Lib "GDIPLUS.DLL" Alias "GdipDeleteBrush" ( _
ByVal brush As DWord _
) As Long
Declare Function GdipDeletePen Lib "GDIPLUS.DLL" Alias "GdipDeletePen" ( _
ByVal pen As DWord _
) As Long
Declare Function GdipDeleteStringFormat Lib "GDIPLUS.DLL" Alias "GdipDeleteStringFormat" ( _
ByVal pFormat As DWord _
) As Long
Declare Function GdipDeleteGraphics Lib "GDIPLUS.DLL" Alias "GdipDeleteGraphics" ( _
ByVal graphics As DWord _
) As Long
would be nice if you can check the example again :)
bye, largo
Petr Schreiber
14-11-2011, 15:59
Check how do you use GdipCreateFontFamilyFromName and how did you declared the parameters.
Petr
largo_winch
15-11-2011, 19:45
thank you, petr, but I cannot see the solution? Tried a lot of changing, but nothing works correct.
do you are meaning
hStatus = GdipCreateFontFamilyFromName(STRPTR(strFontName), %NULL, pFontFamily) ' original
Declare Function GdipCreateFontFamilyFromName Lib "GDIPLUS.DLL" Alias "GdipCreateFontFamilyFromName" ( _
ByRef pName As String _ ' __in GDIPCONST WCHAR *name
, ByVal fontCollection As DWord _ ' __in GpFontCollection *fontCollection
, ByRef fontFamily As DWord _ ' __out GpFontFamily **fontFamily
) As Long ' GpStatus
isn't correct?
I am thinking it could be also
'-------------> problemzone ------------------------------------------------->
hStatus = GdipCreateStringFormat(0, %LANG_NEUTRAL, pFormat ) 'StrPtr(pFormat ) no!
'-------------> problemzone ------------------------------------------------->
perhaps you have one detail more for me why the string isn't shown? -thanks!
bye, largo
Petr Schreiber
15-11-2011, 23:21
When you watch José's codes, you can see he stores the hStatus information for many function calls.
That serves the debugging purpose - if hStatus <> %StatusOk, it means something went wrong. %StatusOk has value of zero.
Tip #1:
place breakpoint on the beginning of body of TBMain (this can be done using right click in code / Insert code block / Debugger breakpoint)
press F8 to enter debugging mode
press F5 to execute until breakpoint
repeatedly press F8 and watch if the hStatus is really zero
you will see GdipCreateFontFamilyFromName call does not return zero - so something is wrong already there
Tip #2:
Watch the declaration:
Declare Function GdipCreateFontFamilyFromName Lib "GDIPLUS.DLL" Alias "GdipCreateFontFamilyFromName" ( _
ByRef pName As String _ ' __in GDIPCONST WCHAR *name
, ByVal fontCollection As DWord _ ' __in GpFontCollection *fontCollection
, ByRef fontFamily As DWord _ ' __out GpFontFamily **fontFamily
) As Long
Watch how you use it:
hStatus = GdipCreateFontFamilyFromName(STRPTR(strFontName), %NULL, pFontFamily)
The first parameter of the function is ByRef String, that means, you should pass string variable directly (thinBasic will obtain the pointer automagically) OR BYVAL STRPTR(stringvariable) (this forces the passed value to be understood as pointer). Passing STRPTR without BYVAL has no meaning, and is the cause of the problem.
Petr
largo_winch
16-11-2011, 01:07
here a little test, if I have understood your explanations and thanks for more details! :)
' Empty GUI script created on 11-15-2011 23:44:20 by largo_winch (ThinAIR)
Uses "console"
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef pDst As Any, _
ByRef pSrc As Any, _
ByVal ByteLen As Long)
'---------------->
Sub myexample()
'---------------->
Const TEST_TEXT As String = "Hello Largo "
Dim strString As String
Dim lngCounter As Long, lngPosition As Long
strString = $SPC(20 * Len(TEST_TEXT))
For lngCounter = 1 To 20
Call CopyMemory(ByVal StrPtr(strString) + lngPosition, _
ByVal StrPtr(TEST_TEXT), Len(TEST_TEXT) )
lngPosition = lngPosition + Len(TEST_TEXT)
Next
PrintL strString
PrintL test_text
End Sub
PrintL myexample()
PrintL "hello test end"
WaitKey
so I must change one of the problem zone of my last example (gdip_createStringFormat) line into
hStatus = GdipCreateFontFamilyFromName(byval strptr(strFontName), %NULL, ByVal StrPtr(pFontFamily ) )
and some more code parts too ;)
bye, largo
largo_winch
16-11-2011, 01:39
after I've checked all declarations new with byref/byval parameters I've got this new example:
' Empty GUI script created on 11-15-2011 23:59:24 by (ThinAIR)
' Empty GUI script created on 11-14-2011 14:33:05 by largo_winch (ThinAIR)
'--------------> GDIPLUS TEST FOR THINBASIC -------------------->
'------------------------->
' Example original from
' http://www.jose.it-berater.org/smfforum/index.php?topic=1827.0
'------------------------->
Uses "UI", "console"
'---------------------------->
'#INCLUDE "GDIPLUS_LW1b.INC"
'---------------------------->
'--------------------------------------------------------------------------------------------------
%UnitPixel = 2 ' Sets each unit to be one device pixel
'--------------------------------------------------------------------------------------------------
'//--------------------------------------------------------------------------
'// FontStyle: face types and common styles
'//--------------------------------------------------------------------------
' enum FontStyle
%FontStyleRegular = 0
%FontStyleBold = 1
%FontStyleItalic = 2
%FontStyleBoldItalic = 3
%FontStyleUnderline = 4
%FontStyleStrikeout = 8
' enum Unit
%UnitWorld = 0 ' // 0 -- World coordinate (non-physical unit)
%UnitDisplay = 1 ' // 1 -- Variable -- for PageTransform only
%UnitPixel = 2 ' // 2 -- Each unit is one device pixel.
%UnitPoint = 3 ' // 3 -- Each unit is a printer's point, or 1/72 inch.
%UnitInch = 4 ' // 4 -- Each unit is 1 inch.
%UnitDocument = 5 ' // 5 -- Each unit is 1/300 inch.
%UnitMillimeter = 6 ' // 6 -- Each unit is 1 millimeter.
Begin ControlID
%Canvas_Gdip
%bClose
End ControlID
Type RectF
x As Long
y As Long
width As Long
height As Long
End Type
Type GDIP_BGRA_STRUCT Byte
blue As Byte
green As Byte
red As Byte
alpha As Byte
End Type
' // Size = 4 bytes
Union GDIP_BGRA_UNION
Colors As DWord
GDIP_BGRA_STRUCT
End Union
'-------------------------->
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
Dialog New 0, "tb_gdiplus create_StringFormat",-1,-1, 420, 270, _
%WS_POPUP Or %WS_VISIBLE Or _
%WS_CLIPCHILDREN Or %WS_CAPTION Or _
%WS_SYSMENU Or %WS_MINIMIZEBOX, 0 To hDlg
Dialog Show Modal hDlg, Call dlgProc
' Shutdown GDI+
GdiplusShutdown token
End Function
' ========================================================================================
' ========================================================================================
' Main Dialog procedure
' ========================================================================================
CallBack Function DlgProc() As Long
Local cx, cy, hDc As Long
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Place controls here
Dialog Pixels CBHNDL, 400, 250 To Units cx, cy
Control Add Canvas, CBHNDL, %Canvas_Gdip, "", 5, 5, cx+100, cy+100
Control Add Button, CBHNDL, %bClose, "Close", 80+cx, cy+5-84, 50, 18, Call bCloseProc
Canvas_Attach CBHNDL, %Canvas_Gdip, %TRUE
Canvas_Color Rgb(128, 255, 0), Rgb(0, 0, 0)
'Canvas_Clear(Rgb(0,0,0))
Canvas_Scale Pixels
Case %WM_PAINT
GDIP_CreateStringFormat()
Canvas_Redraw
Case %WM_COMMAND
Select Case CBCTL
Case %IDCANCEL
If CBCTLMSG = %BN_CLICKED Then Dialog End CBHNDL, 0
End Select
End Select
End Function
' -- Callback for close button
CallBack Function bCloseProc()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
'------------------------------>
Sub GDIP_CreateStringFormat()
'------------------------------>
Local hStatus As Long
Local pGraphics As DWord
Local pPen As DWord
Local pFont As DWord
Local pFontFamily As DWord
Local pFormat As DWord
Local pBlackBrush As DWord
Local strFontName As String
Local strText As String
Local rcf As RECTF
Local fontCollection As DWord
hStatus = GdipCreateFromHDC(Canvas_GetDC, pGraphics)
' // Create the font
strFontName = Ucode$("Arial")
'hStatus = GdipCreateFontFamilyFromName(strFontName,0,pFontFamily ) '
hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, ByVal StrPtr(pFontFamily ) )
If hStatus = %StatusOk And pFontFamily <> %NULL Then
hStatus = GdipCreateFont(pFontFamily, 16, %FontStyleRegular, %UnitPoint, ByVal StrPtr(pFont) )
GdipDeleteFontFamily(pFontFamily)
End If
' Note: You can use the wrapper function GdiPlusCreateFontFromName to create the font:
' hStatus = GdiPlusCreateFontFromName("Arial", 16, %FontStyleRegular, %UnitPoint, pFont)
' // Create a solid brush
hStatus = GdipCreateSolidFill(GDIP_ARGB(255, 0, 0, 0), ByVal StrPtr(pBlackBrush) )
' // Draw the string
rcf.x = 30.0 : rcf.y = 30.0 : rcf.Width = 200.0 : rcf.Height = 25.0
'-------------> problemzone ------------------------------------------------->
hStatus = GdipCreateStringFormat(0, %LANG_NEUTRAL, ByVal StrPtr(pFormat ) ) 'StrPtr(pFormat ) no!
'-------------> problemzone ------------------------------------------------->
'hStatus = GdipSetStringFormatAlign(pFormat, %StringAlignmentCenter)
strText = Ucode$("Sample text")
'hStatus = GdipDrawString(pGraphics, StrPtr(strText), Len(strText) \ 2, pFont, rcf, pFormat, pBlackBrush)
hStatus = GdipDrawString(pGraphics, ByVal StrPtr(strText), Len(strText) \ 2, pFont, ByVal StrPtr(rcf), pFormat, pBlackBrush)
' // Create a Pen
hStatus = GdipCreatePen1(GDIP_ARGB(255,0, 0, 0), 3, %UnitPixel, pPen )
' // Draw a rectangle
hStatus = GdipDrawRectangle(pGraphics, pPen, rcf.x, rcf.y, rcf.Width, rcf.Height)
' // Cleanup
If pFont Then GdipDeleteFont(pFont)
If pBlackBrush Then GdipDeleteBrush(pBlackBrush)
If pPen Then GdipDeletePen(pPen)
If pFormat Then GdipDeleteStringFormat(pFormat)
If pGraphics Then GdipDeleteGraphics(pGraphics)
End Sub
'----------------> GDIP INCLUDE HELPERS ------------------------------------------------------>
' enum FillMode
%FillModeAlternate = 0
%FillModeWinding = 1
'---------------------------------->
%LANG_NEUTRAL = &H00??
%LANG_INVARIANT = &H7f??
'---------------------------------->
' enum StringAlignment
' // Left edge for left-to-right text,
' // right for right-to-left text,
' // and top for vertical
%StringAlignmentNear = 0
%StringAlignmentCenter = 1
%StringAlignmentFar = 2
Declare Function GdipSetStringFormatAlign Lib "GDIPLUS.DLL" Alias "GdipSetStringFormatAlign" ( _
ByVal pFormat As DWord, _
ByVal align As Long _
) As Long
Declare Function GdipCreateStringFormat Lib "GDIPLUS.DLL" Alias "GdipCreateStringFormat" ( _
ByVal formatAttributes As Long _ ' __in INT formatAttributes
, ByVal language As Word _ ' __in LANGID language
, ByRef format As DWord _ ' __out GpStringFormat **format '''[out] Pointer to a variable that receives a pointer to the new StringFormat object.
) As Long ' GpStatus
Declare Function GdipCreateFromHDC Lib "GDIPLUS.DLL" Alias "GdipCreateFromHDC" ( _
ByVal hdc As DWord _
, ByRef graphics As DWord _
) As Long
Declare Function GdipCreateFontFamilyFromName Lib "GDIPLUS.DLL" Alias "GdipCreateFontFamilyFromName" ( _
ByRef pName As String _ ' __in GDIPCONST WCHAR *name
, ByVal fontCollection As DWord _ ' __in GpFontCollection *fontCollection
, ByRef fontFamily As DWord _ ' __out GpFontFamily **fontFamily
) As Long ' GpStatus
Declare Function GdipCreateSolidFill Lib "GDIPLUS.DLL" Alias "GdipCreateSolidFill" ( _
ByVal pColor As DWord _ ' __in ARGB color
, ByRef brush As DWord _ ' __out GpSolidFill **brush
) As Long ' GpStatus
Declare Function GdipDeleteFontFamily Lib "GDIPLUS.DLL" Alias "GdipDeleteFontFamily" ( _
ByVal fontFamily As DWord _ ' __in GpFontFamily *fontFamily
) As Long ' GpStatus
Declare Function GdipCreateFont Lib "GDIPLUS.DLL" Alias "GdipCreateFont" ( _
ByVal fontFamily As DWord _ ' __in GDIPCONST GpFontFamily *fontFamily
, ByVal emSize As Single _ ' __in REAL emSize
, ByVal style As Long _ ' __in INT style
, ByVal unit As Long _ ' __in GpUnit unit
, ByRef pFont As DWord _ ' __out GpFont **font
) As Long ' GpStatus
'----------------------------------------------------------->
' -- Definitions from Josés headers
%StatusOk = 0
Type GdiplusStartupInput
GdiplusVersion As DWord
DebugEventCallback As DWord
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
If SizeOf(GdiplusStartupInput) <> 16 Then MsgBox 0, "Invalid size of GdiplusStartupInput"
Type GdiplusStartupOutput
NotificationHook As DWord
NotificationUnhook As DWord
End Type
If SizeOf(GdiplusStartupOutput) <> 8 Then MsgBox 0, "Invalid size of GdiplusStartupOutput"
Type EncoderParameter
pGuid As String * 16 ' // GUID of the parameter
NumberOfValues As DWord ' // Number of the parameter values
dwType As DWord ' // Value type, like ValueTypeLONG etc.
Value As DWord ' // A pointer to the parameter values
End Type
If SizeOf(EncoderParameter) <> 28 Then MsgBox 0, "Invalid size of EncoderParameter"
Type EncoderParameters
Count As DWord ' // Number of parameters in this structure
Parameter As EncoderParameter ' // Parameter values - variable-length array
End Type
If SizeOf(EncoderParameters) <> 32 Then MsgBox 0, "Invalid size of EncoderParameters"
Type ImageCodecInfo
Clsid As String * 16 ' CLSID
FormatID As String * 16 ' GUID
CodecName As Word Ptr ' const WCHAR*
DllName As Word Ptr ' const WCHAR*
FormatDescription As Word Ptr ' const WCHAR*
FilenameExtension As Word Ptr ' const WCHAR*
MimeType As Word Ptr ' const WCHAR*
Flags As DWord ' DWORD
Version As DWord ' DWORD
SigCount As DWord ' DWORD
SigSize As DWord ' DWORD
SigPattern As Byte Ptr ' const BYTE*
SigMask As Byte Ptr ' const BYTE*
End Type
If SizeOf(ImageCodecInfo) <> 76 Then MsgBox 0, "Invalid size of ImageCodecInfo"
Declare Function GdiplusStartup Lib "GDIPLUS.DLL" Alias "GdiplusStartup" (
ByRef token As DWord ' __out token ULONG_PTR
, ByRef input As GdiplusStartupInput ' __in input GdiplusStartupInput <record>
, ByRef output As GdiplusStartupOutput ' __out output GdiplusStartupOutput <record>
) As Long ' GpStatus
Declare Function GdipLoadImageFromFile Lib "GDIPLUS.DLL" Alias "GdipLoadImageFromFile" (
ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef pImage As DWord ' __out GpImage **image
) As Long ' GpStatus
Declare Function lstrlenw Lib "KERNEL32.DLL" Alias "lstrlenW" ( _
ByVal lpString As DWord _ ' __in LPCWSTR lpString
) As Long
Declare Function GdipGetImageEncodersSize Lib "GDIPLUS.DLL" Alias "GdipGetImageEncodersSize" (
ByRef numEncoders As DWord ' __in UINT *numEncoders
, ByRef Size As DWord ' __out UINT *size
) As Long ' Status
Declare Function GdipGetImageEncoders Lib "GDIPLUS.DLL" Alias "GdipGetImageEncoders" (
ByVal numEncoders As DWord ' __in UINT numEncoders
, ByVal Size As DWord ' __in UINT size
, ByRef encoders As Any ' __out ImageCodecInfo *encoders
) As Long ' Status
Declare Function GdipSaveImageToFile Lib "GDIPLUS.DLL" Alias "GdipSaveImageToFile" (
ByVal Image As DWord ' __in GpImage *image
, ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef clsidEncoder As Guid ' __in GDIPCONST CLSID clsidEncoder
, ByRef encoderParams As EncoderParameters ' __out GDIPCONST EncoderParameters *encoderParams
) As Long
Declare Function GdipDisposeImage Lib "GDIPLUS.DLL" Alias "GdipDisposeImage" (
ByVal Image As DWord ' __in GpImage *image
) As Long ' GpStatus
Declare Sub GdiplusShutdown Lib "GDIPLUS.DLL" Alias "GdiplusShutdown" ( _
ByVal token As DWord _ ' __in token ULONG_PTR
)
' void
Function GdiPlusGetEncoderClsid (ByVal strMimeType As String) As String
Local hr As Long
Local pImageCodecInfo As DWord
Local numEncoders As DWord
Local nSize As DWord
Local i As Long
Local wstrlen As Long
Local sMimeType As String
hr = GdipGetImageEncodersSize(numEncoders, nSize)
Dim buffer(nSize) As Byte
pImageCodecInfo = VarPtr(buffer(1))
Local myImageCodecInfo As ImageCodecInfo At pImageCodecInfo
hr = GdipGetImageEncoders(numEncoders, nSize, ByVal pImageCodecInfo)
If hr = 0 Then
For i = 1 To numEncoders
wstrlen = lstrlenW(myImageCodecInfo.MimeType)
If wstrlen Then sMimeType = Acode$(Peek$(myImageCodecInfo.MimeType, wstrlen * 2))
If InStr(Ucase$(sMimeType), Ucase$(strMimeType)) Then
Function = GuidTxt$(myImageCodecInfo.Clsid)
Exit For
End If
pImageCodecInfo += SizeOf(ImageCodecInfo) '// Increments pointer
SetAt(myImageCodecInfo, pImageCodecInfo)
Next
End If
End Function
Function GDIP_ARGB (ByVal a As Byte, ByVal r As Byte, ByVal g As Byte, ByVal b As Byte) As DWord
Local clr As GDIP_BGRA_UNION
clr.alpha = a
clr.red = r
clr.green = g
clr.blue = b
Function = clr.Colors
End Function
Declare Function GdipDrawString Lib "GDIPLUS.DLL" Alias "GdipDrawString" ( _
ByVal graphics As DWord _ ' __in GpGraphics *graphics
, ByRef Strings As String _ ' __in GDIPCONST WCHAR *string
, ByVal length As Long _ ' __in INT length
, ByVal pFont As DWord _ ' __in GDIPCONST GpFont *font
, ByRef layoutRect As RectF _ ' __in GDIPCONST GpRectF *layoutRect
, ByVal stringFormat As DWord _ ' __in GDIPCONST GpStringFormat *stringFormat
, ByVal brush As DWord _ ' __in GpBrush *brush
) As Long ' GpStatus
Declare Function GdipCreatePen1 Lib "GDIPLUS.DLL" Alias "GdipCreatePen1" ( _
ByVal pColor As DWord, _
ByVal nWidth As Single, _
ByVal unit As Long, _
ByRef pen As DWord _
) As Long
Declare Function GdipDrawRectangle Lib "GDIPLUS.DLL" Alias "GdipDrawRectangle" ( _
ByVal graphics As DWord, _
ByVal pen As DWord, _
ByVal x As Single, _
ByVal y As Single, _
ByVal nWidth As Single, _
ByVal nHeight As Single _
) As Long
Declare Function GdipDeleteBrush Lib "GDIPLUS.DLL" Alias "GdipDeleteBrush" ( _
ByVal brush As DWord _
) As Long
Declare Function GdipDeletePen Lib "GDIPLUS.DLL" Alias "GdipDeletePen" ( _
ByVal pen As DWord _
) As Long
Declare Function GdipDeleteStringFormat Lib "GDIPLUS.DLL" Alias "GdipDeleteStringFormat" ( _
ByVal pFormat As DWord _
) As Long
Declare Function GdipDeleteGraphics Lib "GDIPLUS.DLL" Alias "GdipDeleteGraphics" ( _
ByVal graphics As DWord _
) As Long
'------------------> GdiPlusCreateFontFromName ---------------------------------------------------------------------------------------------------------------------->
'Function GdiPlusCreateFontFromName (ByRef wszFamilyName As String, ByVal emSize As Single, ByVal lStyle As Long, ByVal unit As DWord, ByRef pFont As DWord) As Long
' Local hStatus As Long
' Local pFontFamily As DWord
' hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(wszFamilyName), %NULL, ByVal StrPtr(pFontFamily) )
' If hStatus = %StatusOk And pFontFamily <> %NULL Then
' hStatus = GdipCreateFont(pFontFamily, emSize, lStyle, unit, ByVal StrPtr(pFont))
' GdipDeleteFontFamily(pFontFamily)
' End If
' Function = hStatus
'
'End Function
' ========================================================================================
Declare Function GdipDeleteFontFamily Lib "GDIPLUS.DLL" Alias "GdipDeleteFontFamily" ( _
ByVal fontFamily As DWord _ ' __in GpFontFamily *fontFamily
) As Long ' GpStatus
Declare Function GdipDeleteFont Lib "GDIPLUS.DLL" Alias "GdipDeleteFont" ( _
ByVal Font As DWord _ ' __in GpFont *font
) As Long ' GpStatus
but the string isn't shown. Something I've done wrong?
bye, largo
José Roca
16-11-2011, 05:03
Type RectF
x As Long
y As Long
width As Long
height As Long
End Type
must be
Type RectF
x As Single
y As Single
width As Single
height As Single
End Type
José Roca
16-11-2011, 05:23
Something I've done wrong?
Yes. You are using StrPtr wrongly in all cases except one.
hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, ByVal StrPtr(pFontFamily ) )
must be
hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, pFontFamily )
or
hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, ByVal VarPtr(pFontFamily ) )
etc.
StrPtr is only for strings. It means string pointer.
largo_winch
16-11-2011, 11:18
a) using strptr and varptr in correct order that's the fact, thank you a lot josé! :) now example is running fine. I've changed all wrong strptr into varptr where needed and b) corrected Type RectF udt's into singles (that's what I didn't expected there could be a bigger problem!)
Type RectF
x As Single 'Long
y As Single 'Long
width As Single 'As Long
height As Single 'Long
End Type
here's fine running example for "tb_gdiplus create_StringFormat".
' Empty GUI script created on 11-16-2011 10:04:11 by largo_winch (ThinAIR)
' Empty GUI script created on 11-14-2011 14:33:05 by largo_winch (ThinAIR)
'--------------> GDIPLUS TEST FOR THINBASIC -------------------->
'------------------------->
' Example original from
' http://www.jose.it-berater.org/smfforum/index.php?topic=1827.0
'------------------------->
Uses "UI", "console"
'---------------------------->
'#INCLUDE "GDIPLUS_LW1b.INC"
'---------------------------->
'--------------------------------------------------------------------------------------------------
%UnitPixel = 2 ' Sets each unit to be one device pixel
'--------------------------------------------------------------------------------------------------
'//--------------------------------------------------------------------------
'// FontStyle: face types and common styles
'//--------------------------------------------------------------------------
' enum FontStyle
%FontStyleRegular = 0
%FontStyleBold = 1
%FontStyleItalic = 2
%FontStyleBoldItalic = 3
%FontStyleUnderline = 4
%FontStyleStrikeout = 8
' enum Unit
%UnitWorld = 0 ' // 0 -- World coordinate (non-physical unit)
%UnitDisplay = 1 ' // 1 -- Variable -- for PageTransform only
%UnitPixel = 2 ' // 2 -- Each unit is one device pixel.
%UnitPoint = 3 ' // 3 -- Each unit is a printer's point, or 1/72 inch.
%UnitInch = 4 ' // 4 -- Each unit is 1 inch.
%UnitDocument = 5 ' // 5 -- Each unit is 1/300 inch.
%UnitMillimeter = 6 ' // 6 -- Each unit is 1 millimeter.
Begin ControlID
%Canvas_Gdip
%bClose
End ControlID
'----------------------> problemzone solved by jose roca :)
Type RectF
x As Single 'Long
y As Single 'Long
width As Single 'As Long
height As Single 'Long
End Type
'----------------------> problemzone solved by jose roca :)
Type GDIP_BGRA_STRUCT Byte
blue As Byte
green As Byte
red As Byte
alpha As Byte
End Type
' // Size = 4 bytes
Union GDIP_BGRA_UNION
Colors As DWord
GDIP_BGRA_STRUCT
End Union
'-------------> BEGIN OF EXAMPLE ----------------------->
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function TBMain() As Long
Local hr As Long
Local hDlg As DWord
Local hdc As DWord
Local token As DWord
Local StartupInput As GdiplusStartupInput
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hr = GdiplusStartup(token, StartupInput, ByVal %NULL)
If hr Then
MsgBox "Error initializing GDI+"
Exit Function
End If
Dialog New 0, "tb_gdiplus create_StringFormat",-1,-1, 420, 270, _
%WS_POPUP Or %WS_VISIBLE Or _
%WS_CLIPCHILDREN Or %WS_CAPTION Or _
%WS_SYSMENU Or %WS_MINIMIZEBOX, 0 To hDlg
Dialog Show Modal hDlg, Call dlgProc
' Shutdown GDI+
GdiplusShutdown token
End Function
' ========================================================================================
' ========================================================================================
' Main Dialog procedure
' ========================================================================================
CallBack Function DlgProc() As Long
Local cx, cy, hDc As Long
' -- Test for messages
Select Case CBMSG
Case %WM_INITDIALOG
' -- Place controls here
Dialog Pixels CBHNDL, 400, 250 To Units cx, cy
Control Add Canvas, CBHNDL, %Canvas_Gdip, "", 5, 5, cx+100, cy+100
Control Add Button, CBHNDL, %bClose, "Close", 80+cx, cy+5-84, 50, 18, Call bCloseProc
Canvas_Attach CBHNDL, %Canvas_Gdip, %TRUE
Canvas_Color Rgb(128, 255, 0), Rgb(0, 0, 0)
'Canvas_Clear(Rgb(0,0,0))
Canvas_Scale Pixels
Case %WM_PAINT
GDIP_CreateStringFormat()
Canvas_Redraw
Case %WM_COMMAND
Select Case CBCTL
Case %IDCANCEL
If CBCTLMSG = %BN_CLICKED Then Dialog End CBHNDL, 0
End Select
End Select
End Function
' -- Callback for close button
CallBack Function bCloseProc()
If CBMSG = %WM_COMMAND Then
If CBCTLMSG = %BN_CLICKED Then
' -- Closes the dialog
Dialog End CBHNDL
End If
End If
End Function
'------------------------------> with perfect solution :)
Sub GDIP_CreateStringFormat()
'------------------------------> with perfect solution :)
Local hStatus As Long
Local pGraphics As DWord
Local pPen As DWord
Local pFont As DWord
Local pFontFamily As DWord
Local pFormat As DWord
Local pBlackBrush As DWord
Local strFontName As String
Local strText As String
Local rcf As RECTF
Local fontCollection As DWord
hStatus = GdipCreateFromHDC(Canvas_GetDC, pGraphics)
' // Create the font
strFontName = Ucode$("Arial")
'hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, pFontFamily )
hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(strFontName), %NULL, ByVal VarPtr(pFontFamily) ) '(
If hStatus = %StatusOk And pFontFamily <> %NULL Then '
hStatus = GdipCreateFont(pFontFamily, 16, %FontStyleRegular, %UnitPoint, ByVal VarPtr(pFont ) )
GdipDeleteFontFamily(pFontFamily)
End If
' Note: You can use the wrapper function GdiPlusCreateFontFromName to create the font:
' hStatus = GdiPlusCreateFontFromName("Arial", 16, %FontStyleRegular, %UnitPoint, pFont)
' // Create a solid brush
hStatus = GdipCreateSolidFill(GDIP_ARGB(255, 0, 0, 0), ByVal VarPtr(pBlackBrush ) )
' // Draw the string
rcf.x = 30.0 : rcf.y = 30.0 : rcf.Width = 200.0 : rcf.Height = 25.0
'-------------> problemzone solved ------------------------------------------------->
hStatus = GdipCreateStringFormat(0, %LANG_NEUTRAL, ByVal VarPtr(pFormat) )
'-------------> problemzone solved ------------------------------------------------->
'hStatus = GdipSetStringFormatAlign(pFormat, %StringAlignmentCenter)
strText = Ucode$("Sample text")
hStatus = GdipDrawString(pGraphics, ByVal StrPtr(strText), Len(strText) \ 2, pFont, ByVal VarPtr(rcf), pFormat, pBlackBrush)
' // Create a Pen
hStatus = GdipCreatePen1(GDIP_ARGB(255,0, 0, 0), 3, %UnitPixel, ByVal VarPtr(pPen) )
' // Draw a rectangle
hStatus = GdipDrawRectangle(pGraphics, pPen, rcf.x, rcf.y, rcf.Width, rcf.Height)
' // Cleanup
If pFont Then GdipDeleteFont(pFont)
If pBlackBrush Then GdipDeleteBrush(pBlackBrush)
If pPen Then GdipDeletePen(pPen)
If pFormat Then GdipDeleteStringFormat(pFormat)
If pGraphics Then GdipDeleteGraphics(pGraphics)
End Sub
'-------------> END OF EXAMPLE ----------------------->
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'----------------> GDIP INCLUDE HELPERS ------------------------------------------------------>
' enum FillMode
%FillModeAlternate = 0
%FillModeWinding = 1
'---------------------------------->
%LANG_NEUTRAL = &H00??
%LANG_INVARIANT = &H7f??
'---------------------------------->
' enum StringAlignment
' // Left edge for left-to-right text,
' // right for right-to-left text,
' // and top for vertical
%StringAlignmentNear = 0
%StringAlignmentCenter = 1
%StringAlignmentFar = 2
Declare Function GdipSetStringFormatAlign Lib "GDIPLUS.DLL" Alias "GdipSetStringFormatAlign" ( _
ByVal pFormat As DWord, _
ByVal align As Long _
) As Long
Declare Function GdipCreateStringFormat Lib "GDIPLUS.DLL" Alias "GdipCreateStringFormat" ( _
ByVal formatAttributes As Long _ ' __in INT formatAttributes
, ByVal language As Word _ ' __in LANGID language
, ByRef format As DWord _ ' __out GpStringFormat **format '''[out] Pointer to a variable that receives a pointer to the new StringFormat object.
) As Long ' GpStatus
Declare Function GdipCreateFromHDC Lib "GDIPLUS.DLL" Alias "GdipCreateFromHDC" ( _
ByVal hdc As DWord _
, ByRef graphics As DWord _
) As Long
Declare Function GdipCreateFontFamilyFromName Lib "GDIPLUS.DLL" Alias "GdipCreateFontFamilyFromName" ( _
ByRef pName As String _ ' __in GDIPCONST WCHAR *name
, ByVal fontCollection As DWord _ ' __in GpFontCollection *fontCollection
, ByRef fontFamily As DWord _ ' __out GpFontFamily **fontFamily
) As Long ' GpStatus
Declare Function GdipCreateSolidFill Lib "GDIPLUS.DLL" Alias "GdipCreateSolidFill" ( _
ByVal pColor As DWord _ ' __in ARGB color
, ByRef brush As DWord _ ' __out GpSolidFill **brush
) As Long ' GpStatus
Declare Function GdipDeleteFontFamily Lib "GDIPLUS.DLL" Alias "GdipDeleteFontFamily" ( _
ByVal fontFamily As DWord _ ' __in GpFontFamily *fontFamily
) As Long ' GpStatus
Declare Function GdipCreateFont Lib "GDIPLUS.DLL" Alias "GdipCreateFont" ( _
ByVal fontFamily As DWord _ ' __in GDIPCONST GpFontFamily *fontFamily
, ByVal emSize As Single _ ' __in REAL emSize
, ByVal style As Long _ ' __in INT style
, ByVal unit As Long _ ' __in GpUnit unit
, ByRef pFont As DWord _ ' __out GpFont **font
) As Long ' GpStatus
'----------------------------------------------------------->
' -- Definitions from Josés headers
%StatusOk = 0
Type GdiplusStartupInput
GdiplusVersion As DWord
DebugEventCallback As DWord
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
If SizeOf(GdiplusStartupInput) <> 16 Then MsgBox 0, "Invalid size of GdiplusStartupInput"
Type GdiplusStartupOutput
NotificationHook As DWord
NotificationUnhook As DWord
End Type
If SizeOf(GdiplusStartupOutput) <> 8 Then MsgBox 0, "Invalid size of GdiplusStartupOutput"
Type EncoderParameter
pGuid As String * 16 ' // GUID of the parameter
NumberOfValues As DWord ' // Number of the parameter values
dwType As DWord ' // Value type, like ValueTypeLONG etc.
Value As DWord ' // A pointer to the parameter values
End Type
If SizeOf(EncoderParameter) <> 28 Then MsgBox 0, "Invalid size of EncoderParameter"
Type EncoderParameters
Count As DWord ' // Number of parameters in this structure
Parameter As EncoderParameter ' // Parameter values - variable-length array
End Type
If SizeOf(EncoderParameters) <> 32 Then MsgBox 0, "Invalid size of EncoderParameters"
Type ImageCodecInfo
Clsid As String * 16 ' CLSID
FormatID As String * 16 ' GUID
CodecName As Word Ptr ' const WCHAR*
DllName As Word Ptr ' const WCHAR*
FormatDescription As Word Ptr ' const WCHAR*
FilenameExtension As Word Ptr ' const WCHAR*
MimeType As Word Ptr ' const WCHAR*
Flags As DWord ' DWORD
Version As DWord ' DWORD
SigCount As DWord ' DWORD
SigSize As DWord ' DWORD
SigPattern As Byte Ptr ' const BYTE*
SigMask As Byte Ptr ' const BYTE*
End Type
If SizeOf(ImageCodecInfo) <> 76 Then MsgBox 0, "Invalid size of ImageCodecInfo"
Declare Function GdiplusStartup Lib "GDIPLUS.DLL" Alias "GdiplusStartup" (
ByRef token As DWord ' __out token ULONG_PTR
, ByRef input As GdiplusStartupInput ' __in input GdiplusStartupInput <record>
, ByRef output As GdiplusStartupOutput ' __out output GdiplusStartupOutput <record>
) As Long ' GpStatus
Declare Function GdipLoadImageFromFile Lib "GDIPLUS.DLL" Alias "GdipLoadImageFromFile" (
ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef pImage As DWord ' __out GpImage **image
) As Long ' GpStatus
Declare Function lstrlenw Lib "KERNEL32.DLL" Alias "lstrlenW" ( _
ByVal lpString As DWord _ ' __in LPCWSTR lpString
) As Long
Declare Function GdipGetImageEncodersSize Lib "GDIPLUS.DLL" Alias "GdipGetImageEncodersSize" (
ByRef numEncoders As DWord ' __in UINT *numEncoders
, ByRef Size As DWord ' __out UINT *size
) As Long ' Status
Declare Function GdipGetImageEncoders Lib "GDIPLUS.DLL" Alias "GdipGetImageEncoders" (
ByVal numEncoders As DWord ' __in UINT numEncoders
, ByVal Size As DWord ' __in UINT size
, ByRef encoders As Any ' __out ImageCodecInfo *encoders
) As Long ' Status
Declare Function GdipSaveImageToFile Lib "GDIPLUS.DLL" Alias "GdipSaveImageToFile" (
ByVal Image As DWord ' __in GpImage *image
, ByVal filename As DWord ' __in GDIPCONST WCHAR *filename
, ByRef clsidEncoder As Guid ' __in GDIPCONST CLSID clsidEncoder
, ByRef encoderParams As EncoderParameters ' __out GDIPCONST EncoderParameters *encoderParams
) As Long
Declare Function GdipDisposeImage Lib "GDIPLUS.DLL" Alias "GdipDisposeImage" (
ByVal Image As DWord ' __in GpImage *image
) As Long ' GpStatus
Declare Sub GdiplusShutdown Lib "GDIPLUS.DLL" Alias "GdiplusShutdown" ( _
ByVal token As DWord _ ' __in token ULONG_PTR
)
' void
Function GdiPlusGetEncoderClsid (ByVal strMimeType As String) As String
Local hr As Long
Local pImageCodecInfo As DWord
Local numEncoders As DWord
Local nSize As DWord
Local i As Long
Local wstrlen As Long
Local sMimeType As String
hr = GdipGetImageEncodersSize(numEncoders, nSize)
Dim buffer(nSize) As Byte
pImageCodecInfo = VarPtr(buffer(1))
Local myImageCodecInfo As ImageCodecInfo At pImageCodecInfo
hr = GdipGetImageEncoders(numEncoders, nSize, ByVal pImageCodecInfo)
If hr = 0 Then
For i = 1 To numEncoders
wstrlen = lstrlenW(myImageCodecInfo.MimeType)
If wstrlen Then sMimeType = Acode$(Peek$(myImageCodecInfo.MimeType, wstrlen * 2))
If InStr(Ucase$(sMimeType), Ucase$(strMimeType)) Then
Function = GuidTxt$(myImageCodecInfo.Clsid)
Exit For
End If
pImageCodecInfo += SizeOf(ImageCodecInfo) '// Increments pointer
SetAt(myImageCodecInfo, pImageCodecInfo)
Next
End If
End Function
Function GDIP_ARGB (ByVal a As Byte, ByVal r As Byte, ByVal g As Byte, ByVal b As Byte) As DWord
Local clr As GDIP_BGRA_UNION
clr.alpha = a
clr.red = r
clr.green = g
clr.blue = b
Function = clr.Colors
End Function
Declare Function GdipDrawString Lib "GDIPLUS.DLL" Alias "GdipDrawString" ( _
ByVal graphics As DWord _ ' __in GpGraphics *graphics
, ByRef Strings As String _ ' __in GDIPCONST WCHAR *string
, ByVal length As Long _ ' __in INT length
, ByVal pFont As DWord _ ' __in GDIPCONST GpFont *font
, ByRef layoutRect As RectF _ ' __in GDIPCONST GpRectF *layoutRect
, ByVal stringFormat As DWord _ ' __in GDIPCONST GpStringFormat *stringFormat
, ByVal brush As DWord _ ' __in GpBrush *brush
) As Long ' GpStatus
Declare Function GdipCreatePen1 Lib "GDIPLUS.DLL" Alias "GdipCreatePen1" ( _
ByVal pColor As DWord, _
ByVal nWidth As Single, _
ByVal unit As Long, _
ByRef pen As DWord _
) As Long
Declare Function GdipDrawRectangle Lib "GDIPLUS.DLL" Alias "GdipDrawRectangle" ( _
ByVal graphics As DWord, _
ByVal pen As DWord, _
ByVal x As Single, _
ByVal y As Single, _
ByVal nWidth As Single, _
ByVal nHeight As Single _
) As Long
Declare Function GdipDeleteBrush Lib "GDIPLUS.DLL" Alias "GdipDeleteBrush" ( _
ByVal brush As DWord _
) As Long
Declare Function GdipDeletePen Lib "GDIPLUS.DLL" Alias "GdipDeletePen" ( _
ByVal pen As DWord _
) As Long
Declare Function GdipDeleteStringFormat Lib "GDIPLUS.DLL" Alias "GdipDeleteStringFormat" ( _
ByVal pFormat As DWord _
) As Long
Declare Function GdipDeleteGraphics Lib "GDIPLUS.DLL" Alias "GdipDeleteGraphics" ( _
ByVal graphics As DWord _
) As Long
Declare Function GdipDeleteFontFamily Lib "GDIPLUS.DLL" Alias "GdipDeleteFontFamily" ( _
ByVal fontFamily As DWord _ ' __in GpFontFamily *fontFamily
) As Long ' GpStatus
Declare Function GdipDeleteFont Lib "GDIPLUS.DLL" Alias "GdipDeleteFont" ( _
ByVal Font As DWord _ ' __in GpFont *font
) As Long ' GpStatus
'------------------> GdiPlusCreateFontFromName ---------------------------------------------------------------------------------------------------------------------->
'Function GdiPlusCreateFontFromName (ByRef wszFamilyName As String, ByVal emSize As Single, ByVal lStyle As Long, ByVal unit As DWord, ByRef pFont As DWord) As Long
' Local hStatus As Long
' Local pFontFamily As DWord
' hStatus = GdipCreateFontFamilyFromName(ByVal StrPtr(wszFamilyName), %NULL, ByVal StrPtr(pFontFamily) )
' If hStatus = %StatusOk And pFontFamily <> %NULL Then
' hStatus = GdipCreateFont(pFontFamily, emSize, lStyle, unit, ByVal StrPtr(pFont))
' GdipDeleteFontFamily(pFontFamily)
' End If
' Function = hStatus
'
'End Function
' ========================================================================================
c) thanks petr for his help and patience too :) to work at night it's not even good for me because of losing concentration after hard working day at my job!
bye, largo
ErosOlmi
16-11-2011, 11:18
StrPtr is only for strings. It means string pointer.
Interesting (and embarrassing). I will add more error checking in StrPtr and VarPtr functions.
José Roca
16-11-2011, 22:33
And more specifically, for dynamic strings. The reason is that, with these kind of variables, VarPtr returns the address of the string descriptor and StrPtr the address of the string data. For all other kind of variables, including null-terminated strings and fixed-length strings, VarPtr must be used.