while button pressed

Started by raymw, July 31, 2018, 09:16:57 PM

Previous topic - Next topic

raymw

I missing something pretty fundamental here. I eventually want to send data via a com port while a button is pressed. In the meantime I've been sort of simulating the data transmission by simply trying to increment a value in a textbox while a button is pressed. I can start the count with the button mousedown event, but once the counting has started the button mouseup event is not detected.
''  Remove the following Application.Run code if it used elsewhere in your application.
Application.Run(Form1)

   dim shared dn as boolean
    dn=false

sub stry()
  st:
   
          form1.TextBox1.text = str(val (form1.textbox1.text)+1)
               
          form1.refresh
                         
        if dn=true then goto st
   
END SUB


Function Form1_Button1_MouseDown( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT

  dn=true
  stry()

Function = 0
End Function

''
''
Function Form1_Button1_MouseUp( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
  dn=false
  form1.textbox1.text=""
  Function = 0
End Function


Thanks for any ideas.

Paul Squires

You will need to insert a DoEvents in that tight GOTO loop to ensure that Windows messages hit the application's message queue.


sub stry()
  st:
   
          form1.TextBox1.text = str(val (form1.textbox1.text)+1)
               
          Application.DoEvents
         
          'form1.refresh
                         
        if dn=true then goto st
   
END SUB

Paul Squires
PlanetSquires Software

raymw

Thanks Paul. In my ignorance, I thought the refresh would do the same as DoEvents, but then I also thought that button down could be detected after button had actually gone down. btw, your WinFBE_VisualDesigner.pdf refers to events as 'OnKeyPress' and the like (using 'On' preceding the event name given in the visual designer). Is there a difference? I think OnKeyPress describes the event better. The same as 'MouseHover' event suggests to me that it occurs while the mouse is hovering over the object, whereas it is a single event triggered as the mouse enters the area of the object. I guess I'm looking for buffers...

Paul Squires

Quote from: raymw on August 01, 2018, 09:05:34 AM
...btw, your WinFBE_VisualDesigner.pdf refers to events as 'OnKeyPress' and the like (using 'On' preceding the event name given in the visual designer). Is there a difference? I think OnKeyPress describes the event better.
I have now removed the "On" prefix to avoid confusion.

QuoteThe same as 'MouseHover' event suggests to me that it occurs while the mouse is hovering over the object, whereas it is a single event triggered as the mouse enters the area of the object.
That's not 100% accurate. The MouseEnter event fires when the mouse cursor first touches the control. The MouseHover will fire after the mouse cursor has entered the control and has remained idle/stationary for a short period. The MouseLeave event will fire when the mouse cursor moves off of the control's client area.
Paul Squires
PlanetSquires Software

raymw

Hi Paul, I've added another button to decrement the counter. Sometimes, it seems to me that the mouse down and mouse up does not relate to a specific button. It continues counting even if I click another button on the form.
''
''  Remove the following Application.Run code if it used elsewhere in your application.
Application.Run(jogger)

dim shared xbeg as Long
dim shared xcurr as Long
dim shared millout as double   'this will be x posn from dll?
millout = 500.88
dim shared xdown as Boolean
xdown=false
dim shared xup as boolean
xup=false
xcurr=millout
''
''
Function jogger_Buttonx_Click( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
 
jogger.startx.Text = str(millout)
Function = 0
End Function

''
''
Function jogger_returnx_Click( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
   'stuff here  to step back to starting point
   jogger.nowx.Text = jogger.startx.text
   Function = 0
End Function


''

''
   sub xincrement()
     stt:
      if xup=true  then
         jogger.nowx.Text=str (val (jogger.nowx.text) +1)
         
      END IF
         
       application.doevents
       jogger.refresh
       if xup=false then return
       goto stt
     
   END SUB


sub xdecrement()
     stt:
      if xdown=true  then
         jogger.nowx.Text=str (val (jogger.nowx.text) - 1)
         
      END IF
         
       application.doevents
       jogger.refresh
       if xdown=false then return
       goto stt
     
   END SUB

''
Function jogger_down_MouseDown( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
     
          xdown=true
             xdecrement()
       
   Function = 0
End Function

''''
Function jogger_down_MouseUp( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
   
xdown=false
   Function = 0
End Function

''
Function jogger_up_MouseDown( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
   
xup=true
        xincrement()
Function = 0
End Function

Function jogger_up_MouseUp( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
  xup=false
         
   Function = 0
End Function




Briefly, it's a couple of buttons, up and down, to add or subtract a value in the nowx text box. Often, pressing another button (even 'buttonx' ) continues the last operation, it does not seem to be detecting the change in mouse up or down related to a specific button.  What's the magic word this time?
Best wishes,

Ray

Paul Squires

I put together a test program based on your code. It seems like the MouseDown message is only being received when the button has input focus. This means that you need to click on the button and then do mousedown and mouseup. This is obviously not the behaviour you are needing. I expect that this problem is a combination of CXpButton's message handler and WinFBE's subclassing of that button. I will dive into it more closely later tonight. In the meantime, I have attached a copy of the form so others can verify the behaviour that I am seeing.
Paul Squires
PlanetSquires Software

raymw


Paul Squires

#7
Hi Ray,

This is a combination problem of how Windows handles messages and how WinFBE handles user input through the Event handlers.

When you press the mouse button down, Windows sends the WM_LBUTTONDOWN message. WinFBE routes that message to the Event handler for you to act on. In this case, we enter a very tight loop that does not allow the Event handler to ever exit until a WM_LBUTTONUP message is posted to the message queue. The problem with that is the WinFBE MouseDown Event handler MUST return otherwise the WM_LBUTTONDOWN message will never get fully processed by Windows because it never gets sent to Windows DefWindowProc. Essentially, we are eating the WM_LBUTTONDOWN message by not letting it fully process by staying that tight loop in your xincrement or xdecrement routines. The side effect of the WM_LBUTTONDOWN message not fully processing means that WM_GOTFOCUS and WM_LOSTFOCUS messages never get posted thereby not changing focus to the other button controls.

You might want to rethink the design of the experiment you're coding. Maybe respond to the Click Events of the buttons rather than the MouseDown and MouseUp.

Thinking out loud, I guess that one solution would be to start a thread during mouse down and do your incrementing/decrementing there and then exit the mouse down event handler. Mouseup event handler would terminate the thread.
Paul Squires
PlanetSquires Software

raymw

Hi Paul, thanks for the explanation. In the meantime, I thought I'd see if I could get what I wanted in Firefox, but there I couldn't find the events similar to mouse down. I started thinking about windows apis, then came across the fact that it seems for a checkbox, you can use FF_Control_GetCheck  . Not having used it in a tight loop, but I'd assume that there was a flag set when the check box was checked, and instead of checking for mouse up an down events, you simply inspect the flag. Of course, not sure at what level that flag would be, whether tending towards windows, or the user language. I've noticed that in WinFBE you have the same events for both the checkbox and the button. 

Is there a winapi that can access the state of a button? If so how do I use it? For this particular situation, at least the final program, I need a continuous stream of data being sent, while a button is pressed, in fact their will be four groups of buttons, one per axis, and most likely five or six per axis to send data at different speeds, only one being pressed at a time - most likely a worse situation wrt event handling.

Paul Squires

For a Checkbox, the visual designer help file lists the following property:

CheckState - Gets or sets the state of the control. Refer to the CheckBoxState enum.

So.... something like this:

If Form1.Check1.CheckState = CheckBoxState.Checked Then
   ' My checkbox is checked!
End If

To set the checkbox to a checked state:
Form1.Check1.CheckState = CheckBoxState.Checked

I have implemented checkboxes to allow 3-states (refer to the ThreeState property)
CheckBoxState.Checked
CheckBoxState.UnChecked
CheckBoxState.Indeterminate


Paul Squires
PlanetSquires Software

raymw

Not tried it, nor thought too much, but could not the button have a checkstate? Or, if I use a checkbox, will it still give errors due to the event handler and tight loop? A check box is not the interface I want, but if it works, maybe some features could be blended with the button. e.g. checkstate for button down. I'll have a play with checkboxes, but I'm not holding out much hope
nb, just noticed in my previous post I mentioned Firefox, I meant firefly. Never would have happened with netscape...

Paul Squires

Maybe you're thinking of he Button "ToggleMode" property? That allows you to have an "Off" and "On" type of state.

To get or set the toggle state use:
Form1.Button1.ToggleState = True/False
Paul Squires
PlanetSquires Software

raymw

Not toggle, since afaik you press once to turn on, and press again to turn off. (a bit like the check box wrt number of presses to change state.) I've just sort of integrated the buttons with check boxes, and that behaves as I want - e.g counts while button pressed. BUT it's doing something nasty at a low level - have to do 'ctrl alt delete' to stop the program as everything locks up when I press the red x.

''  Remove the following Application.Run code if it used elsewhere in your application.
Application.Run(jogger)

dim shared xbeg as Long
dim shared xcurr as Long
dim shared millout as double   'this will be x posn from dll?
millout = 500
dim shared xdown as Boolean
xdown=false
dim shared xup as boolean
xup=false
xcurr=millout

''
''
Function jogger_Buttonx_Click( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
 
jogger.startx.Text = str(millout)
Function = 0
End Function

''
''
Function jogger_returnx_Click( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
   'stuff here  to step back to starting point
   jogger.nowx.Text = jogger.startx.text
   Function = 0
End Function


   sub xincrement()
     stt:
      if jogger.checkup.CheckState = checkboxstate.checked  then
        jogger.checkdown.CheckState = checkboxstate.unchecked
         jogger.nowx.Text=str (val (jogger.nowx.text) +1)
         
      END IF
         
       application.doevents
       jogger.refresh
       if jogger.checkup.CheckState = checkboxstate.checked   then
       application.doevents
       goto stt
       end if
   END SUB
'
  sub xdecrement()
     stt:
      if jogger.checkdown.CheckState = checkboxstate.checked  then
        jogger.checkup.CheckState = checkboxstate.unchecked
         jogger.nowx.Text=str (val (jogger.nowx.text) -1)
         
      END IF
         
       application.doevents
       jogger.refresh
       if jogger.checkdown.CheckState = checkboxstate.checked   then
       application.doevents
       goto stt
       end if
   END SUB
'

''
Function jogger_Load( ByRef sender As wfxForm, ByRef e As EventArgs) As LRESULT
   
jogger.show

   fff:
   xincrement()
   xdecrement()
   goto fff
   Function = 0
End Function

''
''
Function jogger_up_MouseDown( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
  jogger.Checkup.CheckState  = checkboxstate.checked
   Function = 0
End Function

''
''
Function jogger_up_MouseUp( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
   jogger.checkup.CheckState = checkboxstate.unchecked
     Function = 0
End Function

''
''
Function jogger_down_MouseDown( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
  jogger.Checkdown.CheckState  = checkboxstate.checked
   Function = 0
End Function

''
''
Function jogger_down_MouseUp( ByRef sender As wfxButton, ByRef e As EventArgs) As LRESULT
  jogger.Checkdown.CheckState  = checkboxstate.unchecked
   Function = 0
End Function


(I may be able to get something going in the toggle button mode - dies it have a checkstate like the checkbox?)

Plenty of room for improvement, but it shows, however ugly the code, I've a chance of doing what I want.
The next stage will be trying to get the interfacing to a pre-written dll (in gwbasic, I believe) and sorting out talking via usb port.

Paul Squires

I'd be surprised if your code worked because once again an Event handler looks like it's being prevented from being completed ("Form1_Load").

Let me look at using the Thread route and using a global to signal on/off or +/- of the values. That would be the best option by far in this case.
Paul Squires
PlanetSquires Software

raymw

It runs, but I can't stop it. Even ctrl alt del doesn't always get the task manager, sometimes i can change user, but often need to power off pc. Dangerous stuff...