pb disablegadget() leaves the gadget, well, disabled

all fine, but what if you want the gadget to look like the regular thing, but not operating? (let's just say you're into visual designers and you want to drag buttons

here's a solution
Code: Select all
Structure x_dgwindow
windownr.l
mousehook_h.l
EndStructure
Structure x_dggadget
gadgetnr.l
gadget_h.l
windownr.l
EndStructure
Global NewList x_dgwindow.x_dgwindow()
Global NewList x_dggadget.x_dggadget()
Procedure x_dg_mousehookhandler(ncode.l,wparam.l,lparam.l)
Protected mx.l, my.l, rect.RECT
;
If wparam = #WM_LBUTTONUP Or wparam = #WM_LBUTTONDOWN ; only rmb or lmb messages
ResetList(x_dggadget())
While NextElement(x_dggadget()) <> 0
If EventWindow() = x_dggadget()\windownr
mx = DesktopMouseX()
my = DesktopMouseY()
rect.RECT
GetWindowRect_(x_dggadget()\gadget_h,@rect)
If mx >= rect\left And mx <= rect\right And my >= rect\Top And my <= rect\bottom
ProcedureReturn 1
EndIf
EndIf
Wend
EndIf
ProcedureReturn 0
EndProcedure
Procedure.l x_enddisablegadgets(windownr.l) ; reenable all gadgets on specified window
Protected found.l, endoflist.l
;
; *** remove the specified windownr and all gadgets on it from the list and enable these gadgets
;
; in: windownr.l = -1 - reenable all gadgets and windows. remove all hooks
; = n - reenable all gadgets on specified window, remove hook
; retval: -1 - no window removed from list
; 0 - removed window and hook
;
x_retval = -1
If windownr > 0
;
; delete all elements in the list of gadgets that belong to the specified window
;
endoflist = 1
If FirstElement(x_dggadget()) <> 0
Repeat
If x_dggadget()\windownr = windownr
DeleteElement(x_dggadget(),1)
Else
endoflist = NextElement(x_dggadget())
EndIf
Until endoflist = 0
EndIf
;
; now unhook the window and remove it from the list of windows
;
found = #False
If FirstElement(x_dgwindow())
Repeat
If x_dgwindow()\windownr = windownr
found = #True
EndIf
Until found = #True Or NextElement(x_dgwindow()) = 0
If found = #True
UnhookWindowsHookEx_(x_dgwindow()\mousehook_h)
DeleteElement(x_dgwindow())
x_retval = 0
EndIf
EndIf
;
Else
;
; window was specified as -1 so unhook all windows, enable all gadgets and clear both lists
;
ResetList(x_dgwindow())
While NextElement(x_dgwindow()) <> 0
UnhookWindowsHookEx_(x_dgwindow()\mousehook_h)
Wend
ClearList(x_dgwindow())
ClearList(x_dggadget())
x_retval = 0
;
EndIf
;
EndProcedure
Procedure.l x_disablegadget(gadgetnr,windownr,disable.l) ; disable gadget by intercepting clicks
Protected found.l, instance_h.l, thread_id.l
Global x_retval.l
; Global x_dgwindow.l(), x_dggadget.l()
;
; *** disable or enable gadgets by intercepting clicks
;
; in: with disable.l = #true:
; gadgetnr = m windownr = n - disable gadget m on window n
; windownr = -1 - disable gadget rectangle on any window
; gadgetnr = -1 windownr = n - disable specified gadgets for window n
; windownr = -1 - error
; with disable.l = #false:
; gadgetnr = m - reenable specified gadget (windownr is ignored)
; gadgetnr = -1 windownr = n - reenable all gadgets on this window
;
; x_retval: -1 - error
; 0 - no error
;
; note 1: do not close windows once a hook has been set up for them, make sure you call
; x_enddisablegadgets() with the proper windownumber, or x_disablegadget(-1,n,0)
;
; note 2: nothing stops people from tabbing to the gadget, this one's just for those that
; have (quiet :-)) aspirations to write a visual designer :-)
;
x_retval = 0
If disable = #True
;
; *** disabling gadgets
;
If windownr > 0
If IsWindow(windownr)
;
; first process window: does it exist, was it already in the list, if not add it to list for windows and hook it
;
window_h = WindowID(windownr) ; handle of window
found = #False ; is the window already hooked?
If FirstElement(x_dgwindow()) <> 0
Repeat
If x_dgwindow()\windownr = windownr
found = #True
EndIf
Until found = #True Or NextElement(x_dgwindow()) = 0
EndIf
If found = #False ; wasn't hooked yet
AddElement(x_dgwindow()) ; new window to monitor
x_dgwindow()\windownr = windownr
instance_h = GetModuleHandle_(0) ; do the hooky thing
thread_id = GetWindowThreadProcessId_(window_h, 0)
x_dgwindow()\mousehook_h = SetWindowsHookEx_(#WH_MOUSE, @x_dg_mousehookhandler(), instance_h, thread_id)
EndIf
Else
x_retval = -1 ; specified window does not exist, error
EndIf
ElseIf gadgetnr < 0 ; neither gadget nor window were specified, error
x_retval = -1
EndIf
;
; now the gadget: does it exist, was it already in the list, if not add to list for gadgets
;
If x_retval > -1
If IsGadget(gadgetnr)
found = #False
If FirstElement(x_dggadget()) <> 0
Repeat
If x_dggadget()\gadgetnr = gadgetnr ; already existed
found = #True
EndIf
Until found = #True Or NextElement(x_dggadget()) = 0
EndIf
If found = #False ; didn't exist so add
AddElement(x_dggadget())
x_dggadget()\gadgetnr = gadgetnr
x_dggadget()\gadget_h = GadgetID(gadgetnr)
x_dggadget()\windownr = windownr
EndIf
Else ; gadget does not exist
x_retval = -1
EndIf
EndIf
;
Else
;
; *** reenabling gadgets or windows
;
If gadgetnr > -1
found = #False
If FirstElement(x_dggadget()) <> 0 ; begin of list of gadgets
Repeat
If x_dggadget()\gadgetnr = gadgetnr ; found the gadget
found = #True
EndIf
Until found = #True Or NextElement(x_dggadget()) = 0
If found = #True ; found now delete
windownr = x_dggadget()\windownr ; but first remember windownr
DeleteElement(x_dggadget()) ; delete from list of gadgets
found = #False
If FirstElement(x_dggadget()) ; now check if there were more gadgets on the same window
Repeat
If x_dggadget()\windownr = windownr
found = #True
EndIf
Until found = #True Or NextElement(x_dggadget()) = 0 ; keep on going until found or end of list
EndIf
If found = #False ; no more gadgets on this window
x_retval = x_enddisablegadgets(windownr)
EndIf
EndIf
EndIf
ElseIf windownr > -1
x_retval = x_enddisablegadgets(windownr)
Else
x_retval = -1
EndIf
;
EndIf
;
ProcedureReturn x_retval
;
EndProcedure
h = OpenWindow(1,300,200,400,300,"test",#PB_Window_SystemMenu)
ButtonGadget(1,10,10,20,20,"1")
ButtonGadget(2,30,10,20,20,"2")
ButtonGadget(3,50,10,20,20,"3")
x_disablegadget(1,1,1)
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow
x_enddisablegadgets(-1)