PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → Hors-sujet → Exemple d'animation WD12 avec les API bas niveau
Exemple d'animation WD12 avec les API bas niveau
Débuté par Patrice TERRIER, 24 sep. 2008 13:38 - Aucune réponse
Posté le 24 septembre 2008 - 13:38
Je partage avec vous un exemple montrant comment créer une animation temps réel à partir d'une image PNG 32-bit avec opacité variable et anti-aliasing.

J'ai écrit ce projet pour voir jusqu'où l'on pouvait aller dans l'utilisation de l'API bas niveau avec WinDev. Il n'y a donc aucun appel aux fonctions du w-langage, et tout le code est contenu dans la section "code source du projet".
Ce qui permet de réduire le framework WinDev aux 2 seules WD120VM.DLL et WD12STD.DLL lorsqu'on "compile" le projet.

Il existe une version de GoldFish codée en code managé sous C#, écrite par Davidwu (www.cnpopsoft.com).

La version que je vous propose est basée uniquement sur la FLAT API, elle ne nécessite donc pas le framework DotNET pour fonctionner.

La seule fonction qui m'a posé un problème sous windev est la gestion du code UNICODE lors de l'utilisation de l'API GDIPLUS "GdipLoadImageFromFile", pour laquelle je me suis servi de la fonction équivalente "zLoadImageFromFile" (GDImage).

Note: Afin de faciliter la conversion de ce code, celui-ci est écrit en anglais afin de ressembler au langage "BASIC" dont la syntaxe est très proche.

CODE D'INITIALISATION DU PROJET
CONSTANT
MAX_PATH = 260
ERROR_ALREADY_EXISTS = 183
AC_SRC_OVER = 0x00
AC_SRC_ALPHA = 0x01
SW_SHOW = 5
SW_RESTORE = 9
WM_DESTROY = 0x0002
WM_NCHITTEST = 0x0084
WM_KEYDOWN = 0x0100
WM_TIMER = 0x0113
HTCAPTION = 2
WS_POPUP = 0x80000000
WS_EX_TOPMOST = 0x00000008
WS_EX_LAYERED = 0x00080000
CS_VREDRAW = 0x0001
CS_HREDRAW = 0x0002
CS_DBLCLKS = 0x0008
PM_REMOVE = 0x0001
ULW_ALPHA = 0x00000002
SM_CXSCREEN = 0
SM_CYSCREEN = 1
IDC_ARROW = 32512

GDI32 = "GDI32"
USER32 = "USER32"
GDIPLUS = "GDIPLUS"
GDIMAGE = "GDIMAGE"
END

POINTAPI is structure
x is int // long x
y is int // long y
END

SIZEL is structure
cx is int // long x
cy is int // long y
END

RECT is structure
nLeft is int // long Left
nTop is int // long top
nRight is int // long Right
nBottom is int // long bottom
END

SECURITY_ATTRIBUTES is structure
nLength is int // DWORD nLength
lpSecurityDescriptor is int // LPVOID lpSecurityDescriptor
bInheritHandle is int // BOOL bInheritHandle
END

TagMSG is structure
hWnd is int// HWND hwnd
nMessage is int// UINT Message
wParam is int// WPARAM wParam
lParam is int// LPARAM lParam
nTime is int// DWORD time
pt is POINTAPI// POINT pt
END

BITMAP is structure
bmType is int//Type C : LONG
bmWidth is int//Type C : LONG
bmHeight is int//Type C : LONG
bmWidthBytes is int//Type C : LONG
bmPlanes is 2-byte int//Type C : WORD
bmBitsPixel is 2-byte int//Type C : WORD
bmBits is int//Type C : LPVOID
END

BLENDFUNCTION is structure
BlendOp is 1-byte int
BlendFlags is 1-byte int
SourceConstantAlpha is 1-byte int
AlphaFormat is 1-byte int
END

WNDCLASSEXA is structure
cbSize is unsigned int//Type C : UINT
style is unsigned int//Type C : UINT
lpfnWndProc is int//Type C : WNDPROC
cbClsExtra is int//Type C : int
cbWndExtra is int//Type C : int
hInstance is int//Type C : HINSTANCE
hIcon is int//Type C : HICON
hCursor is int//Type C : HCURSOR
hbrBackground is int//Type C : HBRUSH
lpszMenuName is int//Type C : LPCSTR
lpszClassName is int//Type C : LPCSTR
hIconSm is int//Type C : HICON
END

BITMAPINFOHEADER is structure
biSize is int
biWidth is int
biHeight is int
biPlanes is 2-byte int
biBitCount is 2-byte int
biCompression is int
biSizeImage is int
biXPelsPerMeter is int
biYPelsPerMeter is int
biClrUsed is int
biClrImportant is int
END

