Page 1 of 2

catching single and double click on listicon...

Posted: Wed Jan 10, 2007 11:55 pm
by DoMi
Hello
using listIconGadget, I want to catch and distinguish those events :
#PB_EventType_LeftDoubleClick
#PB_EventType_LeftClick

Code: Select all

 If GadgetID = #lbxFreq
      If EventType = #PB_EventType_LeftDoubleClick
        lbxFreqLeftDblClick()
      ElseIf EventType = #PB_EventType_LeftClick
        lbxFreqLeftClick()
      ElseIf EventType = #PB_EventType_RightClick
        lbxFreqRightClick()
      EndIf 
Each time I double-click single-click event is raised too
I could set a timer to differentiate single and double-click or set a flag in the event loop but I guess Windows already does that !? does it?

Any explanation or solution ?
Thanks in advance

Posted: Wed Jan 10, 2007 11:59 pm
by srod
From the win32.hlp file:
Double-clicking the left mouse button actually generates four messages: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, and WM_LBUTTONUP again.
:)

Posted: Thu Jan 11, 2007 12:37 am
by DoMi
thanks for information
Does it mean that PB sends always :
#PB_EventType_LeftClick
#PB_EventType_LeftDoubleClick
for doubleClick event?

By my side, if I set a flag On (without action) when a click occurs can I be sure that the right next event is either the second click -> I manage doubleClick treatment)
or another event -> I manage singleClick treatment then (setting the flag Off) and the other event after

