This thread is to post your questions about GDImage ...
I've been very pleased with the functionality of GDImage, though I'm having problems with rotating an image that I've loaded from my program's resource file. Here is the boiled down code that shows where I'm struggling:
#PBFORMS CREATED
'SED_PBWIN
#COMPILE EXE
#DIM ALL
#PBFORMS BEGIN INCLUDES
#RESOURCE "DMV.pbr"
#INCLUDE "DMV.inc"
#PBFORMS END INCLUDES
'--------------------------------------------------------------------------------
' ** Constants **
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
#PBFORMS BEGIN CONSTANTS
%IDD_DIALOG1 = 101
%IDC_GDimageCTRL1 = 102
%ID_TIMER1 = 103
%ID_BITMAP_ARROW = 1 ' Bitmap overlay
#PBFORMS END CONSTANTS
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
' ** Declarations **
'--------------------------------------------------------------------------------
DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
declare sub DisplayArrow(hDlg as long)
#PBFORMS DECLARATIONS
'--------------------------------------------------------------------------------
' Search for "GDImage" in the source code
#INCLUDE "GDImage.inc" ' GDImage
'$MyImage1 = "level01.jpg" + "<fit>" ' GDImage (edit this using a full path name to image)
$MyImage1 = "" + "<fit>" ' GDImage (edit this using a full path name to image)
global lHor as long, lVer as long, lDep as LONG, lDir as LONG, ghCtrl&
'--------------------------------------------------------------------------------
FUNCTION PBMAIN()
RegisterGDImageClass ' GDImage
ShowDIALOG1 %HWND_DESKTOP
END FUNCTION 'PBMAIN
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
' ** CallBacks **
'--------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()
local hBitmapFromResource&
SELECT CASE AS LONG CBMSG
CASE %WM_INITDIALOG
STATIC idEvent AS LONG
'Initialization handler
'Load Arrow Bitmap from resource, and create a BITMAP overlay
ghCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
if hBitmapFromResource& = 0 then hBitmapFromResource& = ZI_LoadBitmap("BMP_ARROW") ' Load it ONLY ONCE !
CALL ZD_DrawBitmapToCtrl(ghCtrl&, 174, 0, hBitmapFromResource&, ZD_ColorARGB(255,0), %ID_BITMAP_ARROW, %ZS_VISIBLE)
ZD_SetObjectLocked %ID_BITMAP_ARROW, %TRUE
'Create WM_TIMER events with the SetTimer API at 500 ms (0.5 s) interval
idEvent = SetTimer(CBHNDL, %ID_TIMER1, 500, BYVAL %NULL)
DIALOG POST CBHNDL, %WM_TIMER, %ID_TIMER1, 0 ' force an initial %WM_TIMER "event"
CASE %WM_TIMER ' Posted by the created timer
IF CBWPARAM = %ID_TIMER1 THEN ' Make sure it's corrent timer id
'Do some processing here that's removed
DisplayArrow cbhndl
END IF
CASE %WM_PALETTECHANGED
'if in 256 color mode, switching between app's with different palettes
'can cause weird results. Trapping %WM_PALETTECHANGED and redrawing
'entire dialog helps some. Maybe not the best solution, but..
IF CBWPARAM <> CBHNDL THEN
RedrawWindow CBHNDL, BYVAL 0, BYVAL 0, %RDW_INVALIDATE OR %RDW_UPDATENOW
END IF
CASE %WM_DESTROY
'is sent when program ends - a good place to delete created
'objects and store settings in file for next run, etc.
'-------------------------------------------------------------
CASE %WM_NCACTIVATE
STATIC hWndSaveFocus AS DWORD
IF ISFALSE CBWPARAM THEN
' Save control focus
hWndSaveFocus = GetFocus()
ELSEIF hWndSaveFocus THEN
' Restore control focus
SetFocus(hWndSaveFocus)
hWndSaveFocus = 0
END IF
CASE %WM_COMMAND
' Process control notifications
SELECT CASE AS LONG CBCTL
CASE %IDCANCEL
IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
DIALOG END CBHNDL, 0
END IF
END SELECT
END SELECT
END FUNCTION 'ShowDIALOG1Proc
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
LOCAL lRslt AS LONG
#PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
LOCAL hDlg AS DWORD
DIALOG NEW hParent, "Demise Map Viewer", 43, 58, 497, 413, %WS_POPUP OR %WS_BORDER OR _
%WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR _
%DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, $MyImage1, 7, 5, 423, 390, %WS_CHILD OR _
%WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
#PBFORMS END DIALOG
'Example for above as PBForms always jacks it up.
'CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, $MyImage1, 7, 5, 420, 190
DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
#PBFORMS BEGIN CLEANUP %IDD_DIALOG1
#PBFORMS END CLEANUP
FUNCTION = lRslt
END FUNCTION 'ShowDIALOG1
'--------------------------------------------------------------------------------
sub DisplayArrow(hDlg as long)
local lHorP as LONG, lVerP as long
'Layout looks like this:
'1,45 45,45
'1, 1 45, 1
lHor = 24 'Horizontal coordinate
lVer = 3 'Vertical coordinate
lDep = 1 'Which map we're on
lDir = 2 'Direction facing
lHorP = (lHor * 14) - 12
lVerP = ((45 - lVer) * 14) + 2
select CASE lDir
case 1 'North
ZD_SetObjectRotation %ID_BITMAP_ARROW, 0
case 2 'East
CALL ZD_SetObjectAngle(%ID_BITMAP_ARROW, 90, %TRUE)
'ZD_SetObjectRotation %ID_BITMAP_ARROW, 90
'ZD_RotateObjectClockWise90 (%ID_BITMAP_ARROW)
case 3 'South
ZD_SetObjectRotation %ID_BITMAP_ARROW, 180
'ZD_FlipObjectY %ID_BITMAP_ARROW
case 4 'West
'ZD_SetObjectRotation (%ID_BITMAP_ARROW, 270)
END SELECT
ZD_SetObjectXY %ID_BITMAP_ARROW, lHorP, lVerP, 1
CALL ZI_UpdateWindow(ghCtrl&, %TRUE)
END SUB
Here's a zip archive that is compilable but does not include the GDImage.dll file or the includes. I'm using the demo version available from the ZAP site that is version 4.06 (according to the header file).
<I've pulled the link as it's been replaced>
...in the SUB DisplayArrow I update the placement of an arrow against a map background based on a timer. When my program is ran, the arrow moves along just fine using the SUB as it is; but, it doesn't face the way that I would like. I'd like to have it point east when traveling east and so on. The placement is pulled from a game. In the above SUB I've given sample coordinates to showcase the basics. I've tried a few things that you can see in the SELECT CASE to no avail. Any ideas or am I horribly butchering something?
Donnie,
I am not comfortable with the DDT proprietary syntax, however the first thing that comes to my mind is that your arrow PNG file uses an original angle rotation of 90° instead of 0°, and that could explain the problem you have to perform the correct rotation of your arrow.
If you are looking at a clock, then three = 0°, while twelve = 90°, nine = 180°, six = 270°.
Also with PNG file you must always use
CALL ZD_UsePngOpacity(%ID_BITMAP_ARROW, %TRUE)
in order to use alpha channel and zooming capabilities
'Initialization handler
'Load Arrow Bitmap from resource, and create a BITMAP overlay
ghCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
if hBitmapFromResource& = 0 then hBitmapFromResource& = ZI_LoadBitmap("BMP_ARROW") ' Load it ONLY ONCE !
CALL ZD_DrawBitmapToCtrl(ghCtrl&, 174, 0, hBitmapFromResource&, ZD_ColorARGB(255,0), %ID_BITMAP_ARROW, %ZS_VISIBLE)
CALL ZD_UsePngOpacity(%ID_BITMAP_ARROW, %TRUE)
CALL ZD_SetObjectAngle(%ID_BITMAP_ARROW, 180, %TRUE)
This is perfect. I was able to incorporate what you showed me and placed it in my code. It very neatly works now.
Hi. I try to use the:
I call:
---------------------------
MsgBox "Past #1 "
Call ZI_GetImageSizeFromFile ("c:\aFireFly\GDImage\image.jpg", 0, 0 )
MsgBox "Result #2 = " + Str$(imgWidth)
Call test()
..............
SUB ZI_GetImageSizeFromFile ( _
zFullPathName As Asciiz, _ ' The name graphic file size.
imgWidth As Long, _ ' Width of the picture.
imgHeight As Long _ ' Height of the picture.
)
MsgBox "Past #3 here "
End Sub
'------------------------------
Sub test()
MsgBox "Past #4 testsub ok "
End Sub
-------------------------------
Result
display Past #1
display Result #2 = 0
display Past #4 testsub ok
-------------------------------
It seem it never go to sub ZI_GetImageSizeFromFile
I never see Past #3 here
I use your trail version
I download today not sure about the way I code.
but my kind of trace help me to figure out I have a problem.
I try to use Firefly 2.91
Thanks.
Robert,
ZI_GetImageSizeFromFile is a GDImage API, thus you are not allowed to duplicate the name of this API in your own code, that is a NoNo.
Also to get the width and height values, you must first declare in your code two numeric parameters like this:
LOCAL imgWidth, imgHeight AS LONG
Then use the API this way:
CALL ZI_GetImageSizeFromFile("c:\aFireFly\GDImage\image.jpg", imgWidth, imgHeight)
MsgBox STR$(imgWidth) + STR$(imgHeight)
...
Thanks more clear, now it work well but to came back to
my goal to resize image I find 1 command to seize image.
Call ZI_GetImageSizeFromFile ("c:\aFireFly\GDImage\10.jpg", imgWidth, imgHeight )
imgWidth=imgWidth / 10
imgHeight=imgHeight / 10
ZI_FitImageFromFile("c:\aFireFly\GDImage\10.jpg",imgWidth,imgHeight)
But I don't know where the fitImage go in memory? or where?
How to sent this image to hWndForm, I never sent this image to hWndForm.
Now if I want to use the only one else commande to save:
ZI_SaveBitmapToFile("c:\aFireFly\GDImage\10n.jpg",hWndForm,80)
Easy to see is not working the hWndForm have no instruction.
I read all the function 1 by 1 to find how to resize image that only 2
function I find. Again few for zomming a lot of get but not to many
for set image.
I am right?, It look you convert all image (Jpg, Tif, gif, etc.) to bitmap,
at that point you modify you play with the way you want, and if we
want to save the result; you convert again to save in any format.
1 more question: when I use:
gnCtrl = CreateWindowEx(ExStyles, _ ' 0
ClassName, _ ' "ZIMAGECTRL"
Caption, _ ' Full path to default image ""
Styles, _ ' %WS_CHILD Or %WS_VISIBLE
nLeft, nTop, nWidth, nHeight, _
hWndParent, IDC_FORM1_GDIMAGECONTROL, _
GetModuleHandle(ByVal %Null), _
ByVal %Null)
If I got no picture It came with, BLACK windows, can we change that color
by white or any or transparency.
The color is just the look but the way to use resize or save is all the program.
Thanks again.
Robert,
Please studdy the examples provided with the trial version, then start modifying one of them to achieve your goal.
Usualy the ZI_FitimageFromFile returns a resized bitmap handle that must be assigned to a GDImage graphic control.
But if you want you can save the newly created bitmap directly to disk, using ZI_SaveBitmap.
GDImage is able to handle either GDI bitmap or GDIPLUS bitmap (image).
There is also a low level GDImage API to convert from Bitmap to Image (GDIPLUS), its name is zBitmapToImage.
See the convert.bas example, i think it could help you, and it can't be simpler than that:
#COMPILE EXE "convert.exe"
%WINAPI = 1
%WM_USER = &H400
TYPE POINTS
x AS INTEGER
y AS INTEGER
END TYPE
#INCLUDE "gdimage.inc"
FUNCTION PBMAIN
LOCAL hBitmap AS LONG, ErrorCode AS LONG
hBitmap = ZI_FitImageFromFile("C:\multimedia\pictures\skins\wallpapers\cogs2.jpg", 48, 48)
ErrorCode = ZI_SaveBitmapToFile("c:\travail\gdimage\icon.jpg", hBitmap, 0)
CALL DeleteObject(hBitmap)
END FUNCTION
Thanks Patrice
I post the result:
http://www.jose.it-berater.org/smfforum/index.php?topic=2966.msg9040#msg9040
With the help for drag and drop from: Paul Squires
and the project is done. Voila! 8)
I got the drop and drag.
The resize all image and .ext
The preview image for the result.
The detection for not graphics file.
The performance.
Thanks to answer: "all my questions".
Robert.
Robert,
When saving to JPEG you can select the Quality (using the last parameter of ZI_SaveBitmapToFile).
GDImage's default for JPEG is always the highest quality if you don't specify a value (see the CHM help file).
...
Robert,
I forget to say that you must delete the bitmap object when you are done, using:
CALL DeleteObject(hBitmap)
The example code has been a great boon to me in having some fun with graphics.. I didn't realize that I would have to do so much math though. I've edited the zoomplus.bas file a bit to show my question. If you right-click on the black square of Monaco you'll get the coordinates around 301, 209. If you zoom all the way in, recenter Monaco and click the black square, you'll get 211, 192. If you maximize the dialog, recenter Monaco I got 543, 476 with my settings. I understand that I'm getting different coordinates because of the size of the image and the zoom factor; but, is it possible to mathematically get them all to match? What would I need to do to accomplish that?
Feel free to look at the attachment; but, I think I'm getting closer to solving this. I'll post a changed attachment if I do. I will be out of town for a few days so it might be a bit.
Donnie,
GDImage does already the hard work for you.
ZI_GetCropCoordinates API returns real coordinates as if you were viewing without zoom factor (1/1)
I noticed that; but, I'd prefer a mouse-click instead of creating a crop rectangle. I don't see any other way to use that SUB. I've got it figured out when the user resizes the dialog or maximizes; but, no luck yet on zooming. Hopefully I'll get a chance to tackle it when I'm back.
Well, I'm going to keep working on it; but, I've not figured it out yet. I'm sure that the ZI_GetZoomValue is part of the equation; but, I'm stumped. Patrice, do you mind sharing how the ZI_GetCropCoordinates API gains it's information? I feel like I should be getting this; but, I'm not.
On another note (and still using the zoomplus.bas example), if I added a sprite above Monaco, would it be possible that once zoomed in we could automatically center the sprite and the background image would still scroll with it using ZD_SetObjectScroll? Any similar examples or should I start tinkering?
Donnie,
Here are some insights to help you:
Note: X1, Y1 are the mouse coordinates and hWnd is the handle of the GDImage control.
LOCAL lpr AS RECT, ZoomValue AS SINGLE, nW, nH, ZoomWidth, ZoomHeight, xOffset, yOffset, imgWidth, imgHeight AS LONG
' Get current Zoom value
ZoomValue! = ZI_GetZoomValue(hWnd)
' Retrieve the size of the memory bitmap
CALL ZI_GetImageSizeFromControl(hWnd, nW&, nH&)
' Get the client size of the control
CALL GetClientRect(hWnd, lpr)
' Compute x,y offset
ZoomWidth& = nW& * ZoomValue!
ZoomHeight& = nH& * ZoomValue!
xOffset& = 0: yOffset& = 0
IF ZoomWidth& < lpr.nRight OR ZoomHeight& < lpr.nBottom THEN
IF ZoomWidth& < lpr.nRight THEN xOffset& = (lpr.nRight - ZoomWidth&) \ 2
IF ZoomHeight& < lpr.nBottom THEN yOffset& = (lpr.nBottom - ZoomHeight&) \ 2
END IF
' Compute real coordinates
IF ZoomValue! > 0 THEN
x1& = (x1& - xOffset&) / ZoomValue!
y1& = (y1& - yOffset&) / ZoomValue!
imgWidth& = imgWidth& / ZoomValue!
imgHeight& = imgHeight& / ZoomValue!
END IF
For your other question you can always change the location of a sprite at any time.
The ZI_GetXscroll and ZI_GetYscroll API give you the horizontal and vertical scroll range for a specific GDImage control.
Donnie
Here is a WinDev procedure that is being used to display the mouse coordinates in a GDImage ZOOM control.
It can be easily translated to PowerBASIC
PROCEDURE GDImageDisplayMouseXY(hWnd is int, x is int, y is int)
lpr is RECT
// Get current Zoom value
ZoomValue is 4-byte real = ZI_GetZoomValue(hWnd)
// Retrieve the size of the memory bitmap
nW, nH are int; ZI_GetImageSizeFromControl(hWnd, nW, nH)
// Get the client size of the control
GetClientRect(hWnd, lpr)
// Compute x,y offset
ZoomWidth is int = nW * ZoomValue
ZoomHeight is int = nH * ZoomValue
xOffset is int = 0; yOffset is int = 0
IF ZoomWidth < lpr:nRight OR ZoomHeight < lpr:nBottom THEN
IF ZoomWidth < lpr:nRight THEN xOffset = Round((lpr:nRight - ZoomWidth) / 2)
IF ZoomHeight < lpr:nBottom THEN yOffset = Round((lpr:nBottom - ZoomHeight)/ 2)
END
// Retrieve scroll values
xCurrentScroll is int = ZI_GetXscroll(hWnd)
yCurrentScroll is int = ZI_GetYscroll(hWnd)
// Show mouse coordinates
SC_Coord.X = NumToString(Round((x + xCurrentScroll - xOffset) / ZoomValue, 0))
SC_Coord.Y = NumToString(Round((y + yCurrentScroll - yOffset) / ZoomValue, 0))
Donnie,
I have posted a WinDev project named
GeneScene there:
http://www.zapsolution.com/demo/GeneScene.zip (http://www.zapsolution.com/demo/GeneScene.zip)
It displays a map(s) with pushpin sprites spread on it.
Each pushpin is a hot spot that does match a specific tunnel (Try with the one named "l'Arme" located above Monaco).
You will see also on this example that the mouse X,Y location is shown below the map while you are moving the mouse, and it display the correct location whatever the zoom being used.
Perhaps it is something like that you want to achieve?
This is perfect! For whatever reason, I'm not able to replicate that functionality when I'm zoomed in. I must be letting something slide somewhere.
GDImage allows you to process/monitor all the messages of its graphic controls via a callback procedure.
Note: in the GeneScene project all the pushpins (except one) are clone objects, this is a very unique GDImage feature.
I was handling the current scroll in the wrong spot. The WinDev post though nearly the same as the PB showed me where I was screwing up. I was so sure that some of my own code was accurate I was blinded to the truth. I've attached the zoomplus sample with my changes in case anyone else is interested. The output information is sent as a debug string. I capture those with DebugView.
A few more questions. I have a bit of code:
'Find current zoom and scoll values
hCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
ZoomValue! = ZI_GetZoomValue(hCtrl&)
xCurrentScroll = ZI_GetXscroll(hCtrl&)
yCurrentScroll = ZI_GetYscroll(hCtrl&)
'Load the new image
call GDImageLoadFile(cbhndl, FilName$)
'Reassign zoom and scroll values after loading file
CALL ZI_SetZoomValue(hCtrl&, ZoomValue!)
CALL ZI_SetZoomScrollInfo(hCtrl&, ZoomValue!, ZoomValue!)
call ZI_SetProperty(hCtrl&, %ZI_Horizontal, xCurrentScroll)
call ZI_SetProperty(hCtrl&, %ZI_Vertical, yCurrentScroll)
...that while checking each of the values they seem to be fine. Unfortunately, the image control doesn't show the changed %ZI_Horizontal and %ZI_Vertical settings, instead they show the default zero. I tossed in a redraw for fun and still don't see anything. Anything I might be overlooking?
Also, I can see from ZD_GetObjectQuality that you can change the rendering quality. Is it possible to have no adjustment at all when zooming and such? I'd like to see pixels and all without any interpolation.
Donnie,
A GDImage ZOOM control always use HALFTONE interpolation, because the zoom can be smaller than the 1/1 pixel ratio (for example 0.33)
If you want to have full control on your image, then use it as a sprite object (a layer floating above the background, like in PhotoShop). See on this forum the PhotoSetup demo project.
Then you have a bunch of properties you can apply to your sprite, see all the API prefixed with ZD_SetOblect... and ZD_GetObject... in the GDImage.inc file (the include file is more accurate than the CHM help file).
To facilitate the manipulation of GDImage's sprite object use a Sprite type like this one
TYPE SpriteStruct
ID is int '// The unique sprite object IDentifier
objtype is int '// The object type
filename is string ASCIIZ on MAX_PATH '// File of the sprite bitmap
label is string ASCIIZ on 64 '// Friendly name
xPos is int '// X location
yPos is int '// Y location
xWidth is int '// Width of the sprite object
yHeight is int '// Height of the sprite object
ARGB is int '// ARGB color
visibility is int '// ZS_HIDDEN or ZS_VISIBLE state
scrollmode is int '// True/False scrolling mode
opacity is int '// True/False PNG opacity
userotate is int '// Rotate90FlipNone or Rotate270FlipNone
flipmode is int '// ZD_Reverse (FlipX) or ZD_Flip (FlipY) constant
angle is int '// Rotation angle 0-360
locked is int '// True/False condition
zorder is int '// The z-order value
scale is 4-byte real '// The scale value
style is int '// The object style
quality is int '// The object quality
clone is int '// The unique ID of the cloned object
'//
resizeW is int '// Resize width to use
resizeH is int '// Resize height to use
trueW is int '// True width of the native bitmap
trueH is int '// True height of the native bitmap
selected is 1-byte unsigned int '// Selected status
reserved is string ASCIIZ on 111 '// For future extension
END TYPE
I can't remember exactly what you want to achieve, because i lost a part of my latest e-mails during the blown up of my notebook, that occured 9 days ago.
Here is a WinDev example showing how to assign a GDImage sprite array.
This one can be very easily translated to PowerBASIC
WD []: is PB ().
WD : is PB .
WD zItem is ZOBJECT is PB DIM zItem AS ZOBJECT
the ZD_GetObjectProperties API allows you to retrieve all the properties of a sprite object in one single call.
'// Assign the ZOBJECT structure/type parameters to the Sprite array
PROCEDURE SpriteArrayGet(ID is int)
x, y, xW, yH are int
'//ZD_GetObjectXY(ID, x, y)
'//ZD_GetObjectBound(ID, xW, yH)
'//gSprite[ID]:ID = ID '// The unique sprite object IDentifier
'//gSprite[ID]:objtype = ZD_GetObjectType(ID) '// The object type (bitmap, text, arrow, curve, rectangle, ellipse, polypolyline)
'//gSprite[ID]:label = ZD_GetObjectImageLabel(ID) '// Friendly name
'//gSprite[ID]:xPos = x '// X location
'//gSprite[ID]:yPos = y '// Y location
'//gSprite[ID]:xWidth = xW '// Width of the sprite object
'//gSprite[ID]:yHeight = yH '// Height of the sprite object
'//gSprite[ID]:ARGB = ZD_GetObjectARGBcolor(ID) '// ARGB color
'//gSprite[ID]:visibility = ZD_IsObjectVisible(ID) '// ZS_HIDDEN or ZS_VISIBLE state
'//gSprite[ID]:scrollmode = ZD_GetObjectScroll(ID) '// Scrolling mode
'//gSprite[ID]:opacity = ZD_GetObjectOpacity(ID) '// True/False PNG opacity
'//gSprite[ID]:userotate = ZD_GetObjectRotation(ID) '// Rotate90FlipNone or Rotate270FlipNone
'//gSprite[ID]:flipmode = ZD_GetObjectFlipMode(ID) '// True/False condition
'//gSprite[ID]:angle = ZD_GetObjectAngle(ID) '// Rotation angle 0-360
'//gSprite[ID]:locked = ZD_GetObjectLocked(ID) '// True/False condition
'//gSprite[ID]:zorder = ZD_GetObjectZorder(ID) '// The z-order value
'//gSprite[ID]:scale = ZD_GetObjectScale(ID) '// The scale value
'//gSprite[ID]:style = ZD_GetObjectStyle(ID) '// The object style
'//gSprite[ID]:quality = ZD_GetObjectQuality(ID) '// The object quality
'//gSprite[ID]:clone = ZD_GetObjectClone(ID) '// The unique ID of the cloned object
'//gSprite[ID]:selected = 0 '// Set selected status to Off
zItem is ZOBJECT
ZD_GetObjectProperties(ID, zItem) '// Retrieves all the details about a GDImage sprite object in one single step.
gSprite[ID]:ID = ID '// The unique sprite object IDentifier
gSprite[ID]:objtype = zItem:objType '// The object type (bitmap, text, arrow, curve, rectangle, ellipse, polypolyline)
gSprite[ID]:label = zItem:objLabel '// Friendly name
gSprite[ID]:xPos = zItem:x1 '// X location
gSprite[ID]:yPos = zItem:y1 '// Y location
gSprite[ID]:xWidth = zItem:x2 '// Width of the sprite object
gSprite[ID]:yHeight = zItem:y2 '// Height of the sprite object
gSprite[ID]:ARGB = zItem:useARGB '// ARGB color
gSprite[ID]:visibility = zItem:visibility '// ZS_HIDDEN or ZS_VISIBLE state
IF BinaryAND(zItem:Style, ZS_SCROLL) = ZS_SCROLL THEN '// Scrolling mode
gSprite[ID]:scrollmode = -1
ELSE
gSprite[ID]:scrollmode = 0
END
gSprite[ID]:opacity = zItem:opacity '// True/False PNG opacity
gSprite[ID]:userotate = zItem:userotate '// Rotate90FlipNone or Rotate270FlipNone
gSprite[ID]:flipmode = zItem:flipmode '// True/False condition
gSprite[ID]:angle = zItem:angle '// Rotation angle 0-360
gSprite[ID]:locked = zItem:locked '// True/False condition
gSprite[ID]:zorder = zItem:order '// The z-order value
gSprite[ID]:scale = zItem:scale '// The scale value
gSprite[ID]:style = zItem:Style '// The object style
gSprite[ID]:quality = zItem:quality '// The object quality
gSprite[ID]:clone = zItem:clone '// The unique ID of the cloned object
gSprite[ID]:selected = 0 '// Set selected status to Off
I can only find one example of using GDImage with PowerBasic DDT Controls – the GDWDDT example. This is clear, but what I can't see is how to do more than create the control (and give it an initial image):
CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
$MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
%WS_EX_RIGHTSCROLLBAR
Works fine, but how do I then get a handle to do other tasks on the control? Eg:
ZD_FillRect (handle, 0, 0, 200, 200, color)
I tried ZI_GetDC and CONTROL HANDLE, but neither worked ...
Perhaps there is a more comprehensive example of using DDT? I can't easily use direct Windows SDK as I am adding graphics to an existing program ...
Pete,
See the code below in
red.
Quote
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
LOCAL lRslt AS LONG
LOCAL hDlg AS DWORD
DIALOG NEW hParent, "DDT + GDImage image control ", 108, 135, 434, 337, %WS_POPUP OR _
%WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
%WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
%DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
%WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
' GDImage
CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
$MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
%WS_EX_RIGHTSCROLLBAR
LOCAL hCtl AS LONG
CONTROL HANDLE hDlg, %IDC_GDimageCTRL1 TO hCtl
ZD_FillRect(ZI_GetDC(hCtl), 10,10, 50,50, RGB(255,0,0))
' GDImage
CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL2, _
$MyImage2, 152, 210, 130, 110, %WS_CHILD OR _
%WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
%WS_EX_RIGHTSCROLLBAR
DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
FUNCTION = lRslt
END FUNCTION
Note: ZD_FillRect draw a rectangle onto the provided DC using a 24-bit RGB color.
If you want to draw a rectangle with an ARGB color (alpha channel), then use ZD_DrawRectangleToCtrl.
I would rather manipulate GDImage sprite objects (multiple layers) than drawing using a DC.
Drawing using a DC = static image, GDImage sprite objects = dynamic image (you can change the location, z-order, and all parameters of each object).
...
Perfect, thanks Patrice.
The ZD_FillRect example above will only draw over the background image. If there is no background image loaded (ie the CONTROL ADD specified "" as the image name) or the image is smaller than the control, ZD_FillRect only draws over the image, or not at all (if there is no image).
I know I can create a sprite overlay, but all I want is to set a background colour for the image area before I load the background bitmap (has to happen later).
Also tried ZI_PaintBrushBitmap, but it has been deprecated (help file needs updating).
Thanks
Pete
Pete
There are several ways to tell GDImage how to paint a specific control background:
Using a gradient color
CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientTop, RGB(93,3,28))
CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientBottom, RGB(146,3,40))
Using a flat color with same color for Top and Bottom
CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientTop, RGB(255,0,0))
CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientBottom, RGB(255,0,0))
Using a tiled background
hTiledBitmap& = ZI_CreateBitmapFromFile("038.jpg", 0,0)
CALL ZI_SetTiledBackground(hCtrl&, hTiledBitmap&)
And of course using an image for background (that could be resized on the fly to match the control size).
See all details in the Resource.bas example.
...
And the next ...
Taking the GDWDDT example again, if we add a sprite to the GDImage Control:
CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
$MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
%WS_EX_RIGHTSCROLLBAR
LOCAL hCtl AS LONG
CONTROL HANDLE hDlg, %IDC_GDimageCTRL1 TO hCtl
ZD_FillRect(ZI_GetDC(hCtl), 10,10, 50,50, RGB(255,0,0))
ZD_DrawRectangleToCtrl(hCtl, 10,10,100,100, &HFFFFFFFF, 0, %IDC_Sprite, %ZS_VISIBLE, %ZD_DRAW_FILLED)
We get a nice independant sprite rectangle overlaid, which we can move, manipulate (and remove) without affecting the underlying image. This is really cool.
Two questions:
1. Without adding any code to GDWDDT, hovering over the sprite changes the mouse cursor, and you can drag the sprite anywhere you want in the GDImage control. Again, very cool, EXCEPT if you don't want the user to be able to do this .... How do we prevent the mouse hover and the drag?
2. With a standard PowerBasic Image control, adding the %SS_NOTIFY attribute causes the callback to fire if the user clicks anywhere on the control. But the same does not happen with the custom control. How do we get mouseclicks on the GDImage control, and how do we get them one of the sprites?
Thanks!
Quote1. Without adding any code to GDWDDT, hovering over the sprite changes the mouse cursor, and you can drag the sprite anywhere you want in the GDImage control. Again, very cool, EXCEPT if you don't want the user to be able to do this .... How do we prevent the mouse hover and the drag?
Easy, just lock and disable the sprite image, using:
ZD_SetObjectLocked(nSpriteID, %TRUE)Quote2. How do we get mouseclicks on the GDImage control, and how do we get them one of the sprites?
Use a
GDImage callback, in correlation with the
ZI_EventMessage you want to monitor.
Search in the
AEROGLASS demo project for:
CALL ZI_EventMessage(CODEPTR(MyCallBack), %WM_LBUTTONDOWN, %TRUE)and look inside
FUNCTION MyCallBack(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
LOCAL sMessage AS STRING, ObjectID AS LONG, rc AS RECT, nRet AS LONG
LOCAL x AS LONG, y AS LONG
nRet = %FALSE ' Do not stop the event processing in GDImage
IF hWnd = GetDlgItem(hMain, %ID_CTRL) THEN ' In case we use the same callback for several GDImage control
' make sure that we handle the good one.
SELECT CASE LONG Msg
CASE %WM_LBUTTONDOWN
ObjectID = ZI_MouseOverObjectID()
IF ObjectID = GetDlgCtrlID(hWnd) THEN LabelIs$ = $Background ELSE LabelIs$ = ZD_GetObjectImageLabel(ObjectID)
'nID& = ZD_GetItemObjectAndColorAtXY(hWnd, LO(INTEGER, lParam), HI(INTEGER, lParam), ColorRGB&)
sMessage = "WM_LBUTTONDOWN on object" + str$(ObjectID) + " >" + LabelIs$ + "<" '+ str$(nID&)+" &H"+HEX$(ColorRGB&)
CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))
CASE %WM_RBUTTONDOWN
ObjectID = ZI_MouseOverObjectID()
IF ObjectID = GetDlgCtrlID(hWnd) THEN LabelIs$ = $Background ELSE LabelIs$ = ZD_GetObjectImageLabel(ObjectID)
sMessage = "WM_RBUTTONDOWN on object" + str$(ObjectID) + " >" + LabelIs$ + "< at location" + str$(LOWRD(lParam))+","+str$(HIWRD(lParam))
CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))
CASE %WM_MOUSEMOVE
ObjectID = ZI_GetMovingSpriteID()
IF ObjectID THEN
' Does %ID_BTN_CHECK is checked ?
IF SendMessage(GetDlgItem(GetParent(hWnd), %ID_BTN_CHECK), %BM_GETCHECK, 0, 0) THEN
x = LOWRD(lParam): y = HIWRD(lParam)
xCurrentScroll& = ZI_GetProperty(hWnd, %ZI_Horizontal)
yCurrentScroll& = ZI_GetProperty(hWnd, %ZI_Vertical)
ZD_GetObjectXY(ObjectID, x1&, y1&)
ZD_GetObjectXYcapture(ObjectID, xCapture&, yCapture&)
DX& = (x - xCapture& + xCurrentScroll&) - x1&
DY& = (y - yCapture& + yCurrentScroll&) - y1&
FOR ID& = %ID_FIRST TO %ID_LAST
IF ID& <> ObjectID THEN
CALL ZD_GetObjectXY(ID&, x, y)
' Add the DX,DY offset
CALL ZD_SetObjectXY(ID&, x + DX&, y + DY&, %ZD_DRAW_DEFERRED) ' Move, without immediate redraw
END IF
NEXT
' Note: The display's refresh is yeld by the default GDImage WM_MOUSE event
END IF
END IF
CASE %WM_KEYDOWN
ObjectID = ZI_GetObjectFocusID()
IF ObjectID THEN
CALL ZD_GetObjectXY(ObjectID, x, y)
x1& = x ' Make a copy to keep the orignal x location unchanged
y1& = y ' Make a copy to keep the orignal y location unchanged
' Check accelerator keys to compute the step range
IF ZI_IsCtrlKeyPressed THEN
UseStep& = 4
IF ZI_IsShiftKeyPressed THEN UseStep& = 16
ELSEIF ZI_IsShiftKeyPressed THEN
UseStep& = 2
ELSE
UseStep& = 1
END IF
IF ZD_GetObjectScroll(ObjectID) THEN ' If object scroll with the bitmap background
' Get the size of the bitmap background
CALL ZI_GetBitmapSize(ZI_GetBMP(GetDlgItem(hMain, %ID_CTRL)), useWidth&, useHeight&)
ELSE
' Get the control client size
CALL GetClientRect(GetDlgItem(hMain, %ID_CTRL), rc)
useWidth& = rc.nRight: useHeight& = rc.nBottom
END IF
' Get the sprite object size
CALL ZD_GetObjectBound(ObjectID, BoundWidth&, BoundHeight&)
x2Div2& = (BoundWidth& \ 2): y2Div2& = BoundHeight& \ 2
SELECT CASE wParam
CASE %VK_HOME
x1& = 0
CASE %VK_END
x1& = MAX&(useWidth& - BoundWidth&, 0)
CASE %VK_PRIOR
y1& = 0
CASE %VK_NEXT
y1& = MAX&(useHeight& - BoundHeight&, 0)
CASE %VK_LEFT, %VK_NUMPAD4
IF x1& > -x2Div2& THEN x1& = MAX&(x1& - UseStep&, -x2Div2&)
CASE %VK_UP, %VK_NUMPAD8
IF y1& > -y2Div2& THEN y1& = MAX&(y1& - UseStep&, -y2Div2&)
CASE %VK_RIGHT, %VK_NUMPAD6
IF x1& < useWidth& - x2Div2& THEN
x1& = MIN&(x1& + UseStep&, useWidth& - x2Div2&)
END IF
CASE %VK_DOWN, %VK_NUMPAD2
IF y1& < useHeight& - y2Div2& THEN
y1& = MIN&(y1& + UseStep&, useHeight& - y2Div2&)
END IF
END SELECT
IF x <> x1& OR y <> y1& THEN
x = x1&: y = y1&
CALL ZD_SetObjectXY(ObjectID, x1&, y1&, %TRUE)
END IF
sMessage = "Object" + str$(ObjectID) + " coordinates" + str$(x&)+","+str$(y&)
CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))
END IF
END SELECT
END IF
FUNCTION = nRet
END FUNCTION