Help with E-Basic Mouse-Capture Loop

David McFarlane mcfarla9 at msu.edu
Mon Dec 13 21:16:30 UTC 2010


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.



More information about the Eprime mailing list