(As matter of fact I observe #PB_EventType_LeftClick is raised when the first WM_LBUTTONUP event occurs
and #PB_EventType_LeftDoubleClick is raised when WM_LBUTTONDBLCLK occurs...not when the next WM_LBUTTONUP occurs)

I don't know which way applications usually manage to differentiate those two events for a same component?

any idea?

Posted: Thu Jan 11, 2007 12:48 am
by srod
DoMi wrote:I don't know which way applications usually manage to differentiate those two events for a same component?
any idea?
I'm not sure that most applications will take steps to differentiate between these two events. By this I mean that they would process the events accordingly; i.e. a double-click of the left button will result in the application processing the #WM_LBUTTONDOWN as per normal and then the #WM_LBUTTONDBLCLK etc. I'm not sure why you would want to mask out the initial #WM_LBUTTONDOWN ?

I'm not saying that it can't be done and I'm sure we could hack up a solution easily enough; it's just that it doesn't seem to be the Windows way! :)

Posted: Thu Jan 11, 2007 1:03 am
by rsts
DoMi wrote:thanks for information
Does it mean that PB sends always :
#PB_EventType_LeftClick
#PB_EventType_LeftDoubleClick
for doubleClick event?
In my experience, yes. If you want to use both, you have to check the single click case before the double click, because it will always occur.

cheers

Posted: Thu Jan 11, 2007 1:11 am
by DoMi
thanks

singleClicking a listIcongadget (of chromatic scale degrees "equaly tempered") plays the sound frequency (Windows beep_(freq,time) )of selected line
doubleClicking a line set the corresponding degree as the new chromatic scale root (but without playing the corresponding tone!)

I finally processed the second task by a single rightClic to avoid headache :?

thanks anyway

Posted: Thu Jan 11, 2007 1:13 am
by srod
DoMi wrote:I finally processed the second task by a single rightClic to avoid headache :?
:D

Posted: Thu Jan 11, 2007 1:29 am
by srod
Here you are. This is pretty rough around the edges, but it seems to work reasonably well! There's probably better ways.

Win xp only.

Code: Select all

Global timerset

Procedure TimerProc(uID, uMsg, dwUser, dw1, dw2) 
If timerset = 0
  Debug "Single click!"
EndIf
timerset=0
EndProcedure 


If OpenWindow(0, 100, 100, 300, 100, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    ListIconGadget(0, 5, 5, 290, 90, "Name", 100, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
    AddGadgetColumn(0, 1, "Address", 250)
    AddGadgetItem(0, -1, "Harry Rannit"+Chr(10)+"12 Parliament Way, Battle Street, By the Bay")
    AddGadgetItem(0, -1, "Ginger Brokeit"+Chr(10)+"130 PureBasic Road, BigTown, CodeCity")
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget
        If EventGadget()=0
          Select EventType()
            Case #PB_EventType_LeftClick
              timeSetEvent_(200,10,@TimerProc(),0, #TIME_ONESHOT)
            Case #PB_EventType_LeftDoubleClick
              timerset=1
              Debug "Double click!"

          EndSelect
        EndIf
      EndSelect
      
     Until Event = #PB_Event_CloseWindow
   EndIf
 EndIf

Posted: Thu Jan 11, 2007 3:50 am
by rsts
Pretty darn slick. Now to revisit all my doubleclick routines :)

cheers

Posted: Thu Jan 11, 2007 11:10 am
by srod
Be careful though as you need to ensure that the timer count:

Code: Select all

timeSetEvent_(200,10,@TimerProc(),0, #TIME_ONESHOT) 
200 milliseconds in this case, is enough to ensure that a double-click can pass, but not too long that you notice the delay.

On my system, the max double-click delay is 500 milliseconds, i.e. 0.5 of a second but because the #WM_LBUTTONDOWN message takes time to process, I had to settle for a count of 200. This obviously depends upon the speed of your system.

You might be better using something like:

Code: Select all

timeSetEvent_(GetDoubleClickTime_()/2, 10, @TimerProc(), 0, #TIME_ONESHOT) 
etc.

Posted: Fri May 25, 2007 4:33 pm
by rsts
Guess I'll resurrect this topic.

I have a program that handles single and double clicks on a listicongadget.

All was fine until I needed to change the single click routine to read a record from a sqlite database (The single click process was previously just internal processing from a linked list).

Now, I find it next to impossible to consistently recognize the doubleclick. Best performance is if I doubleclick very slowly, but even that is not concistent and not a very good solution.

I was playing with srod's method above, but it was also very inconsistent and I need the solution to be cross windows not just XP, so couldn't really use it anyway.

I'm processing the events via normal #PB_EventType_LeftClick and #PB_EventType_LeftDoubleClick, but have a callback in the program if there's a callback solution.

Any reason why the processing in the singleclick routine so negatively impacts the recognition of the doubleclick by windows?

The sequence of events is not a problem as I want to perform the singleclick processing even if there's a doubleclick. It's just that since the singleclick process 'slowed down' due to the database read, I can't cocsistently recognize the doubleclick.

Does this make sense or am i once again lost in the wilderness?

cheers

Posted: Fri May 25, 2007 5:46 pm
by netmaestro
You could try my version here:

http://www.purebasic.fr/english/viewtop ... 81&start=3

Upon getting a single click it waits to see if it'll change to a doubleclick. You can insert your action code so that if it's a doubleclick it does both actions, and doesn't do the singleclick action by itself unless it really didn't change to a double. That way you're not being held up as the timing is always the same.

Posted: Fri May 25, 2007 6:02 pm
by rsts
Thanks once again, I'll give this method a try.

Still trying to figure out why this didn't show up on my search? I thought I had done one just on doubleclick, but may have searched on doubleclick and listicon. I try so many, I tend to get confused :)

cheers

Posted: Fri May 25, 2007 6:35 pm
by rsts
That seems to have done it, Mr Hero. :)

I had tried some things that were attempts at something like this, but didn't know you could 'nest' the waitwindowevent because I seem to have misinterpreted the help explanation "WaitWindowEvent() can only be called once per event loop" to meaning that couldn't be done.

To top it all off, I had seen this 'tip' when you first posted it, but couldn't locate it when I searched.

Oh well, all's well that ends with a netmaestro solution :) What a contributor!

cheers

Posted: Fri May 25, 2007 6:40 pm
by netmaestro
Thanks for the kind words, I'm glad it's getting sorted out.

The help doc for WaitWindowEvent() is left over from an earlier time, before you could put a parameter in. So another WaitWindowEvent() without the parameter would indeed lock up the loop, but with the 1ms timeout it's all good.