Subclassing a window
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Subclassing a window
Dans ce post,
http://forums.purebasic.com/english/vie ... hp?t=15090
elchoni me conseille de 'subclassing the window' mais je ne connais pas cette technique, quelqu'un peut m'aider ?
http://forums.purebasic.com/english/vie ... hp?t=15090
elchoni me conseille de 'subclassing the window' mais je ne connais pas cette technique, quelqu'un peut m'aider ?
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
Le subclassing est un moyen d'interfacer notre propre procédure avant l'appel de la procédure de traitement originale et ainsi pouvoir intervenir sur des messages auxquelles on aurait pas accès.
En voici un exemple que j'avais posté:
En voici un exemple que j'avais posté:
Code : Tout sélectionner
Procedure NouvelleProc( hWnd, Msg, wParam, lParam)
;Ici on récupère l'adresse d'origine de la procédure grâce à la
;chaine qui l'identifie: "OriginProc" et le handle de la fenêtre
;voir la fonction SetProp.
OriginProc.l= GetProp_(hWnd, "OriginProc")
Select Msg
Case #wm_char
If wParam=$0D
;Simulation de la touche Tab
keybd_event_($09, 0, 0, 0)
keybd_event_($09, 0, #KEYEVENTF_KEYUP, 0)
ProcedureReturn 0
EndIf
EndSelect
;On renvoie tous les autres évènements à la procédure d'origine.
ProcedureReturn CallWindowProc_(OriginProc,hWnd,Msg,wParam,lParam)
EndProcedure
If OpenWindow(0,0,0,322,275,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"StringGadget Flags") And CreateGadgetList(WindowID(0))
StringGadget(0,8, 10,306,20,"Normal StringGadget...")
StringGadget(1,8, 35,306,20,"1234567",#PB_String_Numeric)
StringGadget(2,8, 60,306,20,"Readonly StringGadget",#PB_String_ReadOnly)
;Avec cette fonction, on récupère l'adresse d'origine de la procédure
;pour ensuite la restituer, une fois le traitement terminé.
OriginProc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @NouvelleProc())
;Cette fonction est très utile car elle permet d'associer une nouvelle donnée
;à n'importe quelles fenêtres crées en utlisant une chaine de caractère pour
;l'identification; ça évite d'utiliser une valeur globale.
;Ici on associe la valeur OriginProc identifiée par la chaine "OriginProc"
;au StringGadget
SetProp_(GadgetID(0), "OriginProc", OriginProc)
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_EventGadget
Select EventGadgetID()
Case 0
Debug "Normal StringGadget"
EndSelect
Case #WM_CLOSE
;Supprimer avant fermeture du programme la donnée associée à la fenêtre.
RemoveProp_(GadgetID(0),"OriginProc")
Quit=1
EndSelect
Until Quit=1
EndIf
Merci nico pour ton exemple, je ne connaissais pas SetProp_(...), GetProp_(...), RemoveProp_(...)
C'est en fait une simplification de ce genre de code qui peut s'écrire
C'est bien ça nico ?
C'est en fait une simplification de ce genre de code
Code : Tout sélectionner
Addr = GlobalAlloc_(#GMEM_FIXED,8)
OldCB = SetWindowLong_(hBouton,#GWL_WNDPROC,@BoutonRX14_CallBack())
PokeL(Addr,OldCB)
PokeL(Addr+4,number)
SetWindowLong_(hBouton,#GWL_USERDATA,Addr)
Code : Tout sélectionner
OldCB = SetWindowLong_(hBouton,#GWL_WNDPROC,@BoutonRX14_CallBack())
SetProp_(hBouton, "OldCB", OldCB)
SetProp_(hBouton,"number", number)
Je viens de lire ce post et je vois une question sans réponse ^^
à partir du code de nico je t'ai fait un exemple "général"
en gros dans ta lib tu auras la fonction callback (que l'utilisateur n'est pas censé connaître) et la fonction WindowSetMinMaxSize qu'il pourra utiliser autant de fois qu'il voudra pour autant de fenêtre...
Dri
à partir du code de nico je t'ai fait un exemple "général"
Code : Tout sélectionner
Declare WindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Declare WindowSetMinMaxSize(WindowID.l, MinW.l, MinH.l, MaxW.l, MaxH.l)
Declare MinMax(Value.l, OldValue.l)
Procedure WindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Protected WndProc.l, Result.l, *MinMax.MinMaxInfo
If Message = #WM_GetMinMaxInfo
*MinMax = lParam
*MinMax\ptMinTrackSize\x = MinMax(GetProp_(WindowID, "MinTrackWidth"), *MinMax\ptMinTrackSize\x)
*MinMax\ptMinTrackSize\y = MinMax(GetProp_(WindowID, "MinTrackHeight"), *MinMax\ptMinTrackSize\y)
*MinMax\ptMaxTrackSize\x = MinMax(GetProp_(WindowID, "MaxTrackWidth"), *MinMax\ptMaxTrackSize\x)
*MinMax\ptMaxTrackSize\y = MinMax(GetProp_(WindowID, "MaxTrackHeight"), *MinMax\ptMaxTrackSize\y)
EndIf
WndProc = GetProp_(WindowID, "WndProc")
If WndProc
Result = CallWindowProc_(WndProc, WindowID, Message, wParam, lParam)
EndIf
ProcedureReturn Result
EndProcedure
Procedure WindowSetMinMaxSize(WindowID.l, MinW.l, MinH.l, MaxW.l, MaxH.l)
Protected WndProc.l
SetProp_(WindowID, "MinTrackWidth", MinW)
SetProp_(WindowID, "MinTrackHeight", MinH)
SetProp_(WindowID, "MaxTrackWidth", MaxW)
SetProp_(WindowID, "MaxTrackHeight", MaxH)
If GetProp_(WindowID, "WndProc") = #Null
WndProc = SetWindowLong_( WindowID, #GWL_WndProc, @WindowCallback() )
SetProp_(WindowID, "WndProc", WndProc)
EndIf
EndProcedure
Procedure MinMax(Value.l, OldValue.l)
If Value <= 0
Value = OldValue
EndIf
ProcedureReturn Value
EndProcedure
OpenWindow(0, 0, 0, 480, 360, #PB_Window_MinimizeGadget|#PB_Window_Sizegadget, "MinMax")
WindowSetMinMaxSize(WindowID(0), 320, 240, 640, 480)
OpenWindow(1, 100, 100, 400, 300, #PB_Window_MinimizeGadget|#PB_Window_Sizegadget, "Min")
WindowSetMinMaxSize(WindowID(1), 320, 240, 0, 0)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Dri

- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Une petite question au passage : puisque tu parles de userlibs, est il possible de créer plusieurs callbacks pour une meme fenetre ?
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Disons que par exemple, j'ai un callback qui active ceci et un autre qui active cela. Comment faire pour en lancer un des deux ou les deux avec un seul callback ?
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Bah Merci Dri 

Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
voila un exemple avec deux fonctions pour une seule callback...
si la propriété n'existe pas, la fonction GetProp_() renvoie 0... donc faut s'arranger si c'est un long pour que 0 soit une valeur incorrecte... Ou alors on peut pointer vers une structure LONG si toutes les valeurs sont acceptées...
Dri
Code : Tout sélectionner
Declare WindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Declare WindowSetMinMaxSize(WindowID.l, MinW.l, MinH.l, MaxW.l, MaxH.l)
Declare WindowLockPosition(WindowID.l, x.w, y.w)
Declare MinMax(Value.l, OldValue.l)
Procedure WindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Protected WndProc.l, Result.l, *MinMax.MinMaxInfo, *Pos.WindowPos, x.l, y.l
If Message = #WM_GETMINMAXINFO
*MinMax = lParam
*MinMax\ptMinTrackSize\x = MinMax(GetProp_(WindowID, "MinTrackWidth"), *MinMax\ptMinTrackSize\x)
*MinMax\ptMinTrackSize\y = MinMax(GetProp_(WindowID, "MinTrackHeight"), *MinMax\ptMinTrackSize\y)
*MinMax\ptMaxTrackSize\x = MinMax(GetProp_(WindowID, "MaxTrackWidth"), *MinMax\ptMaxTrackSize\x)
*MinMax\ptMaxTrackSize\y = MinMax(GetProp_(WindowID, "MaxTrackHeight"), *MinMax\ptMaxTrackSize\y)
ElseIf Message = #WM_WINDOWPOSCHANGING
*Pos = lParam
x = GetProp_(WindowID, "PositionLockX")
y = GetProp_(WindowID, "PositionLockY")
If x & $10000 : *Pos\x = x & $FFFF : EndIf
If y & $10000 : *Pos\y = y & $FFFF : EndIf
EndIf
WndProc = GetProp_(WindowID, "WndProc")
If WndProc
Result = CallWindowProc_(WndProc, WindowID, Message, wParam, lParam)
EndIf
ProcedureReturn Result
EndProcedure
Procedure WindowSetMinMaxSize(WindowID.l, MinW.l, MinH.l, MaxW.l, MaxH.l)
Protected WndProc.l
SetProp_(WindowID, "MinTrackWidth", MinW)
SetProp_(WindowID, "MinTrackHeight", MinH)
SetProp_(WindowID, "MaxTrackWidth", MaxW)
SetProp_(WindowID, "MaxTrackHeight", MaxH)
If GetProp_(WindowID, "WndProc") = #Null
WndProc = SetWindowLong_( WindowID, #GWL_WNDPROC, @WindowCallback() )
SetProp_(WindowID, "WndProc", WndProc)
EndIf
EndProcedure
Procedure WindowLockPosition(WindowID.l, x.w, y.w)
Protected WndProc.l, xx.l, yy.l
If x >= 0 : xx = $10000 | x : EndIf
If y >= 0 : yy = $10000 | y : EndIf
SetProp_(WindowID, "PositionLockX" ,xx)
SetProp_(WindowID, "PositionLockY" ,yy)
If GetProp_(WindowID, "WndProc") = #Null
WndProc = SetWindowLong_( WindowID, #GWL_WNDPROC, @WindowCallback() )
SetProp_(WindowID, "WndProc", WndProc)
EndIf
EndProcedure
Procedure MinMax(Value.l, OldValue.l)
If Value <= 0
Value = OldValue
EndIf
ProcedureReturn Value
EndProcedure
OpenWindow(0, 0, 0, 480, 360, #PB_Window_MinimizeGadget|#PB_Window_SizeGadget, "MinMax + Lock")
WindowSetMinMaxSize(WindowID(0), 320, 240, 640, 480)
WindowLockPosition(WindowID(0), #PB_Default, 0)
OpenWindow(1, 400, 100, 400, 300, #PB_Window_MinimizeGadget|#PB_Window_SizeGadget, "Min")
WindowSetMinMaxSize(WindowID(1), 320, 240, #Null, #Null)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Dri
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Ptite question à quoi sert getProp_(), Setprop_() ?
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net