Post by Rod on Apr 24, 2018 3:23:16 GMT -5
Rotation has been mentioned elsewhere so I though I would post a couple of examples of rotating .bmps by API. The first uses the blitter and PlgBlt There are tutorials on the wiki.
dial.bmp (234.42 KB)mask.bmp (5.52 KB)
'needle and dial side by side, our graphics resource.
loadbmp "dial","dial.bmp"
'now get its handle
dialImage=hbmp("dial")
'since we know the size we simply set
dialWidth=200
dialHeight=200
'now load the mask to use when blitting the needle
imagePath$="mask.bmp"
flags = _LR_MONOCHROME or _LR_LOADFROMFILE
calldll #user32, "LoadImageA",_
0 as ulong,_ 'instance - use 0 for image from file
imagePath$ as ptr,_ 'path and filename of image
_IMAGE_BITMAP as long,_ 'type of image
dialWidth as long,_ 'desired width
dialHeight as long,_ 'desired height
flags as long,_ 'load flags
maskImage as Ulong 'handle of loaded image
nomainwin
WindowWidth=800
WindowHeight=600
UpperLeftX=(DisplayWidth-WindowWidth)/2
UpperLeftY=(DisplayHeight-WindowHeight)/2
graphicbox #1.g, 0,0,WindowWidth,WindowHeight
open "Parallelogram Blt" for window as #1
#1 "trapclose [quit]"
'we need bmp images to establish the DCs
#1.g "down;fill lightgray"
#1.g "getbmp buf 0 0 800 600"
'now get handles
bufImage=hbmp("buf")
'now choose to place the dial image centre screen
'placement of the dial is defined by its centre point
#1.g "home ; posxy dialMidX dialMidY"
'calculate the dialX and dialY locations for the size
dialX=int(dialMidX-dialWidth/2)
dialY=int(dialMidY-dialHeight/2)
' now set up a memory DC and a buffer DC
' double buffering will stop the flickering
h=hwnd(#1.g) 'graphicbox handle
'get device context for window:
calldll #user32, "GetDC",_
h as ulong,_ 'graphicbox handle
hdc as ulong 'returns handle to device context
'create a copy in memory
calldll #gdi32,"CreateCompatibleDC",_
hdc as uLong,_
memdc as uLong
'put our needle and dial image in it
CallDLL #gdi32,"SelectObject",_
memdc as uLong,_
dialImage as uLong,_
oldObject as uLong
'create a copy as our buffer
'the buffer is 800x600 so more than one dial can be drawn.
calldll #gdi32,"CreateCompatibleDC",_
memdc as uLong,_
bufdc as uLong
'put our background image in it
CallDLL #gdi32,"SelectObject",_
bufdc as uLong,_
bufImage as uLong,_
oldObject as uLong
STRUCT lpPoint,_
x1 as long,_ 'ulx
y1 as long,_ 'uly
x2 as long,_ 'urx
y2 as long,_ 'ury
x3 as long,_ 'llx
y3 as long 'lly
angle=45
timer 100, [draw]
wait
[draw]
'blit the buffer to the screen so that it is in view and persists
'for as long as possible so eliminating flicker
CallDll #gdi32, "BitBlt",_
hdc as ulong,_ 'The destination DC
0 as long,_ 'x location on destination
0 as long,_ 'y location on destination
800 as long,_ 'width to transfer
600 as long,_ 'height to transfer
bufdc as ulong,_ 'The source DC
0 as long,_ 'x location in source
0 as long,_ 'y location in source
_SRCCOPY as ulong,_ 'dwRasterOperation
result as long
angle=angle+1
if angle=361 then angle=1
'now blit out dial image to the buffer to overwrite the last needle
'the image is located at 200,0 in the memdc
CallDll #gdi32, "BitBlt",_
bufdc as ulong,_ 'The destination DC
dialX as long,_ 'x location on destination
dialY as long,_ 'y location on destination
dialWidth as long,_ 'width to transfer
dialHeight as long,_ 'height to transfer
memdc as ulong,_ 'The source DC
200 as long,_ 'x location in source
0 as long,_ 'y location in source
_SRCCOPY as ulong,_ 'dwRasterOperation
result as long
'use some trig to map out our three points on a circle
lpPoint.x1.struct=dialMidX-(150*cos(angle/57.29577951))
lpPoint.y1.struct=dialMidY-(150*sin(angle/57.29577951))
lpPoint.x2.struct=dialMidX-(150*cos((angle+90 mod 360)/57.29577951))
lpPoint.y2.struct=dialMidY-(150*sin((angle+90 mod 360)/57.29577951))
lpPoint.x3.struct=dialMidX-(150*cos((angle+270 mod 360)/57.29577951))
lpPoint.y3.struct=dialMidY-(150*sin((angle+270 mod 360)/57.29577951))
'now plgblt the needle image to the buffer
calldll #gdi32, "PlgBlt",_
bufdc as ulong,_ 'device context of graphicbox
lpPoint as struct,_ 'array of points
memdc as ulong,_ 'memory DC
0 as long,_ 'ulx source
0 as long,_ 'uly source
dialWidth as long,_ 'width source
dialHeight as long,_ 'height source
maskImage as ulong,_ 'mask bmp handle, null = not used
0 as long,_ 'ulx mask
0 as long,_ 'uly mask
re as long 'nonzero=success
'method to flush GDI graphics:
'#1.g "getbmp pix 0 0 ";winWide;" ";winHigh
'#1.g "drawbmp pix 0 0;flush"
wait
[quit]
calldll #user32, "ReleaseDC",_
h as ulong,_ 'window handle
hdc as ulong,_ 'device context
ret as long
CallDLL #gdi32, "DeleteDC",memdc as uLong, r As Boolean
CallDLL #gdi32, "DeleteDC",bufdc as uLong, r As Boolean
close #1:end
dial.bmp (234.42 KB)mask.bmp (5.52 KB)