RGBQUAD is structure
bBlue is 1-byte int
bGreen is 1-byte int
bRed is 1-byte int
bReserved is 1-byte int
END

BITMAPINFO_API is structure
bmiHeader is BITMAPINFOHEADER//BITMAPINFOHEADER est une autre structure
bmiColors is RGBQUAD//RGBQUAD est une autre structure
END

GdiplusStartupInput is structure
GdiplusVersion is int // Must be 1
DebugEventCallback is int // Ignored on free builds
SuppressBackgroundThread is int // False unless you//re prepared TO call
SuppressExternalCodecs is int // False unless you want GDI+ only TO Use
END

gnToTheRight, gnFrame are int // To store SetImage static values

gsIMAGE_FullPathName is string = CompleteDir(fExeDir()) + "GoldFish.png"
gnFRAME_SizeX is int = 84 // Must match the animation frame width
gnFRAME_SizeY is int = 84 // Must match the animation frame height
gnFRAME_Count is int = 20 // The frame number
gnUSE_StepX is int = 3 // X step value in pixel
gnUSE_StepY is int = 1 // Y step value in pixel

LOCAL
IF LoadDLL(GDIMAGE) THEN

// The WinMain section

nRet, x, y are int
wc is WNDCLASSEXA
zClass is string ASCIIZ on 16 = "ZANIMATION"
wcStyle is int = CS_HREDRAW + CS_VREDRAW
IsInitialized is int = API(USER32, "GetClassInfoExA", Instance, &zClass, &wc)
IF IsInitialized = 0 THEN
wc:cbSize = Dimension(wc)
wc:style = wcStyle
wc:lpfnWndProc = &WndProc
wc:cbClsExtra = 0
wc:cbWndExtra = 0 // Extend_cbWndExtra * 4
wc:hInstance = Instance
wc:hIcon = API(USER32, "LoadImageA", Null, "GoldFish.ico", 1, 0, 0, 0x00000010 + 0x00000040)
wc:hCursor = API(USER32, "LoadCursorA", Null, IDC_ARROW)
wc:hbrBackground = Null
wc:lpszMenuName = Null
wc:lpszClassName = &zClass
wc:hIconSm = Null
IF API(USER32, "RegisterClassExA", &wc) THEN IsInitialized = True
END

IF IsInitialized THEN
x = Max((API(USER32, "GetSystemMetrics", SM_CXSCREEN) - gnFRAME_SizeX) / 2, 0)
y = Max((API(USER32, "GetSystemMetrics", SM_CYSCREEN) - gnFRAME_SizeY) / 2, 0)

hMain is int = API(USER32, "CreateWindowExA", ...
WS_EX_LAYERED, ...// SDK extended style
zClass, ... // Set this one to your default path name
"GoldFish", ...// Caption
WS_POPUP + WS_EX_TOPMOST, ...// SDK style
x, ...// X location
y, ...// Y location
gnFRAME_SizeX, ...// Control width
gnFRAME_SizeY, ...// Control height
Null, ... // Parent handle
0, ...// Control ID
Instance, ...// Instance
0)

IF hMain THEN

Msg is TagMSG
SetImage(hMain, gsIMAGE_FullPathName, 255)
API(USER32,"ShowWindow", hMain, SW_SHOW)

IF gnFRAME_Count > 1 THEN API(USER32, "SetTimer", hMain, 1, 50, Null)
WHILE API(USER32, "GetMessageA", &Msg, Null, 0, 0)
API(USER32, "TranslateMessage", &Msg)
API(USER32, "DispatchMessageA", &Msg)
END
IF gnFRAME_Count > 1 THEN API(USER32,"KillTimer", hMain, 1)

nRet = Msg:wParam

END

END

END


PROCEDURES GLOBALES
Procedure SetImage(LOCAL hWnd is int, LOCAL sFileName is string, LOCAL alpha is int)
graphics, desktopDC, hMemDC, hBmp, OldBmp, Img, nImgW, nImgH, ImgAttr, x, y, nStepX, nStepY, nOrientation are int
rw is RECT
Bmp is BITMAP
bi is BITMAPINFO_API
nDwp is unsigned int
bf is BLENDFUNCTION
lp, ptSrc are POINTAPI
lpSize is SIZEL

//static gnToTheRight, gnFrame AS long

API(USER32,"GetWindowRect", hWnd, &rw)
lpSize:cx = rw:nRight - rw:nLeft; lpSize:cy = rw:nBottom - rw:nTop

