Win32::GUI Community, Thank you for your help in the birth of this sample application. Thanks to Brian Millham for the MUTEX suggestion and sample code. Also to jez for the Hook suggestion. To Robert May, Thanks for such a good perl module. I have posted this sampe so others won't have the same growing pains that I did. I hope you can use it.
The purpose of this application is to scan barcodes using the Socket Mobile ScanAPI.dll. You must have the Socket Mobile SDK installed before this application will run. The application has two buttons. The first "START" will initilize the ScanAPI.dll. The second button "Scan" will trigger the scanner and print out the result. Based on the SocketScan.exe, it will also trigger the scanner by starting a second copy of the application. This is useful when you use a Hot button on a laptop to start the application and trigger the scanner. Please feel free to suggest improvements. Richard Noble ___ Code ___ #!perl -w use strict; use warnings; use Win32::GUI qw(MB_OK MB_ICONASTERISK); use Win32::API; use Win32::API::Prototype; use Carp qw(croak); use Win32::Mutex; # Preloaded methods go here. ########################################################################### # DLL Function call setup ########################################################################### my $ScanInit = Win32::API->new('ScanAPI.dll','long ScanInit(HWND hWnd, long wminseriton, long wmRemoval)'); my $ScanOpenDevice = Win32::API->new('ScanAPI.dll','long ScanOpenDevice(HANDLE hScanner)'); my $ScanCloseDevice = Win32::API->new('ScanAPI.dll','long ScanCloseDevice(HANDLE hScanner)'); my $ScanRequestDataEvents = Win32::API->new('ScanAPI.dll','long ScanRequestDataEvents(HANDLE hScanner, HWND hWnd, long wmScannerData)'); my $ScanTrigger = Win32::API->new('ScanAPI.dll','long ScanTrigger(HANDLE hScanner)'); my $ScanGetData = Win32::API->new('ScanAPI.dll','long ScanGetData(HANDLE hScanner, LPSTR lpBuff, LPINT BufSize)'); # define user messages sub WM_USER() {1024}; sub WM_INSERTION(){WM_USER + 1}; # the message we want on device insertions sub WM_REMOVAL(){WM_USER + 2}; # the message we want on device removals sub WM_SCANNERDATA(){WM_USER + 3}; # the message we want when data is available sub WM_CHS_STATUS(){WM_USER + 4}; # the message we want when CHS status changes sub WM_SCANBADGE(){WM_USER + 5}; # the message we want when application starts a 2nd copy to scan a badge sub NOCALLBACK(){1}; # SCANAPI return values use constant SR_SUCCESS => 0; use constant SR_INVALID_WMINSERTION => 1; use constant SR_INVALID_WMREMOVAL => 2; use constant SR_PLUG_THREAD_FAILURE => 3; use constant SR_DEVICE_THREAD_FAILURE => 4; use constant SR_INVALID_SCANNER_HANDLE => 5; use constant SR_OPEN_FAILURE => 6; use constant SR_INVALID_WMSCANNERDATA => 7; use constant SR_NO_DATA => 8; use constant SR_BUFFER_TOO_SMALL => 9; use constant SR_SCANNER_NOT_OPEN => 10; use constant SR_INVALID_SOUND_TYPE => 11; use constant SR_WAVFILE_NOT_FOUND => 12; use constant SR_MEMORY_FAILURE => 13; use constant SR_INVALID_ERR => 14; use constant SR_TOO_MANY_USERS => 15; use constant SR_NOT_INITIALIZED => 16; use constant SR_DEVICE_FAILURE => 17; use constant SR_INTERNAL_FAILURE => 18; use constant SR_INVALID_STRUCTURE => 19; use constant SR_HOTSWAP_ERROR => 20; use constant SR_SCANNER_REMOVED => 21; use constant SR_INVALID_WMCHSSTATUS => 22; our $ret; our $ScannerHandle; sub Buffersize(){1024}; # Create or open the mutex # This code checks to see if a copy of the application is running. # If it detects the first copy it sends it a message to trigger the # scanner. Then exit after the message has been posted. my $mutex = Win32::Mutex->new(1, "Mutex Test"); # Die if the mutex exists (183 == ERROR_ALREADY_EXISTS) if ($^E == 183) { # find first copy of application and get its window handle my $hWnd=Win32::GUI::FindWindow("\x00","ScanTest"); Win32::GUI::SendMessage($hWnd, WM_SCANBADGE, 1, 0); exit; } # Create a window, saving it in variable $main my $main = Win32::GUI::Window->new( -name => 'Main', -width => 100, -height => 100, -title => 'ScanTest', ); # Add a label to the window (by default a label # has size big enough for its text and is positioned # in the top left of its containing window) $main->AddLabel( -text => $main->{-handle}, ); $main->AddButton( -name => 'button1', -text => "Start", ); $main->AddButton( -name => 'button2', -text => "Scan", -left => 50, ); # set up message hooks $main->Hook(WM_INSERTION, \&WMINSERTION); $main->Hook(WM_REMOVAL, \&WMREMOVAL); $main->Hook(WM_SCANNERDATA, \&WMSCANNERDATA); $main->Hook(WM_SCANBADGE, \&WMSCANBADGE); # Show our main window $main->Show(); # Enter the windows message loop, often referred # to as the "dialog phase". Win32::GUI::Dialog(); # When the message loop returns control to our # perl program, then the interaction with the # GUI is complete, so we exit. exit(0); ###################### ###################### # The Terminate event handler for a window # named 'Main'. Returning -1 causes the # windows message loop to exit and return # control to our perl program. sub Main_Terminate { return -1; } sub button1_Click { # initilize the ScanAPI.dll $ret=$ScanInit->Call($main->{-handle},WM_INSERTION,WM_REMOVAL); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } } 1; sub button2_Click { # trigger the scanner $ret=$ScanTrigger->Call($ScannerHandle); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } } 1; sub WMINSERTION { # Handle the scanner insertion message # get data passed from the message queue my ($object, $wParam, $lParam, $type, $msgcode) = @_; return unless $type == 0; return unless $msgcode == WM_INSERTION; # Store the scanner handle to a global $ScannerHandle=$lParam; # call the ScanAPI open device function my $ret=$ScanOpenDevice->Call($lParam); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } # if the ScanAPI opens the scanner, add this application to the ScanAPI.dll message queue $ret=$ScanRequestDataEvents->Call($lParam, $main->{-handle}, WM_SCANNERDATA); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } return 1; } sub WMREMOVAL { # Handle the scanner removal message # get data passed from the message queue my ($object, $wParam, $lParam, $type, $msgcode) = @_; return unless $type == 0; return unless $msgcode == WM_REMOVAL; # Close the ScanAPI my $ret=$ScanCloseDevice->Call($lParam); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } return 1; } sub WMSCANNERDATA { # Handle the scanner has data waiting message # get data passed from the message queue my ($object, $wParam, $lParam, $type, $msgcode) = @_; return unless $type == 0; return unless $msgcode == WM_SCANNERDATA; # The $wParam tell us how much data is in the scanner buffer. If there is # a problem in future, multiply the $wParam by the Win32::API::Type->sizeof() # function using the TCHAR # define a buffer the size of the data in the scanner buffer my $buffer= 0 x $wParam; my $buffersize= \$wParam; # store the reference to $wmParam, why I don't know. # Get the data from the scanner my $ret=$ScanGetData->Call($ScannerHandle, $buffer, $buffersize); if ($ret != SR_SUCCESS) { &DisplayScanError($ret); return 0; } #Process scanner data here print $buffer."\n\n"; return 1; } sub WMSCANBADGE { # This message tells the application to trigger the scanner. This message is sent # from a 2nd copy of the application # get data passed from the message queue print "a second copy of the program has started\n"; my ($object, $wParam, $lParam, $type, $msgcode) = @_; return unless $type == 0; return unless $msgcode == WM_SCANBADGE; #`trigger the scanner button2_Click(); return 1; } sub DisplayScanError() { # process any ScanAPI error messages my $ErrorCode=$_[0]; my $ErrorText=''; if ($ErrorCode == SR_INVALID_WMINSERTION) { $ErrorText= "ScanAPI Error: Invalid WM_INSERTION Value"; } if ($ErrorCode == SR_INVALID_WMREMOVAL) { $ErrorText= "ScanAPI Error: Invalid WM_REMOVAL Value"; } if ($ErrorCode == SR_PLUG_THREAD_FAILURE) { $ErrorText= "ScanAPI Error: SR_PLUG_THREAD_FAILURE"; } if ($ErrorCode == SR_DEVICE_THREAD_FAILURE) { $ErrorText= "ScanAPI Error: SR_DEVICE_THREAD_FAILURE"; } if ($ErrorCode == SR_INVALID_SCANNER_HANDLE) { $ErrorText= "ScanAPI Error: SR_INVALID_SCANNER_HANDLE"; } if ($ErrorCode == SR_OPEN_FAILURE) { $ErrorText= "ScanAPI Error: SR_OPEN_FAILURE"; } if ($ErrorCode == SR_INVALID_WMSCANNERDATA) { $ErrorText= "ScanAPI Error: SR_INVALID_WMSCANNERDATA"; } if ($ErrorCode == SR_NO_DATA) { $ErrorText= "ScanAPI Error: SR_NO_DATA"; } if ($ErrorCode == SR_BUFFER_TOO_SMALL) { $ErrorText= "ScanAPI Error: SR_BUFFER_TOO_SMALL"; } if ($ErrorCode == SR_SCANNER_NOT_OPEN) { $ErrorText= "ScanAPI Error: SR_SCANNER_NOT_OPEN"; } if ($ErrorCode == SR_INVALID_SOUND_TYPE) { $ErrorText= "ScanAPI Error: SR_INVALID_SOUND_TYPE"; } if ($ErrorCode == SR_WAVFILE_NOT_FOUND) { $ErrorText= "ScanAPI Error: SR_WAVFILE_NOT_FOUND"; } if ($ErrorCode == SR_MEMORY_FAILURE) { $ErrorText= "ScanAPI Error: SR_MEMORY_FAILURE"; } if ($ErrorCode == SR_INVALID_ERR) { $ErrorText= "ScanAPI Error: SR_INVALID_ERR"; } if ($ErrorCode == SR_TOO_MANY_USERS) { $ErrorText= "ScanAPI Error: SR_TOO_MANY_USERS"; } if ($ErrorCode == SR_NOT_INITIALIZED) { $ErrorText= "ScanAPI Error: SR_NOT_INITIALIZED"; } if ($ErrorCode == SR_DEVICE_FAILURE) { $ErrorText= "ScanAPI Error: SR_DEVICE_FAILURE"; } if ($ErrorCode == SR_INTERNAL_FAILURE) { $ErrorText= "ScanAPI Error: SR_INTERNAL_FAILURE"; } if ($ErrorCode == SR_INVALID_STRUCTURE) { $ErrorText= "ScanAPI Error: SR_INVALID_STRUCTURE"; } if ($ErrorCode == SR_HOTSWAP_ERROR) { $ErrorText= "ScanAPI Error: SR_HOTSWAP_ERROR"; } if ($ErrorCode == SR_SCANNER_REMOVED) { $ErrorText= "ScanAPI Error: SR_SCANNER_REMOVED"; } if ($ErrorCode == SR_INVALID_WMCHSSTATUS) { $ErrorText= "ScanAPI Error: SR_INVALID_WMCHSSTATUS"; } Win32::GUI::MessageBox( $main, "ScanAPI.dll Error Message: $ErrorText", MB_OK|MB_ICONASTERISK ); return 0; } ___ End Code ___ -- View this message in context: http://www.nabble.com/Sample-application-to-access-the-ScanAPI.dll-from-Socket-Mobile-tp18062929p18062929.html Sent from the perl-win32-gui-users mailing list archive at Nabble.com. ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ Perl-Win32-GUI-Users mailing list Perl-Win32-GUI-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users http://perl-win32-gui.sourceforge.net/