Page 1 of 1

Events, events, events...

Posted: Wed Aug 19, 2009 7:57 am
by klaver
Well, some basic events for PB gadgets are REALLY needed in my opinion. Here's show an example (Windows only) how I'd see it working. Maybe it's how it might (?) be done, at least for Windows?

Code: Select all

#PB_EventType_LeftClick2 = #PB_EventType_LeftClick+777
#PB_EventType_RightClick2 = #PB_EventType_RightClick+777
#PB_EventType_LeftDoubleClick2 = #PB_EventType_LeftDoubleClick+777
#PB_EventType_RightDoubleClick2 = #PB_EventType_RightDoubleClick+777
#PB_EventType_Focus2 = #PB_EventType_Focus+777
#PB_EventType_LostFocus2 = #PB_EventType_LostFocus+777

Import ""
  PB_Gadget_SendGadgetCommand(hWnd, EventType)
EndImport
Global hWin.i

Procedure CheckFocus(wParam, lParam)
  wParam = GetProp_(hWin, "OldFocus")
  Var3 = GetParent_(lParam)
  ;better method to determine if it's a PB gadget is
  ;needed because PB_ID returns 0 also for #Gadget = 0
  While GetProp_(lParam, "PB_ID") = 0 And Var3 <> 0
    lParam = Var3
    Var3 = GetParent_(Var3)
  WEnd
  If lParam <> wParam And Var3 <> 0
    SetProp_(hWin, "OldFocus", lParam)
    PB_Gadget_SendGadgetCommand(wParam, #PB_EventType_LostFocus2)
    PB_Gadget_SendGadgetCommand(lParam, #PB_EventType_Focus2)
  EndIf
EndProcedure

Procedure EventFunc(hWnd, uMsg, wParam, lParam)
  Protected Result.i = GetProp_(hWnd, "OldProc")
  If Result
    Result = CallWindowProc_(Result, hWnd, uMsg, wParam, lParam)
  EndIf
  
  Select uMsg
    Case #WM_LBUTTONDOWN;#WM_LBUTTONUP
      PB_Gadget_SendGadgetCommand(hWnd, #PB_EventType_LeftClick2)
    Case #WM_RBUTTONDOWN;#WM_RBUTTONUP
      PB_Gadget_SendGadgetCommand(hWnd, #PB_EventType_RightClick2)
    Case #WM_LBUTTONDBLCLK
      PB_Gadget_SendGadgetCommand(hWnd, #PB_EventType_LeftDoubleClick2)
    Case #WM_RBUTTONDBLCLK
      PB_Gadget_SendGadgetCommand(hWnd, #PB_EventType_RightDoubleClick2)
    Case #WM_SETFOCUS;, #WM_KILLFOCUS
      CheckFocus(wParam, hWnd)
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "OldProc")
  EndSelect
  ProcedureReturn Result
EndProcedure

Procedure ChildFunc(hWnd, uMsg, wParam, lParam)
  Protected Result.i = GetProp_(hWnd, "OldProc")
  If Result
    Result = CallWindowProc_(Result, hWnd, uMsg, wParam, lParam)
  EndIf
  
  Select uMsg
    Case #WM_LBUTTONDOWN;#WM_LBUTTONUP
      PB_Gadget_SendGadgetCommand(GetParent_(hWnd), #PB_EventType_LeftClick2)
    Case #WM_RBUTTONDOWN;#WM_RBUTTONUP
      PB_Gadget_SendGadgetCommand(GetParent_(hWnd), #PB_EventType_RightClick2)
    Case #WM_LBUTTONDBLCLK
      PB_Gadget_SendGadgetCommand(GetParent_(hWnd), #PB_EventType_LeftDoubleClick2)
    Case #WM_RBUTTONDBLCLK
      PB_Gadget_SendGadgetCommand(GetParent_(hWnd), #PB_EventType_RightDoubleClick2)
    Case #WM_SETFOCUS;, #WM_KILLFOCUS
      CheckFocus(wParam, hWnd)
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "OldProc")
  EndSelect
  ProcedureReturn Result
EndProcedure

Procedure EnumChildProc(hWnd, lParam)
  SetProp_(hWnd, "OldProc", SetWindowLong_(hWnd, #GWL_WNDPROC, @ChildFunc()))
  ProcedureReturn #True
EndProcedure

Procedure SetEvents(hWnd, Child = #False)
  If Child
    EnumChildWindows_(hWnd, @EnumChildProc(), 0)
  EndIf
  SetProp_(hWnd, "OldProc", SetWindowLong_(hWnd, #GWL_WNDPROC, @EventFunc()))
EndProcedure

If OpenWindow(0, 0, 0, 400, 300 , "PB Events", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) : hWin = WindowID(0)
  DateGadget(3, 10, 10, 180, 22, "%mm/%dd/%yyyy Time: %hh:%ii", 0, #PB_Date_UpDown) : SetEvents(GadgetID(3), #True)
  
  IPAddressGadget(5, 10, 50, 160, 22) : SetEvents(GadgetID(5), #True)
  
  ComboBoxGadget(11, 10, 88, 180, 22) : SetEvents(GadgetID(11), #True)
  For i = 1 To 4
    AddGadgetItem (11, -1, "Item " + Str(i))
  Next
  
  OptionGadget(13, 10, 120, 60, 20, "Option") : SetEvents(GadgetID(13))
  ;CalendarGadget(13, 10, 120, 180, 140) : SetEvents(GadgetID(13));focus not supported for SysMonthCal32...
  
  ListViewGadget(7, 200, 10, 180, 120) : SetEvents(GadgetID(7))
  For i = 1 To 7
    AddGadgetItem (7, -1, "Item " + Str(i))
  Next
  
  ListIconGadget(9, 200, 140, 180, 120, "Column 1", 100) : SetEvents(GadgetID(9));, #True);header
  For i = 1 To 7
    AddGadgetItem (9, -1, "Item " + Str(i))
  Next
EndIf

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventType()
        Case #PB_EventType_LeftClick2
          Debug "PB_EventType_LeftClick: "+Str(EventGadget())
        Case #PB_EventType_RightClick2
          Debug "PB_EventType_RightClick: "+Str(EventGadget())
        Case #PB_EventType_LeftDoubleClick2
          Debug "PB_EventType_LeftDoubleClick: "+Str(EventGadget())
        Case #PB_EventType_RightDoubleClick2
          Debug "PB_EventType_RightDoubleClick: "+Str(EventGadget())
        Case #PB_EventType_Focus2
          Debug "--> PB_EventType_Focus: "+Str(EventGadget())
        Case #PB_EventType_LostFocus2
          Debug "<-- PB_EventType_LostFocus: "+Str(EventGadget())
      EndSelect
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver

Posted: Wed Aug 19, 2009 8:18 am
by Rescator
Outch outch outch! Don't do that.
Don't store callback or function pointers in the window properties...
They can not only be read but written to/changed by any other application,
a stupid app may also just end up messing them up by accident.
Use an internal structure or similar instead.


PS! Reason I point this out is that I recently read that Microsoft patched up a security hole just like this, related to WM_TIMER messages, although it did not involve window props, it too involved a callback/function pointer being passed publicly, via a the window message. (they patched that in XP SP1 btw)

Posted: Wed Aug 19, 2009 8:29 am
by Rescator
Here's an old post of mine.
Run it and see what lies hidden in so many windows props on your system
http://www.purebasic.fr/english/viewtopic.php?t=35655

Posted: Wed Aug 19, 2009 4:31 pm
by Matt
It does get messy in the event loop when you have so much going on in the program and so many gadgets...

Posted: Wed Aug 19, 2009 10:51 pm
by Rescator
Yeah! Hopefully by the time we get Window 10 there will be a more efficient alternative to the way windows messages work today.