Adam R. Frielink wrote:
> I have hit a road block using the Win32-API module.  I've gotten a
> working tool which allows me to modify the contents of the Crystal
> Reports RPT file in memory using the API interface.  Unfortunately,
> everytime I attempt to access a particular method, my application fails
> with a very non-specific message of...  
> 
> "Perl Command Line interpreter has encountered a problem and needs to
> close.  We are sorry for the inconvenience".
> 
> The particular section of code in which the error occurs is:
> 
> ___CODE___
> my $PEGetSelectedPrinter = new Win32::API 'crpe32',
> 'PEGetSelectedPrinter', 'IlPlPlPP', 'I';
> if (not defined $PEGetSelectedPrinter) {
>    die "Can't import API PEGetSelectedPrinter$!\n";
> }
>     
> print DEBUG "Call Get Selected Printer API\n" if $debug;
>    
> my $PEGetSelectedPrinterErr =
> $PEGetSelectedPrinter->Call($job,$PEdriverHandle,$PEdriverHandleLength,$
> PEprinterHandle,$PEprinterHandleLength,$PEportHandle,$PEportHandleLength
> ,$DEVMODE);   #  Errors here
> ___END___

My best first stab at it:

# all but the first arg are pointers and the first arg is a short

my $PEGetSelectedPrinter = new Win32::API 'crpe32', 'PEGetSelectedPrinter',
   'sPPPPPPP', 'I' or die "import PEGetSelectedPrinter: $! ($^E)";

my $printJob = 0;       # not sure whether these are in, out or in/out args
my $driverHandle = pack 'L', 0; # or what the values should be when you call
my $driverLength = pack 'S', 0; # change the 0s where appropriate
my $printerHandle = pack 'L', 0;
my $printerLength = pack 'S', 0;
my $portHandle = pack 'L', 0;
my $portLength = pack 'S', 0;

# typedef struct _devicemodeA {         # DEVMODEA structure
#     BYTE dmDeviceName[CCHDEVICENAME]; #  00 -  31
#     WORD dmSpecVersion;               #  32 -  33
#     WORD dmDriverVersion;             #  34 -  35
#     WORD dmSize;                      #  36 -  37
#     WORD dmDriverExtra;               #  38 -  39
#     DWORD dmFields;                   #  40 -  43
#     short dmOrientation;              #  44 -  45
#     short dmPaperSize;                #  46 -  47
#     short dmPaperLength;              #  48 -  49
#     short dmPaperWidth;               #  50 -  51
#     short dmScale;                    #  52 -  53
#     short dmCopies;                   #  54 -  55
#     short dmDefaultSource;            #  56 -  57
#     short dmPrintQuality;             #  58 -  59
#     short dmColor;                    #  60 -  61
#     short dmDuplex;                   #  62 -  63
#     short dmYResolution;              #  64 -  65
#     short dmTTOption;                 #  66 -  67
#     short dmCollate;                  #  68 -  69
#     BYTE   dmFormName[CCHFORMNAME];   #  70 - 101
#     WORD   dmLogPixels;               # 102 - 103
#     DWORD  dmBitsPerPel;              # 104 - 107
#     DWORD  dmPelsWidth;               # 108 - 111
#     DWORD  dmPelsHeight;              # 112 - 115
#     DWORD  dmDisplayFlags;            # 116 - 119
#     DWORD  dmDisplayFrequency;        # 120 - 123
# #if (WINVER >= 0x0400)        # assuming > 0x0400
#     DWORD  dmICMMethod;               # 124 - 127
#     DWORD  dmICMIntent;               # 128 - 131
#     DWORD  dmMediaType;               # 132 - 135
#     DWORD  dmDitherType;              # 136 - 139
#     DWORD  dmReserved1;               # 140 - 143
#     DWORD  dmReserved2;               # 144 - 147
# } DEVMODEA, *PDEVMODEA, *NPDEVMODEA, *LPDEVMODEA; # 148 bytes

my $mode = pack 'C148', 0 x 180;        # I padded 32 just in case

# Alternately, you could do a proper pack here field by field, but if you don't
# need any content set, you can just treat it like a big array of nulls as I
# did.  If you need to get something returned back out, you either have to
# unpack it all or use substr to get to the field you want and unpack it
# appropriately.  I'm assuming all of the above are 'out' type args.

my $ret = $PEGetSelectedPrinter->Call($printJob, $driverHandle, $driverLength,
   $printerHandle, $printerLength, $portHandle, $portLength, $mode);
if ($ret < 1) { 
        # I assume a true/positive condition would be good
        die "PEGetSelectedPrinter: $! ($^E)";
}

You'll need to unpack whatever values are returned that you need.

> I have tried many variations of the Parameters for the Win32::API object
> creation.  WINGDI.h says a HANDLE should be a long variable type this is
> not working.  I am current under the belief that this abort is caused by
> accessing memory outside my applications work space.  But I am not
> certain.
> 
> Anyone out there had any success with Crystal Reports to do this trivial
> function?  Anyone see my mistakes?  I have included a definition of the
> method with call list below.

Your definition doesn't state which are in, out or both type args nor
what the possible return values are.

> C Syntax
> BOOL CRPE_API PEGetSelectedPrinter ( 
>     short printJob,
>     HANDLE FAR *driverHandle, 
>     short FAR *driverLength, 
>     HANDLE FAR *printerHandle, 
>     short FAR *printerLength, 
>     HANDLE FAR *portHandle, 
>     short FAR *portLength, 
> #if defined (WIN32)
>     DEVMODEA FAR * FAR *mode
> #else 
>     DEVMODE FAR * FAR *mode 
> #endif );
> 
> 
> printJob Specifies the print job that you want to query to get
> information on the nondefault
> printer that has been selected with the report.
> 
> driverHandle Specifies a pointer to the handle of the printer driver for
> the printer that is
> selected with the print job.
> 
> driverLength Specifies a pointer to the length of the printer driver
> name.
> 
> printerHandle Specifies a pointer to the handle of the printer that is
> selected with the print job.
> 
> printerLength Specifies a pointer to the length of the printer name.
> 
> portHandle Specifies a pointer to the handle of the port to which the
> selected printer is
> connected.
> 
> portLength Specifies a pointer to the length of the port name.
> 
> mode Specifies a pointer to the "DEVMODE" on page 533, or DEVMODE
> Windows
> API structure.
_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to