Using event handlers - (obsolete version)

Developed or developing a new product in PureBasic? Tell the world about it.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Hi schic.

I can't reproduce your first report, but as you indicate, it seems a minor deal.

The problem with the list view is to do with the way Windows sends notifications that a listview item is about to change. It sends it after you release the mouse button (which seems a little strange to me!)

This of course is a massive problem when enabling drag-and-drop since we will not be releasing the mouse button any time soon!

The way round it is to use EasyVent's #OnMouseDown() event instead as the following adaption to the above example shows:

Code: Select all

XIncludeFile "EasyVENT.pbi" 
;********************************************************************************* 

Declare.l SelectItem(*sender.PB_Sender) 
Declare.l DragOverWindow(*sender.PB_Sender) 
Declare.l DragItem(*sender.PB_Sender) 
Declare.l DropItem(*sender.PB_Sender) 
Declare.l DragOver(*sender.PB_Sender) 

Declare.l DragItemTree(*sender.PB_Sender) 

Declare HighLightSelection(hwnd, state) 

Define Event.l, i, WindowID, GadgetID, GadgetEvent 

Global gTargetitem ;Denotes which item we are dropping on. 
Global DragSource 

OpenWindow(0, 100, 100, 330, 200, "EasyVENT drag and drop items demo 4.", #PB_Window_SystemMenu |#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget| #PB_Window_ScreenCentered) 
  
  CreateGadgetList(WindowID(0)) 
    ListViewGadget(1, 0, 0, 150, 150) 
  
    ListIconGadget(2,170,10,150,150, "Drag to", 120) 
    For i = 1 To 10 
      AddGadgetItem(1, -1, "Gadget 1 - item " + Str(i)) 
      ; AddGadgetItem(0, -1, "Gadget 0 - item " + Str(i)) 
      If i < 6 
        AddGadgetItem(2, -1, "Gadget 2 - item " + Str(i)) 
      EndIf 
    Next 

  
;Set event handlers. 
  SetEventHandler(GadgetID(1), #OnMouseDown, @SelectItem()) 
  SetEventHandler(GadgetID(1), #OnDragItemStart, @DragItem()) 
  SetEventHandler(GadgetID(2), #OnDragItemOver, @DragOver()) 
  SetEventHandler(GadgetID(2), #OnDragItemEnd, @DropItem()) 
  SetEventHandler(WindowID(0), #OnDragItemOver, @DragOverWindow()) 

SetActiveGadget(1) 
Repeat 
  Event = WindowEvent() 
Until Event = #PB_Event_CloseWindow 
End 


;********************************************************************************* 
;                                 EVENT HANDLERS 
;********************************************************************************* 


Procedure.l SelectItem(*sender.PB_Sender) 
  Debug GetGadgetState(1) 
ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 


;The following ensures that any highlighted item in the target control is removed 
;whenever the cursor leaves the control. 
Procedure.l DragOverWindow(*sender.PB_Sender) 
;Remove any selection highlight already in place. 
  HighLightSelection(GadgetID(2), 0) 
ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

;Here we simply return #PB_ProcessPureBasicEvents to enable the drag. 
Procedure.l DragItem(*sender.PB_Sender) 
  If GetActiveGadget()=1 And GetGadgetState(1)>=0 
    DragSource = 1 
    *sender\Text$=GetGadgetText(1) 
  EndIf 
ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

;Since the following handles only one gadget, we need not check which control etc. 
Procedure.l DropItem(*sender.PB_Sender) 
;First remove any selection highlight already in place. 
  HighLightSelection(*sender\hwnd, 0) 
  If DragSource = 1 
    AddGadgetItem(2,gTargetitem, GetGadgetText(1)) ;Copy item to ListView. 
    RemoveGadgetItem(1,*sender\item) ;Remove item from ListIcon. 
  ElseIf DragSource = 0 
    AddGadgetItem(2,gTargetitem, GetGadgetText(0)) ;Copy item to ListView. 
    RemoveGadgetItem(1,*sender\item) ;Remove item from ListIcon. 
  EndIf 

ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

Procedure.l DragOver(*sender.PB_Sender) 
  Protected hittestinfo.LV_HITTESTINFO 
;First remove any selection highlight already in place. 
  HighLightSelection(*sender\hwnd, 0) 
;Find which item we are currently hovering over. We need an API call for this. 
  hittestinfo\pt\x = *sender\MouseX 
  hittestinfo\pt\y = *sender\MouseY 
  gTargetitem = SendMessage_(*sender\hwnd, #LVM_HITTEST, 0, @hittestinfo)            
;Highlight the new item 
  If gTargetitem<>-1 
    HighLightSelection(*sender\hwnd, #LVIS_DROPHILITED) 
  EndIf 
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

;********************************************************************************* 
;                              END OF EVENT HANDLERS 
;********************************************************************************* 

;The following utility either highlights the target item or removes the highlight etc. 
Procedure HighLightSelection(hwnd, state) 
  Protected pitem.LV_ITEM 
    pitem\mask = #LVIF_STATE 
    pitem\iItem = gTargetitem 
    pitem\state = state 
    pitem\stateMask = #LVIS_DROPHILITED 
    SendMessage_(hwnd, #LVM_SETITEM, 0, @pitem) 
    RedrawWindow_(hwnd, 0, 0, #RDW_UPDATENOW) 
EndProcedure 
NOTE that you will need to download the new version of EasyVENT (see post 1) which I have just uploaded for this to work.

To be honest, if you're making use of this library, it is probably best if you do not use PB's event loop for anything other than closing the program. I admit that any problems that arise are likely to do with drag-drop (as already shown!) but the two are really not designed to work together! This is not to say that they will not work together, but the two paradigms are quite dissimilar! :D

For example, my current app has nearly 50 events declared at the moment and all is working well. This is of course with the regular PB event loop only being used to close the program.
I may look like a mule, but I'm not a complete ass.
schic
User
User
Posts: 34
Joined: Fri Sep 12, 2003 10:17 am

Post by schic »

Thank you srod for your help.
Now it does work with the ListView.
it is probably best if you do not use PB's event loop for anything other than closing the program
Yes I feared this work, but did already start to resolve the PB Event loop and
change it with EasyVENTs. Think it´s worth while.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You're welcome.

Thinking about it now, the only events which EasyVENT will 'swallow' and hide from any other message trapping routine (e.g. PB's event loop, callbacks etc.) will be those akin to #WM_MOUSEMOVE and #WM_LBUTTONUP, and then only if the user is in the process of dragging and dropping items etc.

There didn't seem to be any point processing such events whilst drag-and-drop was in process. If this turns out to prove problematic under certain 'strange' circumstances, then I'll alter this accordingly.

Stephen.
I may look like a mule, but I'm not a complete ass.
schic
User
User
Posts: 34
Joined: Fri Sep 12, 2003 10:17 am

Post by schic »

Hi srod

did you ever consider on binding the #OnDragItemStart event,
to the #WM_MOUSEMOVE and not to the #WM_LBUTTONDOWN
message? This seems to be the more logic way for me, cause
a drag event occurs not until the mouse is moved with left
botton pressed.

I am not very familiar to all the API-calls you use, but playing
around with yor lib, it seems to work. And all MouseDown
events are behaving as expected - also in the PB-Event-Loop.

Hope my English is not too faulty to understand what I mean.

schic
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

did you ever consider on binding the #OnDragItemStart event,
to the #WM_MOUSEMOVE and not to the #WM_LBUTTONDOWN
message? This seems to be the more logic way for me, cause
a drag event occurs not until the mouse is moved with left
botton pressed.
I don't really see the point; you can't instigate a drag until the left button is down!
Whilst it will not be difficult to code this, I can't see as there will be any difference in practice since EasyVENT now processes all #WM_LBUTTONDOWN events (it does not swallow any such events), even if drag/drop is under way.
I may look like a mule, but I'm not a complete ass.
josku_x
Addict
Addict
Posts: 997
Joined: Sat Sep 24, 2005 2:08 pm

Post by josku_x »

If srod would use #WM_MOUSEMOVE, he must anyway use #WM_LBUTTONDOWN to trace if the left button is pushed before doing anything. So that would be just extra coding, wouldn't it :shock:
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I guess schic means that I would set a flag when the button is pressed etc. either that or use GetAsyncKeyState_(). But as you say, extra coding for no extra gain! :)
I may look like a mule, but I'm not a complete ass.
schic
User
User
Posts: 34
Joined: Fri Sep 12, 2003 10:17 am

Post by schic »

if checking GetAsyncKeyState_(#VK_LBUTTON)=32768
in Case #WM_MOUSEMOVE the whole

Code: Select all

If sender\Text$<>"" 
...
EndIf
can be moved from Case #WM_LBUTTONDOWN to Case #WM_MOUSEMOVE.
I am playing around with it and - well have problems with marking text in
StringGadgets (mouse-button down and moving) but think will find the bug.

And maybe there will be more bugs to detect...
It´s just an idea which may turn out to be the wrong way.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

There is a problem when dragging from StringGadgets (see drag demo 2). To prevent the problem use

Code: Select all

SendMessage_(GadgetID(#string),#WM_SETREDRAW,0,0)
in the #OnDragItemStart event handler.

This isn't a flag I set by default as it disrupts other gadget types.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

**Update: have added one more event, #OnLinkClick

This can be used only in editor gadgets at present and allows for the trapping of clicks whilst the cursor is over a 'link' (which does not have to be a valid URL etc.)

The full list of supported events now runs as follows:

REMOVED (see post below).

An example is included within the download package.

See first post for the download link.

Regards.
Last edited by srod on Sat Jul 15, 2006 11:54 pm, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

July 10th 2006.
Have added a simple example (called 'NewSplitter') which shows how to use EasyVENT to easily implement a flicker-free splitter. This was a by product of my current project.

See first post for the download link.
I may look like a mule, but I'm not a complete ass.
Niffo
Enthusiast
Enthusiast
Posts: 504
Joined: Tue Jan 31, 2006 9:43 am
Location: France

Post by Niffo »

Very very great Work ! :shock:

Thank you very much !
Niffo
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You're welcome Niffo.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

**Update: have added one more event, #OnSizingWindow

This basically translates to the #WM_GETMINMAXINFO Window's message and allows the developer to restrict the user's ability to size a window etc. It differs from the #OnResize event in that #OnSizingWindow is called before changes are made etc.

The full list of supported events now runs as follows:
  • #OnButtonClick
  • #OnChange
  • #OnClose
  • #OnCollapseExpandSelection
  • #OnContextMenuPopup
  • #OnCursorEnter
  • #OnCursorExit
  • #OnDragDrop
  • #OnDragItemEnd
  • #OnDragItemOver
  • #OnDragItemStart
  • #OnDblClick
  • #OnEditTreeLabels
  • #OnGotFocus
  • #OnItemSelected
  • #OnItemSelecting
  • #OnKeyDown
  • #OnKeyPress
  • #OnKeyUp
  • #OnLinkClick
  • #OnLostFocus
  • #OnMaximize
  • #OnMenuItemSelect
  • #OnMinimize
  • #OnMouseDown
  • #OnMouseOver
  • #OnMouseUp
  • #OnMove
  • #OnPaint
  • #OnResize
  • #OnScroll
  • #OnSetCursor
  • #OnSizingWindow
An example of using this new event is detailed within the user guide.

See first post for the download link.

Regards.
I may look like a mule, but I'm not a complete ass.
User avatar
GeoTrail
Addict
Addict
Posts: 2794
Joined: Fri Feb 13, 2004 12:45 am
Location: Bergen, Norway
Contact:

Post by GeoTrail »

This is really cool, nice work srod :)
I Stepped On A Cornflake!!! Now I'm A Cereal Killer!
Post Reply