InitRandom()
nStepX = gnUSE_StepX; nStepY = ((Random() - 0.5) * 1.5) * gnUSE_StepY
lp:y = rw:nTop + nStepY
IF gnToTheRight THEN
IF rw:nRight < API(USER32, "GetSystemMetrics", SM_CXSCREEN) + lpSize:cx THEN
lp:x = rw:nLeft + nStepX
ELSE
gnToTheRight = 0
lp:x = rw:nLeft - nStepX
END
ELSE
IF rw:nLeft > - lpSize:cx THEN
lp:x = rw:nLeft - nStepX
ELSE
gnToTheRight = -1
lp:x = rw:nLeft + nStepX
END
END

IF gnToTheRight THEN nOrientation = 4 ELSE nOrientation = 0

gnFrame++; IF gnFrame > gnFRAME_Count THEN gnFrame = 1

Img = API(GDIMAGE, "zLoadImageFromFile", (sFileName), &nImgW, &nImgH, nOrientation)
IF Img THEN

desktopDC = API(USER32, "GetDC", 0)

// Draw active frame to new memory DC
hMemDC = API(GDI32, "CreateCompatibleDC", desktopDC)
hBmp = API(GDI32, "CreateCompatibleBitmap", desktopDC, nImgW, nImgH)
OldBmp = API(GDI32, "SelectObject", hMemDC, hBmp)
IF API(GDIPLUS, "GdipCreateFromHDC", hMemDC, &graphics) = 0 THEN
API(GDIPLUS, "GdipDrawImageRectRectI", graphics, Img, 0, 0, lpSize:cx, lpSize:cy, gnFrame * lpSize:cx - lpSize:cx, 0, lpSize:cx, lpSize:cy, 2, ImgAttr, 0, 0)
API(GDIPLUS, "GdipDeleteGraphics", graphics)
API(GDIPLUS, "GdipDisposeImage", Img)
END

API(GDI32, "GetObjectA", hBmp, Dimension(Bmp), &Bmp)

bf:BlendOp = AC_SRC_OVER
bf:BlendFlags = 0
bf:AlphaFormat = AC_SRC_ALPHA // Use source alpha
bf:SourceConstantAlpha = alpha

API(USER32, "SetWindowPos", hWnd, -1, 0, 0, 0, 0, 3) // Keep it topmost
API(USER32, "UpdateLayeredWindow", hWnd, desktopDC, &lp, &lpSize, hMemDC, &ptSrc, 0, &bf, ULW_ALPHA)

END

API(GDI32, "SelectObject", hMemDC, OldBmp)
API(GDI32, "DeleteObject", hBmp)
API(GDI32, "DeleteDC", hMemDC)
API(USER32, "ReleaseDC", 0, desktopDC)
Procedure WndProc(LOCAL hWnd is int, LOCAL Msg is int, LOCAL wParam is int, LOCAL lParam is int)
nRet is int

SWITCH Msg

CASE WM_KEYDOWN
IF wParam = 0x1B THEN // VK_ESCAPE
API(USER32, "DestroyWindow", hWnd)
END

CASE WM_TIMER
SetImage(hWnd, gsIMAGE_FullPathName, 255)

CASE WM_NCHITTEST
nRet = HTCAPTION; GOTO ExitFunction

CASE WM_DESTROY
API(USER32, "PostQuitMessage", 0)
nRet = 0; GOTO ExitFunction

END

nRet = API(USER32, "DefWindowProcA", hWnd, Msg, wParam, lParam)

ExitFunction :
RESULT nRet


Procedure WndProc(LOCAL hWnd is int, LOCAL Msg is int, LOCAL wParam is int, LOCAL lParam is int)
nRet is int

SWITCH Msg

CASE WM_KEYDOWN
IF wParam = 0x1B THEN // VK_ESCAPE
API(USER32, "DestroyWindow", hWnd)
END

CASE WM_TIMER
SetImage(hWnd, gsIMAGE_FullPathName, 255)

CASE WM_NCHITTEST
nRet = HTCAPTION; GOTO ExitFunction

CASE WM_DESTROY
API(USER32, "PostQuitMessage", 0)
nRet = 0; GOTO ExitFunction

END

nRet = API(USER32, "DefWindowProcA", hWnd, Msg, wParam, lParam)

ExitFunction :
RESULT nRet


Et maintenant le plus facile, le lien pour télécharger le projet complet :
http://www.zapsolution.com/windev/GoldFish.zip

Dans un prochain article, je vous montrerai comment créer un splash-screen sur le même principe.

Patrice Terrier
http://www.zapsolution.com/newwindev/FR/index.html