Transparent .png images
Posted: Wed Jan 16, 2008 4:01 am
I have a piece of code that I have cobbled together from bits on the forum that shows images with a transparent background that I have used as backround pictures (fancy icons really) to run odds and ends. It may not be great programming and I don't fully understand it but it works!
The question is - Is there a way of making a suitable modification to this or is there a better way to show a series of same sized images to make a simple animation?
Obviously the requirements are using a borderless window that stays behind all other windows, that can be moved, has a transparent background, utilises a menu and does not suck up too much CPU time. Or to put it another way exactly what I have but allowing changing the image every few seconds, I'm not after 30fps !
P.S. the bit at the start MonitorX & MonitorY is because one of the menu items is to save the screen position. Another being to close the prog if required as well as the bits it is actually designed for.
Code: Select all
;
; Saved as Garfield StarterPicture.exe
;
Define.l MonitorX, MonitorY
Define.s MyFile$ = "C:\Users\Whatever"
If ReadFile(1, MyFile$)
MonitorX = ReadLong(1)
MonitorY = ReadLong(1)
CloseFile(1)
Else
MonitorX = 1280
MonitorY = 948
EndIf
UsePNGImageDecoder()
Procedure.l Exist(File$) ;- Check a drive + file exists, without system requesters etc.
Protected EFlag.l, OldErrorMode.l, Junk.l
OldErrorMode = SetErrorMode_(1) ; Turn off screen error messages
If GetFileAttributes_(@File$)=-1 ; Get file butes. -1 = fail
Junk.l=GetLastError_() ; Get last error, to flush system
SetLastError_(0) ; Set error to zero
EFlag.l = 0 ; Return value to flag FAIL
Else
EFlag.l = 1 ; Return value to flag a PASS
EndIf
SetErrorMode_(OldErrorMode) ; Reset the error flags
ProcedureReturn EFlag
EndProcedure
;
Procedure Error(message.s, fatal.b)
ErrorBuffer$ = Space(256)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError_(), 0, ErrorBuffer$, Len(ErrorBuffer$), 0)
MessageRequester("Error", message+Chr(10)+Chr(10)+ErrorBuffer$, 0)
If fatal
End
EndIf
EndProcedure
Global MDIFrame, MDIClient, hChild, hStatus, hToolBar, hMainMenu, hChildMenu, ActiveMDIChild
Global xPos, yPos, WindowWidth, WindowHeight, ChildNumber, ExtraWidth, ExtraHeight
Global hInstance
Global wc.WNDCLASSEX
Global ClassName$
Structure GdiplusStartupInput
GdiplusVersion.l
DebugEventCallback.l
SuppressBackgroundThread.l
SuppressExternalCodecs.l
EndStructure
Structure bsize
width.l
height.l
EndStructure
Structure bpoint
x.l
y.l
EndStructure
Structure ARGB
blue.b
green.b
red.b
alpha.b
EndStructure
Structure ImageItemInfo
Clsid.CLSID ; Codec identifier.
FormatID.GUID ; File format identifier. GUIDs that identify various file formats (ImageFormatBMP, ImageFormatEMF, And the like) are defined in Gdiplusimaging.h.
CodecName.s ; WCHAR * Pointer To a null-terminated string that contains the codec name.
DllName.s ; WCHAR * Pointer To a null-terminated string that contains the path name of the DLL in which the codec resides. If the codec is not in a DLL, this pointer is NULL.
FormatDescription.s ; WCHAR * Pointer To a null-terminated string that contains the name of the file format used by the codec.
FilenameExtension.s ; WCHAR * Pointer To a null-terminated string that contains all file-name extensions associated with the codec. The extensions are separated by semicolons.
MimeType.s ; WCHAR * Pointer To a null-terminated string that contains the mime type of the codec.
Flags.l ; DWORD Combination of flags from the ImageCodecFlags enumeration.
Version.l ; DWORD Integer that indicates the version of the codec.
SigCount.l ; DWORD Integer that indicates the number of signatures used by the file format associated with the codec.
SigSize.l ; DWORD Integer that indicates the number of bytes in each signature.
SigPattern.l ; BYTE * Pointer To an array of bytes that contains the pattern For each signature.
SigMask.l ; BYTE * Pointer To an array of bytes that contains the mask For each signature.
EndStructure
Global Gdiplus, gdiplusToken, bitmap, hbmReturn, encoderClsid
Global *GdiplusStartup, *GdipCreateBitmapFromFile, *GdipCreateHBITMAPFromBitmap, *GdipGetImageHeight, *GdipGetImageWidth, *GdiplusShutdown, *GdipSaveImageToFile, *GdipGetImageEncodersSize, *GdipGetImageEncoders, *GdipCreateBitmapFromHBITMAP
Procedure OpenImageFile(File$)
result = 0
If Gdiplus
FileWSize = (Len(File$)*2)+2
*FileW = CoTaskMemAlloc_(FileWSize)
If *FileW
If MultiByteToWideChar_(#CP_ACP, 0, File$, -1, *FileW, FileWSize)
bitmap.l = 0
CallFunctionFast(*GdipCreateBitmapFromFile, *FileW, @bitmap)
If bitmap
hbmReturn.l = 0
CallFunctionFast(*GdipCreateHBITMAPFromBitmap, bitmap, @hbmReturn, 0)
Else
Error("GdipCreateBitmapFromFile() failed."+Chr(10)+File$+" is not a valid image file.", 0)
EndIf
EndIf
Else
SetLastError_(#ERROR_NOT_ENOUGH_MEMORY)
EndIf
CoTaskMemFree_(*FileW)
EndIf
ProcedureReturn hbmReturn
EndProcedure
CoInitialize_(#Null)
Gdiplus = OpenLibrary(0, "GDIPLUS.DLL")
If Gdiplus
*GdiplusStartup = GetFunction(0, "GdiplusStartup")
If *GdiplusStartup
gdpsi.GdiplusStartupInput
gdpsi\GdiplusVersion = 1
gdpsi\DebugEventCallback = 0
gdpsi\SuppressBackgroundThread = 0
gdpsi\SuppressExternalCodecs = 0
CallFunctionFast(*GdiplusStartup, @gdiplusToken, gdpsi, #Null)
If gdiplusToken
*GdipCreateBitmapFromFile = GetFunction(0, "GdipCreateBitmapFromFile")
*GdipCreateHBITMAPFromBitmap = GetFunction(0, "GdipCreateHBITMAPFromBitmap")
*GdipGetImageWidth = GetFunction(0, "GdipGetImageWidth")
*GdipGetImageHeight = GetFunction(0, "GdipGetImageHeight")
*GdipGetImageEncodersSize = GetFunction(0, "GdipGetImageEncodersSize")
*GdipGetImageEncoders = GetFunction(0, "GdipGetImageEncoders")
*GdipCreateBitmapFromHBITMAP = GetFunction(0, "GdipCreateBitmapFromHBITMAP")
*GdipSaveImageToFile = GetFunction(0, "GdipSaveImageToFile")
*GdiplusShutdown = GetFunction(0, "GdiplusShutdown")
Else
Gdiplus = 0
EndIf
Else
Gdiplus = 0
EndIf
Else
Gdiplus = 0
EndIf
File$ = "C:\Users\Something.png"
LoadImage(1, File$)
Myimwid = ImageWidth(1)
Myimht = ImageHeight(1)
FreeImage(1)
bitmap1 = OpenImageFile(File$)
hwnd=OpenWindow(0, MonitorX, MonitorY, Myimwid, Myimht, "Monitor Offulator", #PB_Window_BorderLess|#PB_Window_Invisible)
SetWindowLong_(hwnd,#GWL_EXSTYLE,#WS_EX_TOOLWINDOW) ; this bit stops the window appearing on the toolbar if called before the window is visible
ShowWindow_(WindowID(0),#SW_SHOW) ; make the window visible and it will / won't be on the toolbar depending on OnTopFlag
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, GetWindowLong_(WindowID(0),#GWL_EXSTYLE)|$00080000)
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 1)
If CreatePopupMenu(1)
; whatever
EndIf
width1.l=0
screenDc=GetDC_(#Null)
memDc=CreateCompatibleDC_(screenDc)
oldbitmap=SelectObject_(memDc, bitmap1)
GetObject_(bitmap1,SizeOf(BITMAP),bmInfo.BITMAP)
bitmapsize.bsize
bitmapsize\width=bmInfo\bmWidth
bitmapsize\height=bmInfo\bmHeight
pointsource.bpoint
pointsource\x=0
pointsource\y=0
ExamineDesktops()
topPos.bpoint ; this is where the image appears on the screen
topPos\x= MonitorX
topPos\y= MonitorY
BlendFunc.blendfunction
BlendFunc\blendop=0
BlendFunc\blendflags=0
BlendFunc\sourceconstantalpha=255
BlendFunc\alphaformat=1
UpdateLayeredWindow_(WindowID(0), screenDc, topPos, bitmapsize, memDc, pointsource, 0, BlendFunc, 2)
ReleaseDC_(#Null,screenDc)
SelectObject_(memDc,oldbitmap)
DeleteObject_(hbitmap)
DeleteDC_(memDc)
SetWindowPos_(WindowID(0),#HWND_BOTTOM,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE)
;
Repeat
Select WaitWindowEvent()
Case #WM_LBUTTONDOWN
ReleaseCapture_()
SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
SetWindowPos_(WindowID(0),#HWND_BOTTOM,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE)
Case #WM_RBUTTONDOWN ; right mouse button was clicked =>
DisplayPopupMenu(1, WindowID(0)) ; now display the popup-menu
SetWindowPos_(WindowID(0),#HWND_BOTTOM,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE)
Case #PB_Event_Menu ; an item of the popup-menu was clicked
Select EventMenu()
; do whatever
EndSelect
EndSelect
ForEver
;
;
Obviously the requirements are using a borderless window that stays behind all other windows, that can be moved, has a transparent background, utilises a menu and does not suck up too much CPU time. Or to put it another way exactly what I have but allowing changing the image every few seconds, I'm not after 30fps !
P.S. the bit at the start MonitorX & MonitorY is because one of the menu items is to save the screen position. Another being to close the prog if required as well as the bits it is actually designed for.