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