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