Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re^2: Unable to capture mouse events in Win32::Console

by Marshall (Canon)
on Apr 26, 2022 at 03:47 UTC ( [id://11143296]=note: print w/replies, xml ) Need Help??


in reply to Re: Unable to capture mouse events in Win32::Console
in thread Unable to capture mouse events in Win32::Console

Interestingly enough, this sample.pl does not work as advertised on my Windows 10 machine.
When it starts, "TEST SUITE" is flashing. It says, "Press any key or mouse button to proceed". However, no mouse click will work, although pressing any other key will work.

I believe that the 1 second sleep idea is a "red herring" -> doesn't matter. All that means is that it will take at most one second for the keyboard event to be seen. A normal assumption would be that if you don't poll fast enough, you miss a character because apparently (not sure) that the event stack is only one character deep?

I did play around with the Properties of my standard command window. I turned off any of the normal fancy CTL-V or CTL-C off. But I haven't found the "magic formula" yet. In my testing with short programs, I am seeing that a right click causes the following program to "hang". When the program starts, hitting a normal key produces expected results, but a mouse click gets you nowhere!

I have seen other test programs fail to see the Right-Click. When the test program exits, I get the normal CTL-V behavior. Somehow the Mouse Click is not getting to the running test program and is buffered and presented to the command shell when the test program exits. The correct voo-doo for Console should be able to get this character (mouse click).

I am curious as to what others find. The sample code is complex and I am just trying to find a simple subset that works. This does not.

# https://docs.microsoft.com/en-us/windows/console/reading-input-buffe +r-events\ # reference Perl Monks: https://www.perlmonks.org/?node_id=1212227 use strict; use warnings; use Win32::Console; my $OUT = new Win32::Console(STD_OUTPUT_HANDLE); my $IN = new Win32::Console(STD_INPUT_HANDLE); $OUT->Write("Perl version $^V \n"); $OUT->Write("more text could go here\n\n"); my $n_buttons = $IN->MouseButtons(); $OUT->Write("Your mouse has $n_buttons buttons\n"); $IN->Mode(ENABLE_MOUSE_INPUT); my $counter = 0; while ($counter++ < 5) #5x time out for testing... { if (my @console_events = $IN -> Input ()) { $OUT->Write ("calling input method!\n"); # my @console_events = $IN -> Input (); ##not needed goof (COR +RECTION) $OUT->Write ("An Event was detected! number= ".@console_events. +"\n"); foreach my $event (@console_events) { $OUT->Write("event: $event\n"); } exit; # exit the program, do not fall through to that final + print instruction } else { sleep 1; #should be fine to poll 1x per second for testing... } } $OUT->Write("Timed out! Bummer!\n");

Replies are listed 'Best First'.
Re^3: Unable to capture mouse events in Win32::Console
by pryrt (Abbot) on Apr 26, 2022 at 13:54 UTC
    I played briefly with Marshall's adaptation of the script (though I upped to 60 instead of 5 loops, and before the exit I added a sleep(10);).

    If I run cmd.exe, and from there run perl pm.pl, when I try to do any mouse, it is consumed by my cmd.exe > properties > options, so the script doesn't show any events. If I go to cmd.exe > properties > options, and turn off all the edit and text selection options, then run the script, it still grabs my mouse clicks -- and when I look, I see that it turned back on Quick Edit Mode and Insert Mode! If I do the sequence of run the script, then turn off all the edit options, if I click or wiggle, I do see a mouse event (#2):

    C:\Users\peter.jones\Downloads\TempData\perl>perl pm.pl Perl version v5.30.0 more text could go here Your mouse has 5 buttons calling input method! An Event was detected! number= 6 event: 2 event: 42 event: 48 event: 1 event: 32 event: 0

    Similarly, if I run from Explorer using my double-click association, so that it opens a new cmd.exe window (which doesn't inherit my default options with edit options enabled), I get events. (This was the reason I added the sleep(10): so that the created cmd.exe window wouldn't go away immediately after processing the mouse event(s).

    update: As an aside, if I add the mode setting from vr's post (which I hadn't read yet when I created this post), modified to use Marshall's $IN console, then I find I don't need to futz with the cmd.exe properties manually. Thanks!
    my $save = $IN-> Mode; END { $IN-> Mode( $save )}; $IN-> Mode(( $save | 0x0010 ) & ~0x0040 ); # +MOUSE, -QUICK_EDIT

    When looking at the adapted code, I have a nitpick and a query.

    Nitpick: (this originated in fireblood's original): per Indirect Object Syntax, one should avoid the indirect-object style new Win32::Console(...) syntax, and instead use Win32::Console->new(...) syntax (or even the Win32::Console::->new(...) syntax; there are some circumstances where perl can interpret it ambiguously without both the :: and ->). It's not critical in this example, and I know that Win32::Console still recommends the old notation, but one can learn and use best practices even when the documentation/examples don't use it.

    Query to Marshall: why are you throwing away the first @console_events ? You are actually getting two events, and only reporting the first. I can see this if I change the "calling input method!" print to $OUT->Write ("calling input method!" . @console_events . "(@console_events)\n");, at which point the above in-cmd.exe example becomes

    C:\Users\peter.jones\Downloads\TempData\perl>perl pm.pl Perl version v5.30.0 more text could go here Your mouse has 5 buttons calling input method!6(2 42 47 0 32 1) An Event was detected! number= 6 event: 2 event: 42 event: 48 event: 1 event: 32 event: 0

    For the if condition, did you really want to PeekInput of Win32::Console instead, or stick with GetEvents of Win32::Console as shown in the original, so that it polls whether there was an event, but doesn't remove the event from the queue? Or was there a specific reason for throwing away the first event?

    Regarding the two mys, I am actually surprised there isn't a warning, because the my @console_events in the if condition is then masked by the my @console_events inside the block, but the use warnings isn't saying anything about it. (which it normally does, like in perl -le "use strict; use warnings; my $x; my $x" (warning: windows quote syntax, given the windows context of Win32::Console))

    TL;DR

    Back to the main point: if your cmd.exe window is not trapping the mouse inputs with its edit options, Win32::Console can see mouse events. But sometimes, when you think it won't trap, cmd.exe re-enables at least a couple of the traps, so you have to re-disable them after the program has started (edit: or by using the Mode command).
      Your testing agrees with what I was seeing. I also saw Quick edit mode get turned back on also, but was so tired that I didn't really believe my own eyes!

      I have no idea why my erroneous extra console_events didn't trigger a warning. I went through numerous versions of this thing, trying different stuff. At the time of this version I think I was trying to figure out if actually getting the console events was a blocking or non-blocking call. One other version of the code had a check to see if there was an event at all inside the if statement, then the actual read of the event was the second (now superfluous) one.

Re^3: Unable to capture mouse events in Win32::Console
by fireblood (Scribe) on Apr 26, 2022 at 04:13 UTC

    Hi Marshall, thanks for modifying it and testing it with the two different consoles. That looked promising. Also, after writing what I wrote about the sample code and my own code both not working, my next thought was that if the problem appears in two different programs written by two different people, then maybe the problem was in my mouse, and that I should try re-running it using a better/newer mouse. But since you reproduced the same problem on your academic computer that I was having, I'm thinking now that the mouse is not the problem.

    But both of us are running Windows 10, and the Win32::Console module has been around for a lot longer than Windows 10 has. I wonder if it's a Windows 10 problem? An Internet search of Win32::Console reveals that other languages have versions of it as well. I wonder if they are encountering problems when running programs written in those other languages on Windows 10 machines? No way to pin that down since this is a Perl forum. I did notice that one discussion about this module on Perl in particular -- http://computer-programming-forum.com/53-perl/1fb16f663d489dbe.htm -- goes back to June of 1902, so maybe it is only a Windows 10 problem. But that date makes me even more impressed with the magnitude of what Larry has accomplished beyond just the brilliant design of Perl.

      HI fireblood,
      I did spend some hours messing with this. On the surface, it appeared simple. But I found out that it was not. I do kick myself in the behind because at one point, I did get the "2" for mouse instead of "1" for keyboard and then without thinking, changed so many things at once that I am unable to re-create that result. The false "ahh-ha" syndrome! Hey, it happens!

      I am sure that there is a way to make Win32::Console do what you want, I just don't know how. I think this is a case where the documentation is just not very good. However, Perl Tk GUI's work great. There will be more support here for Tk GUI than for low level console stuff. I commented just this day about the Tk TableMatrix object in another thread.

      It could be that this is what is called an "X Y" problem. You are asking how to do X, but what you really need to know is how to do Y. There are various formulations of this situation. Since you are talking about mouse clicks, some more detail about how you envision your interface working would be helpful. there are all kinds of zoomy GUI things like drop down context sensitive things (i.e. right click ala Windows menus) that are possible.

      It could even perhaps be that your code becomes more simple and no polling loop is required.

      Out of curiosity, where does this 16 buttons come from? I've never seen a Windows mouse with more than 3, but perhaps that exists with some sort of special thing for a gaming control?

        The Razer Naga has "up to 19" buttons. I have an older model that "only" has the 1-12 side panel that I've been very happy with past couple of years. Great for arpgs / mmos / mobas where your main inputs are usually mapped to (e.g.) your 1-0 keys (but you can of course remap things arbitrarily in their software).

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

        Hi Marshall, my mouse is a Redragon M990 -- https://www.amazon.com/Redragon-M990-High-Precision-Programmable-Profiles/dp/B0171AOQG0. I got it so that I could program its buttons to echo out passwords when clicked. I do have a password manager (Dashlane) which meets most of my needs, but the extra edge that the mouse provides is being able to click on a button to type out my login password into a login screen which is encountered prior to being logged on to where Dashlane can then take over. Also, the passwords are stored in the mouse itself, so if I go to a place where I must use a different computer on which my Dashlane profile is not available, as long as I plug my mouse into that computer I can navigate to my usual online locations and then click on the mouse buttons to enter my passwords.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11143296]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-19 01:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found