Help with E-Basic Mouse-Capture Loop

David McFarlane mcfarla9 at msu.edu
Mon Dec 13 21:28:29 UTC 2010


Hmm, after drafting and posting that lengthy reply, I checked my 
E-Prime FAQ and found that I had posted another answer to this at 
http://support.pstnet.com/forum/Topic4009-23-1.aspx , so you might 
also look there (contains more detailed code, but lacks the detailed 
explanation).

As long as I am at it, I should have declared my variable in my third 
mouse approach fragment, so here you go:

Dim  p as Point
Mouse.GetCursorPos p.x, p.y

-- David McFarlane, Professional Faultfinder


>Tyler,
>
>Stock reminder:  1) I do not work for PST.  2) PST's trained staff 
>takes any and all questions at 
>http://support.pstnet.com/e%2Dprime/support/login.asp , and they 
>strive to respond to all requests in 24-48 hours -- this is pretty 
>much their substitute for proper documentation, so make full use of 
>it.  3) If you do get an answer from PST Web Support, please extend 
>the courtesy of posting their reply back here for the sake of others.
>
>That said, here is my take...
>
>First some explanation, then some pointers toward solutions...
>
>If I understand correctly the example you found at PST, then your 
>F1DTLabel lies on the Procedure somewhere before your 
>F1DStimulus.  When the Goto goes back to that label, it re-runs your 
>F1DStimulus, which then also re-runs its input mask and captures one 
>more mouse click, which your inline code then processes.  But the 
>Do...Loop code never re-runs the input mask, so you never get 
>another mouse click.  You might get around this by the simple 
>expedient of replacing your F1DTLabel with a bit of inline code that 
>simply says
>
>Do
>
>and then following up with the approprate Loop Until statement in 
>the code that follows the stimulus, but I expect you had something 
>more elegant in mind like handling everything in one inline code object.
>
>So you would need to have some way for your code to get additional 
>mouse clicks.  In addition, if you run this as an ordinary 
>self-paced presentation (i.e., stimulus Duration of (infinite) and 
>End Action of (terminate)), then your program does not get to the 
>inline code until after the first mouse click, so depending on how 
>you want to play this you might have to also find some way to have 
>EP run your code as soon as the stimulus is presented.
>
>So much for explanation, on to solutions.  I will address the second 
>issue first, then the first issue.
>
>You have two options for running inline code right after 
>presentation of a stimulus:  either set the stimulus Duration to 0, 
>or set PreRelease >= Duration.  Most users will naturally adopt the 
>first option, and that indeed works best for self-paced 
>presentations.  But if you want the stimulus to time out or the next 
>stimulus to come at a controlled time later, then your code would 
>have to also handle the timing.  Most users would handle that with 
>some use of Clock.Read, but by judicious use of PreRelease you can 
>have your code run and still let EP automatically handle the 
>stimulus timing for you.  (Some day I will write up a proper 
>explanation of the interactions between Duration, PreRelease, and 
>NextTargetOnsetTime and post that to the list.)  In your case, if 
>your task involves only a self-paced presentation (i.e., stimulus 
>remains until a response, then moves on), then just set stimulus 
>Duration to 0.  In any case, to collect responses while your code 
>runs, you would also have to use "Extended Input" (see Appendix C of 
>the User's Guide that came with E-Prime), e.g., set Time Limit to (infinite).
>
>OK, now to the code.  It all comes down to the line
>
>Set theMouseResponseData = _
>     CMouseResponseData(F1AStimulus.InputMasks.Responses(1))
>
>As it stands now, that line gets the first, one, and only response 
>from the input mask.  You want to allow for more mouse clicks.  I 
>can think of three approaches here.  First, you could use the 
>Advanced properties to increase the MaxCount to some suitably high 
>value.  Then you might change that line to something like
>
>Set theMouseResponseData = _
>     CMouseResponseData( F1AStimulus.InputMasks.Responses(_
>     F1AStimulus.InputMasks.Responses.Count) )
>
>which will now get the latest mouse click each time.  Or you could 
>do without the input mask and address the Mouse device History directly, as in
>
>Set theMouseResponseData = _
>     CMouseResponseData( Mouse.History(Mouse.History.Count) )
>
>(if you do this, make sure first that the Mouse.History contains at 
>least one mouse click, otherwise you will get a run-time error).  Or 
>you could go hard-core and handle the mouse directly (only the mouse 
>(and perhaps the joystick) allows this level of access), e.g.,
>
>Mouse.GetCursorPos p.x, p.y
>
>with other code changes as appropriate (plus code to debounce the 
>mouse, get response time, etc.).
>
>I like the second and third approaches since those allow me to write 
>transportable code that does not need to know anything about the 
>stimulus object (and then I do not use any input mask on the 
>stimulus object).  I actually used the third approach to write an 
>extensive library of routines to do exactly what you are trying to 
>do, but that was before I understood the device History mechanism, 
>now I might rewrite it to use that approach.  (If I ever get that 
>cleaned up enough then I might submit it to STEP to see if they will 
>post it for everyone.)
>
>Finally, your code might in fact work by just making the 
>substitutions I suggest, but as it stands that would repeatedly 
>re-test each mouse click until the next one comes.  So if you want 
>to look like a real programmer then you will add code to test to see 
>when a new click arrives, and while you are at it clean up some of 
>the other sloppiness that was in the original PST example.  I leave 
>that as an exercise for you.
>
>
>I will address your second question in a separate post.
>
>-- David McFarlane, Professional Faultfinder
>"For a successful technology, reality must take precedence over 
>public relations, for nature cannot be fooled."  (Richard Feynman, 
>Nobel prize-winning physicist)
>
>
>At 12/13/2010 10:57 AM Monday, you wrote:
>>I have two questions that I hope someone can help me figure out the
>>answers to.
>>
>>I'm trying to present a Likert scale on the screen using a Slide and
>>capture responses using E-Basic. I have working code for this, based
>>on an example I found on the PST forums. The first issue I am having
>>is what to do when the user clicks an object that doesn't register as
>>a scale response. Initially, the code I was using would simply
>>continue and register the rating as "nothing". However, as I require a
>>response, I simply used an If... condition that would jump back to a
>>Label (and start the trial over) unless it was a registered response.
>>This is the code I have:
>>
>>------------- BEGIN CODE
>>
>>'Designate "theState" as the Default Slide State, which is the
>>'current ActiveState on the Slide object "Stimulus".
>>Dim theState As SlideState
>>Set theState = F1DStimulus.States("Default")
>>
>>Dim theSlideText As SlideText
>>
>>Dim strHit As String
>>Dim intRating As Integer
>>Dim theMouseResponseData As MouseResponseData
>>
>>
>>         'Get the mouse response.
>>         Set theMouseResponseData =
>>CMouseResponseData(F1DStimulus.InputMasks.Responses(1))
>>
>>         'Was there a response?
>>         If F1DStimulus.InputMasks.Responses.Count > 0 Then
>>
>>                 'Determine string name of SlideText object at
>>                 'mouse click coordinates. Assign that value to strHit
>>                 strHit = theState.HitTest(theMouseResponseData.CursorX,
>>theMouseResponseData.CursorY)
>>
>>                 'Did the subject click one of the SlideText sub-objects?
>>                 If strHit <> "" And strHit <> "Question" And 
>> strHit <> "Image" And
>>strHit <> "Instr" Then
>>
>>                         'Gain access to the SlideText sub-object selected
>>                         'Change appearance of selected sub-object 
>> to provide feedback to
>>the subject.
>>                         Set theSlideText =
>>CSlideText(F1DStimulus.States.Item("Default").Objects(strHit))
>>                         theSlideText.BackColor = CColor("red")
>>
>>                         'Redraw the Slide to present changes
>>                         F1DStimulus.Draw
>>
>>                         'Each SlideText is named "Text" followed 
>> by a single digit. The Mid
>>function is
>>                         'instructed to return the 5th character 
>> (i.e. the digit) of strHit
>>for logging purposes.
>>                         intRating = CInt(Mid(strHit, 5, 1))
>>
>>                         'Log rating in the data file under the 
>> attribute "Rating"
>>                         c.SetAttrib "F1DRating", intRating
>>
>>                         Sleep 1000
>>                         theSlideText.BackColor = CColor("gray")
>>
>>                 'The subject did not click a valid sub-object.
>>                 Else
>>                         'Restart the trial
>>                         GoTo F1DTLabel
>>                 End If
>>
>>         'The subject did not respond.
>>         Else
>>                 'Restart the trial
>>                 GoTo F1DTLabel
>>         End If
>>
>>Set theMouseResponseData = Nothing
>>Mouse.ShowCursor FALSE
>>
>>------------- END CODE
>>
>>The above code works flawlessly.
>>
>>The problem I am having now is that I would like to use a Do... Loop
>>Until in place of the GoTo Label command. With the following code in
>>place, clicking on a scale position work, but clicking on an invalid
>>object does not. What happens is that the program fails to capture any
>>mouse clicks beyond the first one. This is the code I am using:
>>
>>------------- BEGIN CODE
>>
>>'This file has been modified by Tyler Burleigh - December 11, 2010
>>
>>'Designate "theState" as the Default Slide State, which is the
>>'current ActiveState on the Slide object "Stimulus".
>>Dim theState As SlideState
>>Set theState = F1AStimulus.States("Default")
>>
>>Dim theSlideText As SlideText
>>
>>Dim strHit As String
>>Dim intRating As Integer
>>Dim theMouseResponseData As MouseResponseData
>>
>>Do
>>         'Get the mouse response.
>>         Set theMouseResponseData =
>>CMouseResponseData(F1AStimulus.InputMasks.Responses(1))
>>
>>         'Was there a response?
>>         If F1AStimulus.InputMasks.Responses.Count > 0 Then
>>
>>                 'Determine string name of SlideText object at
>>                 'mouse click coordinates. Assign that value to strHit
>>                 strHit = theState.HitTest(theMouseResponseData.CursorX,
>>theMouseResponseData.CursorY)
>>
>>                 'Did the subject click one of the SlideText sub-objects?
>>                 If strHit <> "" And strHit <> "Question" And 
>> strHit <> "Image" And
>>strHit <> "Instr" Then
>>
>>                         'Gain access to the SlideText sub-object selected
>>                         'Change appearance of selected sub-object 
>> to provide feedback to
>>the subject.
>>                         Set theSlideText =
>>CSlideText(F1AStimulus.States.Item("Default").Objects(strHit))
>>                         theSlideText.BackColor = CColor("red")
>>
>>                         'Redraw the Slide to present changes
>>                         F1AStimulus.Draw
>>
>>                         'Each SlideText is named "Text" followed 
>> by a single digit. The Mid
>>function is
>>                         'instructed to return the 5th character 
>> (i.e. the digit) of strHit
>>for logging purposes.
>>                         intRating = CInt(Mid(strHit, 5, 1))
>>
>>                         'Log rating in the data file under the 
>> attribute "Rating"
>>                         c.SetAttrib "F1ARating", intRating
>>
>>                         Sleep 1000
>>                         theSlideText.BackColor = CColor("gray")
>>
>>                 End If
>>         End If
>>
>>Loop Until (intRating > 0)
>>
>>Set theMouseResponseData = Nothing
>>Mouse.ShowCursor FALSE
>>
>>------------- END CODE
>>
>>Can someone help me identify what may be causing the program to not
>>register new mouse clicks? I think it's something simple such as a
>>value not being re-set somewhere, however I tried placing Set
>>theMouseResponseData = Nothing and intRating = 0 inside the loop
>>without any luck.
>>
>>Second, is it possible for the E-Basic code to "know" (or read-in) the
>>name of the Procedure it is running? In the code I am working with I
>>need to make 100+ procedures and adapt the code for each (changing,
>>for example, F1AStimulus to F1DStimulus), but it would save me
>>countless hours if I could read in this value. Is this possible?
>>
>>Thanks,
>>Tyler
>
>--
>You received this message because you are subscribed to the Google 
>Groups "E-Prime" group.
>To post to this group, send email to e-prime at googlegroups.com.
>To unsubscribe from this group, send email to 
>e-prime+unsubscribe at googlegroups.com.
>For more options, visit this group at 
>http://groups.google.com/group/e-prime?hl=en.

-- 
You received this message because you are subscribed to the Google Groups "E-Prime" group.
To post to this group, send email to e-prime at googlegroups.com.
To unsubscribe from this group, send email to e-prime+unsubscribe at googlegroups.com.
For more options, visit this group at http://groups.google.com/group/e-prime?hl=en.



More information about the Eprime mailing list