L'ancienne API LoadCursorFromFile_(name) utilisée pour charger un curseur est toujours fonctionnelle mais dépréciée, elle a été remplacée par LoadImage_(hInst,name,#type,cx,cy,#flags).
Si dans vos applications de dessin (ou autre d'ailleurs) vous souhaitez utiliser d'autres curseurs que ceux fournis par le système, c'est un moyen simple de le faire grâce aux fonctions de PureBasic.
Pour l'exemple d'utilisation j'ai repris celui fourni dans la documentation que j'ai adapté.
Pour ceux qui n'ont pas de curseurs personnels, je vous offre quelques uns des miens que vous pouvez télécharger ici : MyCursors.zip
Amusez-vous bien

Testé avec Windows11, PB 6.21B8, x64 et x86
Exemple d'utilisation:
Code : Tout sélectionner
;================================
; Loads an icon, cursor, animated cursor, or bitmap.
; https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadimagea#return-value
; HANDLE LoadImageA(
; [in, optional] HINSTANCE hInst, (Un handle vers le module d'une DLL ou d'un exécutable (.exe) contenant l'image à charger. Pour charger une image prédéfinie ou une ressource autonome (icône, curseur ou fichier bitmap), définissez ce paramètre sur NULL.)
; [in] LPCSTR name, (nom complet du fichier)
; [in] UINT type, (type de fichier défini par : #IMAGE_BITMAP ou #IMAGE_CURSOR ou #IMAGE_ICON)
; [in] int cx, (largeur curseur = 32 par défaut)
; [in] int cy, (hauteur curseur = 32 par défaut)
; [in] UINT fuLoad (#flags)
; );
;-FLAGS :
; #LR_CREATEDIBSECTION - Lorsque le paramètre uType spécifie IMAGE_BITMAP, la fonction renvoie une image bitmap de section DIB plutôt qu'une image bitmap compatible. Cet indicateur est utile pour charger une image bitmap sans la mapper aux couleurs du périphérique d'affichage.
; #LR_DEFAULTCOLOR - L'indicateur par défaut ; il ne fait rien. Il signifie simplement « non LR_MONOCHROME ».
; #LR_DEFAULTSIZE - Utilise la largeur ou la hauteur spécifiée par les valeurs métriques système pour les curseurs ou les icônes, si les valeurs cx ou cy sont définies sur zéro. Si cet indicateur n'est pas spécifié et que cx et cy sont définies sur zéro, la fonction utilise la taille réelle de la ressource. Si la ressource contient plusieurs images, la fonction utilise la taille de la première image.
; #LR_LOADFROMFILE - Charge l'image autonome à partir du fichier spécifié par son nom (icône, curseur ou fichier bitmap).
; #LR_LOADMAP3DCOLORS - Recherche l'image dans la table des couleurs et remplace les nuances de gris suivantes par la couleur 3D correspondante. N'utilisez pas cette option si vous chargez une image bitmap avec une profondeur de couleur supérieure à 8 bpp.
; #LR_LOADTRANSPARENT - Récupère la valeur de couleur du premier pixel de l'image et remplace l'entrée correspondante de la table des couleurs par la couleur de fenêtre par défaut (COLOR_WINDOW). Tous les pixels de l'image utilisant cette entrée adoptent la couleur de fenêtre par défaut. Cette valeur s'applique uniquement aux images disposant de tables de couleurs correspondantes. N'utilisez pas cette option si vous chargez une image bitmap dont la profondeur de couleur est supérieure à 8 bpp.
; #LR_MONOCHROME - Charge l'image en noir et blanc.
; #LR_SHARED - Partage le handle de l'image si celle-ci est chargée plusieurs fois. Si LR_SHARED n'est pas défini, un second appel à LoadImage pour la même ressource chargera à nouveau l'image et renverra un handle différent. N'utilisez pas LR_SHARED pour les images dont la taille n'est pas standard, qui peuvent changer après le chargement ou qui sont chargées depuis un fichier.
; #LR_VGACOLOR - Utilise de vraies couleurs VGA.
; Valeur de retour : HANDLE
; - Si la fonction réussit, la valeur de retour est le handle de l'image nouvellement chargée.
; - Si la fonction échoue, la valeur de retour est NULL.
; --> HANDLE = LoadImage_(hInst,name,#type,cx,cy,#flags)
;Pour libérer la ressource utilisée :
; Bitmap : DeleteObject(HGDIOBJ)
; Cursor : DestroyCursor(HCURSOR)
; Icon : DestroyIcon(HICON)
Enumeration
#IMAGE_Content ; stores the previous CanvasGadget content while the mouse is down
#IMAGE_Color
#IMAGE_LoadSave
EndEnumeration
Enumeration
#GADGET_Canvas
#GADGET_Color
#GADGET_Brush
#GADGET_Line
#GADGET_Box
#GADGET_Circle
#GADGET_Fill
#GADGET_Clear
#GADGET_Load
#GADGET_Save
EndEnumeration
;exemple avec nouvelle API
Global HCURSOR_F = LoadImage_(#Null,"MyCursors\Paint_fill.cur",#IMAGE_CURSOR,32,32,#LR_LOADFROMFILE|#LR_VGACOLOR)
; If HCURSOR_F = #Null
; Debug "Erreur lors du chargement du curseur!"
; EndIf
;exemple avec ancienne API
Global HCURSOR_B = LoadCursorFromFile_("MyCursors\Rectangle_full.cur")
Global HCURSOR_C = LoadCursorFromFile_("MyCursors\Pencil_1.cur")
;Global HCURSOR_F = LoadCursorFromFile_("MyCursors\Paint_fill.cur")
Global HCURSOR_E = LoadCursorFromFile_("MyCursors\Ellipse_empty.cur")
Global HCURSOR_L = LoadCursorFromFile_("MyCursors\Line.cur")
Global HCURSOR_P = LoadCursorFromFile_("MyCursors\Clic_on_plus.ani") ; curseur animé
Procedure Destroy_Curseurs()
DestroyCursor_(HCURSOR_B)
DestroyCursor_(HCURSOR_C)
DestroyCursor_(HCURSOR_F)
DestroyCursor_(HCURSOR_E)
DestroyCursor_(HCURSOR_L)
DestroyCursor_(HCURSOR_P)
EndProcedure
Global CurrentColor, CurrentMode, StartX, StartY
; Draw the mouse action result depending on the currently selected mode and event type
;
Procedure DrawAction(x, y, EventType)
If StartDrawing(CanvasOutput(#GADGET_Canvas))
Select CurrentMode
Case #GADGET_Brush
If EventType = #PB_EventType_LeftButtonDown Or EventType = #PB_EventType_MouseMove
Circle(x, y, 5, CurrentColor)
EndIf
Case #GADGET_Line
DrawImage(ImageID(#IMAGE_Content), 0, 0)
LineXY(StartX, StartY, x, y, CurrentColor)
Case #GADGET_Box
DrawImage(ImageID(#IMAGE_Content), 0, 0)
Box(StartX, StartY, x-StartX, y-StartY, CurrentColor)
Case #GADGET_Circle
DrawImage(ImageID(#IMAGE_Content), 0, 0)
If x > StartX
rx = x - StartX
Else
rx = StartX - x
EndIf
If y > StartY
ry = y - StartY
Else
ry = StartY - y
EndIf
If GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_Modifiers) & #PB_Canvas_Control
ry = rx
EndIf
Ellipse(StartX, StartY, rx, ry, CurrentColor)
Case #GADGET_Fill
If EventType = #PB_EventType_LeftButtonDown
FillArea(x, y, -1, CurrentColor)
EndIf
EndSelect
StopDrawing()
EndIf
EndProcedure
UseJPEGImageDecoder()
UseJPEGImageEncoder()
CurrentColor = $000000
CurrentMode = #GADGET_Brush
CreateImage(#IMAGE_Color, DesktopScaledX(35), DesktopScaledY(35), 24)
CreateImage(#IMAGE_Content, DesktopScaledX(380), DesktopScaledY(380), 24)
If OpenWindow(0, 0, 0, 460, 400, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(#GADGET_Canvas, 10, 10, 380, 380, #PB_Canvas_ClipMouse)
ButtonImageGadget(#GADGET_Color, 400, 10, 50, 50, ImageID(#IMAGE_Color))
ButtonGadget(#GADGET_Brush, 400, 100, 50, 25, "Brush", #PB_Button_Toggle)
ButtonGadget(#GADGET_Line, 400, 130, 50, 25, "Line", #PB_Button_Toggle)
ButtonGadget(#GADGET_Box, 400, 160, 50, 25, "Box", #PB_Button_Toggle)
ButtonGadget(#GADGET_Circle, 400, 190, 50, 25, "Circle", #PB_Button_Toggle)
ButtonGadget(#GADGET_Fill, 400, 220, 50, 25, "Fill", #PB_Button_Toggle)
ButtonGadget(#GADGET_Clear, 400, 280, 50, 25, "Clear")
ButtonGadget(#GADGET_Load, 400, 335, 50, 25, "Load")
ButtonGadget(#GADGET_Save, 400, 365, 50, 25, "Save")
SetGadgetState(#GADGET_Brush, 1)
;SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_Cursor, #PB_Cursor_Cross)
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_P)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget
Select EventGadget()
Case #GADGET_Brush
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_P)
CurrentMode = EventGadget()
SetGadgetState(#GADGET_Brush, 1) : SetGadgetState(#GADGET_Line, 0) : SetGadgetState(#GADGET_Box, 0) : SetGadgetState(#GADGET_Circle, 0) : SetGadgetState(#GADGET_Fill, 0)
Case #GADGET_Line
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_L)
CurrentMode = EventGadget()
SetGadgetState(#GADGET_Brush, 0) : SetGadgetState(#GADGET_Line, 1) : SetGadgetState(#GADGET_Box, 0) : SetGadgetState(#GADGET_Circle, 0) : SetGadgetState(#GADGET_Fill, 0)
Case #GADGET_Box
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_B)
CurrentMode = EventGadget()
SetGadgetState(#GADGET_Brush, 0) : SetGadgetState(#GADGET_Line, 0) : SetGadgetState(#GADGET_Box, 1) : SetGadgetState(#GADGET_Circle, 0) : SetGadgetState(#GADGET_Fill, 0)
Case #GADGET_Circle
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_E)
CurrentMode = EventGadget()
SetGadgetState(#GADGET_Brush, 0) : SetGadgetState(#GADGET_Line, 0) : SetGadgetState(#GADGET_Box, 0) : SetGadgetState(#GADGET_Circle, 1) : SetGadgetState(#GADGET_Fill, 0)
Case #GADGET_Fill
SetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_CustomCursor, HCURSOR_F)
CurrentMode = EventGadget()
SetGadgetState(#GADGET_Brush, 0) : SetGadgetState(#GADGET_Line, 0) : SetGadgetState(#GADGET_Box, 0) : SetGadgetState(#GADGET_Circle, 0) : SetGadgetState(#GADGET_Fill, 1)
Case #GADGET_Canvas ;{
X = GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_MouseX)
Y = GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_MouseY)
Type = EventType()
Select EventType()
Case #PB_EventType_LeftButtonDown
;
; This stores the current content of the CanvasGadget in #IMAGE_Content,
; so it can be re-drawn while the mouse moves
;
If StartDrawing(ImageOutput(#IMAGE_Content))
DrawImage(GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_Image), 0, 0)
StopDrawing()
EndIf
StartX = X
StartY = Y
DrawAction(X, Y, EventType())
Case #PB_EventType_LeftButtonUp
DrawAction(X, Y, EventType())
Case #PB_EventType_MouseMove
If GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton
DrawAction(X, Y, EventType())
EndIf
EndSelect
;}
Case #GADGET_Color ;{
CurrentColor = ColorRequester(CurrentColor)
If StartDrawing(ImageOutput(#IMAGE_Color))
Box(0, 0, 35, 35, CurrentColor)
StopDrawing()
SetGadgetAttribute(#GADGET_Color, #PB_Button_Image, ImageID(#IMAGE_Color))
EndIf
;}
Case #GADGET_Clear ;{
If StartDrawing(CanvasOutput(#GADGET_Canvas))
Box(0, 0, 380, 380, $FFFFFF)
StopDrawing()
EndIf
;}
Case #GADGET_Load ;{
File$ = OpenFileRequester("Load Image...", "", "JPEG Images|*.jpeg|All Files|*.*", 0)
If File$
If LoadImage(#IMAGE_LoadSave, File$)
If StartDrawing(CanvasOutput(#GADGET_Canvas))
Box(0, 0, 380, 380, $FFFFFF)
DrawImage(ImageID(#IMAGE_LoadSave), 0, 0)
StopDrawing()
EndIf
FreeImage(#IMAGE_LoadSave)
Else
MessageRequester("CanvasGadget", "Cannot load image: " + File$)
EndIf
EndIf
;}
Case #GADGET_Save ;{
File$ = SaveFileRequester("Save Image...", File$, "JPEG Images|*.jpeg|All Files|*.*", 0)
If File$ And (FileSize(File$) = -1 Or MessageRequester("CanvasGadget", "Overwrite this file? " + File$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
If CreateImage(#IMAGE_LoadSave, 380, 380, 24) And StartDrawing(ImageOutput(#IMAGE_LoadSave))
DrawImage(GetGadgetAttribute(#GADGET_Canvas, #PB_Canvas_Image), 0, 0)
StopDrawing()
If SaveImage(#IMAGE_LoadSave, File$, #PB_ImagePlugin_JPEG) = 0
MessageRequester("CanvasGadget", "Cannot save image: " + File$)
EndIf
FreeImage(#IMAGE_LoadSave)
EndIf
EndIf
;}
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
Destroy_Curseurs()
EndIf