For what it is worth, I have written the following subroutines to make it easy to print pretty much any file to any printer on Windows. Also to get a list of available printers, get the default printer, etc... Thanks to
node 193470 for the inspiration to do this.
Enjoy :)
########################################################
### subs_win32printer.pl - requires the following modules
#use Win32::GUI();
#use Win32::GUI::AxWindow;
#use Win32::API;
#use Win32::TieRegistry ( Delimiter=>"/", ArrayValues=>0 );
########################################################
### References
### http://www.perlmonks.org/?node_id=193470
### http://support.microsoft.com/kb/267240
########################################################
##############
sub printText
{
my $text=shift;
my $printer=shift || getDefaultPrinter();
if(-e $text){$text=getFileContents($text);}
#initialize Win32 API calls
my $OpenPrinter = new Win32::API('winspool.drv', 'OpenPrinter',['P
+','P','P'], 'N');
my $StartDocPrinter = new Win32::API('winspool.drv','StartDocPrint
+er', ['N','N','P'], 'N');
my $StartPagePrinter = new Win32::API('winspool.drv','StartPagePri
+nter', ['N'], 'N');
my $WritePrinter = new Win32::API('winspool.drv','WritePrinter
+', ['N','P','N','P'], 'N');
my $EndPagePrinter = new Win32::API('winspool.drv','EndPagePrint
+er', ['N'], 'N');
my $EndDocPrinter = new Win32::API('winspool.drv', 'EndDocPrint
+er', ['N'], 'N');
my $ClosePrinter = new Win32::API('winspool.drv', 'ClosePrinte
+r', ['N'], 'N');
#Setup devicename
$printer .= "\0";
my $hprinter = pack('x4');
# RAW mode
my $datatype = "RAW\0";
# devmode not passed in pdefaults
# user selected paper/orientation/duplex have no effect in RAW mod
+e
# defaults set at printer will be used
my $pdefaults = pack('px4L', $datatype, 0x8); # PRINTER_ACCESS_USE
$OpenPrinter->Call($printer, $hprinter, $pdefaults) || return $^E;
$hprinter = unpack('L', $hprinter);
# name of document in print manager display
# this won't be there very long unless the printer is off or busy
+with another job
my $docname = "Win32::API print test\0";
my $docinfo = pack("px12", $docname);
$StartDocPrinter->Call($hprinter, 1, $docinfo) || return $^E;
$StartPagePrinter->Call($hprinter) || return $^E;
my $written = pack('x4');
$text .= "\f";
my $len = length $text;
$WritePrinter->Call($hprinter, $text, $len, $written) || return $^
+E;
# one canvas per sheet, next postscript would start new sheet
$EndPagePrinter->Call($hprinter) || return $^E;
$EndDocPrinter->Call($hprinter) || return $^E;
$ClosePrinter->Call($hprinter);
return 1;
}
##############
sub printHtml{
my $file=shift || return "No file passed to printHtml";
my $printer=shift || getDefaultPrinter();
my $navigate='';
if($file=~/^http/is){$navigate=$file;}
else{
if($file !~/[\\\/]/s && -e "$progpath\\$file"){$navigate="file
+://$progpath\\$file";}
elsif(-e $file){$navigate="file://$file";}
}
if(!length($navigate)){return("No such file: $file");}
if(length($printer) && !changeDefaultPrinter($printer)){return "Un
+able to change printer to $printer";}
# Create a window to host the axWindow in
my $Window = new Win32::GUI::Window(
-name => "Window",
-title => "Win32::GUI::AxWindow test",
-pos => [100, 100],
-size => [400, 400],
);
# Add a WebBrowser AxtiveX
my $Control = new Win32::GUI::AxWindow (
-parent => $Window,
-name => "Control",
-control => "Shell.Explorer",
-pos => [0, 0],
-size => [400, 400],
);
our $loaded=0;
# Register some event
$Control->RegisterEvent("StatusTextChange",
sub {
my $self = shift;
my $eventid = shift;
my $event = shift;
print "Event : [$eventid][$event]\n" if length($event) &&
+$debug;
if($eventid==102 && $event=~/^done$/is){$loaded=1;}
} );
# Call Method Navigate to load the page
print "printing $navigate\n" if $debug;
$Control->CallMethod("Navigate", $navigate);
#loop until the page has loaded
while(!$loaded){
Win32::GUI::DoEvents();
select(undef,undef,undef,.1);
}
#Print the URL, page, or image
my $PRINT = 6;
my $DONTPROMPTUSER = 2;
print "Printing $file to $printer\n" if $debug;
#Setting custom header and footer - does not work yet
#http://support.microsoft.com/kb/267240
#my $array = Win32::OLE::Variant->new(VT_ARRAY | VT_BSTR, 2);
#$array->Put(0, 'Custom Header');
#$array->Put(1, 'Custom Footer');
#Call print without prompting user
my $ok=$Control->CallMethod("ExecWB",$PRINT,$DONTPROMPTUSER);
print "Done printing [$ok]...\n" if $debug;
# Event loop
$Window->Hide();
$Window->AddTimer('Shutdown', 1500);
Win32::GUI::Dialog();
exit(0);
sub Shutdown_Timer{
print "shutting down\n" if $debug;
changeDefaultPrinter('',1);
return -1;
}
}
################
sub changeDefaultPrinter
{
my $printer=shift;
my $reset=shift;
#Get current Default Printer
my $default = $Registry->{"CUser/Software/Microsoft/Windows NT/Cur
+rentVersion/Windows/Device"};
if($reset && length($Registry->{"CUser/Software/Microsoft/Windows
+NT/CurrentVersion/Windows/PreDevice"}))
{
#Reset default printer back
my $previous = $Registry->{"CUser/Software/Microsoft/Windows N
+T/CurrentVersion/Windows/PreDevice"};
$Registry->{"CUser/Software/Microsoft/Windows NT/CurrentVersio
+n/"}={
"Windows/" => {"/Device"=>$previous}
};
#remove previous key
$Registry->{"CUser/Software/Microsoft/Windows NT/CurrentVersio
+n/"}={
"Windows/" => {"/PreDevice"=>''}
};
return 1;
}
if(!length($printer)){return 0;}
#if the printer is already set, return true
if($default=~/^\Q$printer\E\,/is){return 1;}
#Does the printer exist?
if(!defined $Registry->{"CUser/Software/Microsoft/Windows NT/Curre
+ntVersion/Devices/$printer"}){return 0;}
#Set PreDevice to current default printer
$Registry->{"CUser/Software/Microsoft/Windows NT/CurrentVersion/"}
+={
"Windows/" => {"/PreDevice"=>$default}
};
my $newval=$Registry->{"CUser/Software/Microsoft/Windows NT/Curren
+tVersion/Devices/$printer"};
$Registry->{"CUser/Software/Microsoft/Windows NT/CurrentVersion/"}
+={
"Windows/" => {"/Device"=>"$printer\,$newval"}
};
return 1;
}
################
sub getDefaultPrinter
{
my ($printer,$drv,$port)=split(/\,/,$Registry->{"CUser/Software/Micros
+oft/Windows NT/CurrentVersion/Windows/Device"},3);
return $printer;
}
################
sub getPrinters
{
my $printers=$Registry->{"CUser/Software/Microsoft/Windows NT/Curr
+entVersion/Devices/"};
my @printers=();
foreach my $printer (keys(%{$printers}))
{
$printer=~s/^\/+//sg;
push(@printers,$printer);
#print "Printer: $printer\n";
}
if(wantarray){return @printers};
return join(',',@printers);
}
return 1;
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.