Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Win32 GUI Input or Event

by perldiverx (Beadle)
on Aug 26, 2013 at 15:55 UTC ( #1050977=perlquestion: print w/replies, xml ) Need Help??
perldiverx has asked for the wisdom of the Perl Monks concerning the following question:

I'm creating a program that will take credit card swipe from a USB swiper or the credit card info can be entered manually. I've got a loop currently to read the credit card data being entered from a swiper and I have some buttons on the bottom of the window that the user can press to bring up fields to enter the credit card info into manually (ie card number, expiration date, etc). The problem is that while I'm looping to look for the credit card swipe I cannot accept the user's mouse click on the buttons. Has anyone every done this before/any ideas as how to do it?
Current code:

#!/usr/bin/perl use strict; use warnings; use diagnostics -verbose; use Win32; use Win32::GUI qw(ES_WANTRETURN WS_VISIBLE WS_VSCROLL ); my ($DOShwnd, $DOShinstance) = Win32::GUI::GetPerlWindow(); #Win32::GUI::Hide($DOShwnd); my $desk = Win32::GUI::GetDesktopWindow(); my $dw = Win32::GUI::Width($desk); my $dh = Win32::GUI::Height($desk); use vars qw/$window $status_bar $button1 $button2 $button3 $card_field $sale_field $event_field $card_number_label $option_flag/; $window = Win32::GUI::Window->new( -name => 'main', -text => "Credit Card Authorization", -pos => [170,130], -size => [625,450], -helpbox => 0, -resizable => 0, -maximizebox => 0, ); my $transaction_info = read_psin(); my @transaction_info = @{$transaction_info}; my $card_type = $transaction_info[0]; my $sale_amount = $transaction_info[1]; $status_bar = $window->AddStatusBar( -name => 'status_bar', -text => '', ); $window->Change( -onMouseMove => sub { $status_bar->Text(''); }, ); $button1 = $window->AddButton( -name => 'manual_dial', -text => '1', -size => [60,25], -pos => [120,355], -onMouseMove => sub { $status_bar->Text('Manual card entry with dia +l-out for approval'); }, ); $button2 = $window->AddButton( -name => 'swipe_phone', -text => '2', -size => [60,25], -pos => [270,355], -onMouseMove => sub { $status_bar->Text('Swipe card entry with phon +e call for an approval'); }, ); $button3 = $window->AddButton( -name => 'manual_phone', -text => '3', -size => [60,25], -pos => [420,355], -onMouseMove => sub { $status_bar->Text('Manual card entry with pho +ne call for an approval'); }, ); $window->AddLabel( -name => 'header', -text => 'Credit Card Authorization', -pos => [160,10], ); $window->AddLabel( -name => 'card_type', -text => 'Card Type:', -pos => [20,40], ); $window->AddLabel( -name => 'amount', -text => 'Sale Amount:', -pos => [20,80], ); $card_field = $window->AddTextfield ( -name => 'card_field', -text => $card_type, -size => [180,20], -pos => [90,39], -readonly => 1, ); $sale_field = $window->AddTextfield( -name => 'sale_field', -text => $sale_amount, -size => [180,20], -pos => [90,79], -readonly => 1, ); $event_field = $window->AddTextfield( -name => 'event_field', -size => [360,180], -pos => [120,160], -readonly => 0, -multiline => 1, ); my $card_input = $window->AddTextfield( -name => 'card_input', -size => [480,40], -pos => [90,119], -multiline => 1, -visible => 0, ); $card_number_label = $window->AddLabel( -name => 'card_number_label', -text => 'Card Number: ', -pos => [280,40&], -visible => 0, ); $window->Show(); $window->DoEvents(); $event_field->Append("Initializing modem... "); init_modem(); $event_field->Append("initialized\n"); $card_input->SetFocus(); $event_field->Append("Please swipe card... "); $window->Show(); $window->DoEvents(); my $input1 = $card_input->GetLine(0); my $input2 = $card_input->GetLine(1); while ($card_input->GetLine(1) !~ /\?$/) { #swipe ends second line wi +th a question mark $card_input->SetFocus(); $input1 = $card_input->GetLine(0); $input2 = $card_input->GetLine(1); $window->DoEvents(); # Win32::GUI::Dialog(); ####working here to take in the cl +ick event#### } $event_field->Append("swiped\n"); print "\$input1: $input1\n"; print "\$input2: $input2\n"; my $cc_number; if ($input1 =~ /^\%B(\d{16})/i) { $cc_number = $1; } my $exp_dt; if ($input2 =~ /\=(\d{2})(\d{2})(.*)/) { $exp_dt = $2 . $1; } sleep 1; $event_field->Append("Connecting... ");

Replies are listed 'Best First'.
Re: Win32 GUI Input or Event
by SuicideJunkie (Vicar) on Aug 26, 2013 at 16:55 UTC

    You didn't mention what you're using to show the GUI... that may be important.

    In any case, check out the section "Coexisting with Other GUI Main Loops" from Mastering Perl/Tk

    Try using a repeating timer event to check the USB device on a regular basis without preventing window events from being handled

Re: Win32 GUI Input or Event
by BrowserUk (Pope) on Aug 26, 2013 at 18:46 UTC

    Personally, I'd have a button on the display "Swipe card" and only enter the read loop when the button was pushed.

    Alternatively, put the swiper loop in a thread.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Win32 GUI Input or Event
by kejohm (Hermit) on Aug 27, 2013 at 04:23 UTC

    I have never used a credit card scanner but, if they're like barcode scanners, I'm assuming they simply enter their content in whatever has focus, in this case your hidden $card_input textfield. You could use a Change() event on the textfield to tell you when the card has been swiped. Example: (untested)

    ... # Create controls $event_field->Append("Initializing modem... "); init_modem(); $event_field->Append("initialized\n"); $card_input->SetFocus(); $event_field->Append("Please swipe card... "); $window->Show(); Win32::GUI::Dialog(); sub card_input_Change { my $input1 = $card_input->GetLine(0); my $input2 = $card_input->GetLine(1); $event_field->Append("swiped\n"); print "\$input1: $input1\n"; print "\$input2: $input2\n"; my $cc_number; if ($input1 =~ /^\%B(\d{16})/i) { $cc_number = $1; } my $exp_dt; if ($input2 =~ /\=(\d{2})(\d{2})(.*)/) { $exp_dt = $2 . $1; } sleep 1; $event_field->Append("Connecting... "); ... }
      Figured it out. What I did to get this to work is loop checking for one of two flags. The DoEvents method coupled with a while loop checks for both outcomes, albeit not concurrently. I had to put a short sleep timer in the loop or the click would not register. I've also removed the onMouseMove params from the buttons because the mouse clicks were not registering with them on their.

      So here's what I changed to get this to work:
      use Time::HiRes qw(usleep); #added use vars qw/$cc_number $exp_dt/; #add these two my $input1 = ''; #added these here so I my $input2 = ''; #could use them in subs my $swiped = 0; my $clicked = 0; # ... #old code matched in this section # ... $event_field->Append("Please swipe card... "); $window->Show(); $window->DoEvents(); while ($swiped != 1 && $clicked != 1) { $swiped = check_swipe(); usleep(750000); $window->DoEvents(); } if ($swiped == 1) { $event_field->Append("swiped\n"); } sleep 1; $event_field->Append("Connecting... "); sub check_swipe { $input1 = $card_input->GetLine(0); $input2 = $card_input->GetLine(1); if ($card_input->GetLine(1) !~ /\?$/) { $card_input->SetFocus(); $input1 = $card_input->GetLine(0); $input2 = $card_input->GetLine(1); $window->DoEvents(); } if ($input1 =~ /^\%B(\d{16})/i) { $cc_number = $1; } if ($input2 =~ /\=(\d{2})(\d{2})(.*)/) { $exp_dt = $2 . $1; return 1; } return 0; } sub manual_dial_Click { $card_number_label->Show(); $clicked = 1; }
        This old solution was not very good. What I ended up doing was using the keydown event handler and regex'd on that string.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1050977]
Approved by ww
Front-paged by Corion
[Corion]: Do you want to launch a script and keep the command prompt/console window open?
[Corion]: Do you want to wait for a key press before closing the window?
[LanX]: I want the command line in the history
[tye]: -Mouse
[Corion]: Option a) would mean launching cmd.exe /k c:\path\to\ batchfile- launching-perl- script.cmd. Option b) would be to add pause as the last line of said batch file.
[LanX]: First day after holidays ... and already stressed by the fact that colleagues changed stuff without communication ... apparently I'm the only one trying to fight entropy
[Corion]: LanX: The command is always in the history if you typed it in before. If you didn't type the command into the command line, it will not be there. I think there is doskey which can stuff command lines into the history
LanX damns the cult of CB ;-)
[LanX]: please forget my last 3 posts

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (13)
As of 2017-03-27 15:44 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (320 votes). Check out past polls.