P/N: 980552-001Zebra Card Solutions 6/15/2005 Page 1 of 40 www.zebracard.com
Page 2
DISCLAIMER
Zebra Technologies has made every effort to document this product fully and
accurately. The software and documentation is, nevertheless, provided and
licensed “as is.” Developer acknowledges and agrees that it has no rights to any
upgrades, modifications, enhancements or revisions which Zebra Technologies
may make to the software or documentation.
Developer assumes all risk, and Zebra Technologies makes no representation,
warranty or guarantee whatsoever, express or implied, as to functionality, utility,
error free operation, absence of any virus, or any other aspect of the software’s
operation or performance, or the accuracy, completeness or adequacy of the
documentation. Developer agrees that its use of the software and
documentation is at developer’s own risk.
ZEBRA TECHNOLOGIES SPECIFICALLY DISCLAIMS ANY AND ALL
WARRANTIES OF ANY NATURE IN CONNECTION WITH THE SOFTWARE
AND DOCUMENTATION, TO INCLUDE, BUT NOT BE LIMITED TO, ANY
WARRANTY OF MERCHANTABILITY OF FITNESS FOR A PARTICULAR
PURPOSE.
Neither Zebra Technologies nor any of its agents, consultants, distributors or
dealers shall, under any circumstances, be liable for any indirect, incidental or
consequential damages arising from the use of this publication. Zebra
Technologies reserves the right to make improvements and/or changes in the
products and programs as described in this manual at any time without notice.
This document describes the programming interface to control Zebra
Technologies P640 and P640i card printers. This manual along with the code
and the reference distributed with it are known as the Zebra Technologies P640
Programmer’s Manual. This manual is intended as a reference for the developer
wishing to write drivers or applications that control a Zebra Technologies P640 or
P640i printer.
This manual is organized to assist the developer in rapidly becoming familiar with
the P640/P640i printer. The first section gives an overview describing the driver
architecture. The next section describes the programming steps necessary to
carry out specific functions. Following this is a brief discussion of the code.
Developers using this manual should have a working knowledge of printers in
general and a working knowledge of Ethernet networks, and USB and parallel
interfaces.
The user interface (UI) dll handles the display of the property sheets to the user
when the user selects either Printing Preferences… or Properties | Device
Settings. The UI gets the configuration information from the printer and displays
it to the user. It also sends commands to the printer depending on user actions.
The UI is responsible for updating the DevMode structure with driver
configuration information. The DevMode structure is stored by the operating
system in the registry, and is passed to the driver dlls whenever they are called.
2.2 Kernel/User mode dll
The kernel/user mode dll (DRV) handles the GDI (Graphical Device Interface)
calls that are made by application programs to send print data to the printer. The
DRV formats the print data for the printer performing such operations as black
extraction and image rotation. It then writes the data to the spooler.
2.3 Language Monitor
The language monitor dll (LM) is called by the spooler when a print job is sent to
the printer. The LM passes the print job along to the appropriate port monitor.
The LM then monitors the status of the job as it prints and is responsible for
communicating any errors that occur, to the user. The LM displays error dialogs
explaining the corrective action to be taken to correct the error and handles
reprinting jobs as necessary.
The language monitor also receives the GetPrinterData and SetPrinterData calls
made by application programs. It passes these commands to the printer and
passes any data returned from the printer back to the calling application.
2.4 Port Monitors
There are port monitor dlls (PMs) for each communication type that the P640
supports, parallel, USB, and Ethernet. The PMs are called by the language
monitor and are used to pass the data between the LM and the printer using the
appropriate protocol.
3 Sending Commands to the Printer through the Driver
An application program can send commands to the printer through the Language
Monitor, using the GetPrinterData function. The command sent can be either a
simple command or a request for the printer to return data. If data is to be
returned, the caller must provide a buffer to store the returned data. If the
returned data is variable in length, GetPrinterData can be called first with pData
set to NULL and nSize set to 0. The function will fail, but the buffer size needed
will be returned in pcbNeeded. See section 3.4 below for further explanation of
these parameters.
It is good practice to call SetPrinterData with a NULL text string before calling
GetPrinterData to ensure that all data from previous commands is erased.
To pass data to the printer, such as for setting the printer’s configuration (i.e.
SMARTCARD_DATA), the application must first call SetPrinterDataEx with the
data to be sent. This will store the data in the registry for retrieval by the
Language Monitor. A GetPrinterData command is then issued to tell the
Language Monitor to retrieve the data and send it to the printer.
The header file messages.h contains #defines for all of the messages that can be
send to the Language Monitor by the driver or an application program. The
header file printerdefs.h contains the data structure definitions for data being
send to the printer and data being received from the printer. The structures
make it easy to format the data correctly for the printer and to parse messages
coming back from the printer.
if(OpenPrinter(TEXT(“Zebra P640”),&hPrinter,&pd))
{
//Before Get, do dummy set to clear cached data
SetPrinterData(hPrinter,COMMAND,REG_SZ,(LPBYTE)TEXT(""),
_tcslen(TEXT(""))*sizeof(TCHAR));
// if the command’s entry in messages.h says “Data: Yes”, set Data
SetPrinterDataEx(hPrinter,ATL_MESSAGE_KEY,DATANAME,REG_SZ,
(LPBYTE)DATABUFFER, DATABUFFER_LENGTH));
// Data buffer MUST be at least ERROR_TEXT_SIZE TCHARs long
// to receive results
dwRet = GetPrinterData(hPrinter,Command,&dwType,(LPBYTE)Data,
ERROR_TEXT_SIZE*sizeof(TCHAR),&dwRead);
if (!(_tcsncmp(Data,ERROR_SUCCESS_TEXT, ERROR_TEXT_SIZE)))
{
// success
}
hPrinter
handle to a printer from OpenPrinter
pValueName
pointer to a string of TCHAR type. UNICODE should be defined in the project.
Make sure it is NUL terminated. This is the command to execute. In some
cases, an argument can come after the command. If such a command is
entered, the remainder of the string after the command will be converted to
single byte characters and sent to the printer.
pType
Type of data. This is ignored in our implementation so it should be NULL.
pData
Output Data buffer. If the command does not need data back, this may be
NULL. The data is returned exactly as returned from the printer, so no big
endian->little endian conversion is done, so if you need to cast it to something
you need to do that yourself.
nSize
size of pData. If pData is NULL, this should be 0
pcbNeeded
the number of bytes read into pData. Note that, in general if GetPrinterData
returns FALSE, the data here is invalid. It is NOT set to the number of bytes
needed. However, there is an exception to this in the GET commands for
paths and strings. In this case, it will be set to the needed number of bytes.
Return Values
ERROR_SUCCESS if the function succeeds, otherwise an error value.
3.4.1 Excerpt from messages.h header file
Listed below are the commands that can be sent to the printer. These are pulled
from the messages.h header file used by the driver and IDPrint. For further
explanation of any command’s function, see section 2 above. Each command is
defined in the following format:
Command Name (ESC Code sent to printer by Language Monitor)
#define for the command – this will be the pValueName parameter
Input = function expects arguments following the command string input arguments should be
concatenated to the command
Output = function returns data in pData
Data = Data is to be put in the registry ahead of time by the SetPrinterDataEx command
¾NOTE: The data structures listed for input and output are defined in printerdefs.h
Request Sensor Data
#define REQUEST_SENSOR_DATA TEXT("SENSORDATA")
Input: No
Output: Yes – SENSORDATA structure
Data: No
typedef struct tagSENSORDATA
{
union {
WORD wFlipLift;
struct {
// NOTE: this assumes that you will be doing a big->little endian conversion
// on this word, since wFlipLift needs it!!
// these are backwards because this compiler does bitfields backwards
struct {
BYTE iButtonDone:1; // bit 0 - Write to iButton is complete
BYTE CarriageNearHopper:1; // bit 1 - Carriage is near
// card hopper - 0 = Away, 1 = Near
BYTE HopperDoorOpen:1; // bit 2 - Hopper door open - 0 =
// Closed, 1 = Open
BYTE CardLamExit:1; // bit 3 - Card Laminator Exiting
// Sensor - 0 = No card, 1 = Card
BYTE CardLamEnter:1; // bit 4 - Card Laminator Entering
//Sensor - 0 = No card, 1 = Card
BYTE ElevatorDown:1; // bit 5 - Elevator Down - 0 = Up, 1 =
// Down
BYTE CarriageHome:1; // bit 6 - Carriage Home Position - 0
// = Out of home, 1 = At home
BYTE DoorOpen:1; // bit 7 - Door Open Sensor - 0 =
// Closed, 1 = Open
} LoByte;
// these are backwards because this compiler does bitfields backwards
struct {
BYTE JumperSelect1:1; // bit 8 - Jumper selection 1
// (reserved)
BYTE ACLoss:1; // bit 9 - Loss of AC - 0 = power, 1 = no
//power
BYTE HeadUp:1; // bit 10 - head state - 0 = down, 1 = up
BYTE Reserved11:1; // bit 11 - reserved
BYTE Reserved12:1; // bit 12 - reserved
BYTE OvlAdvButton:1; // bit 13 - overlay advance button
BYTE RibAdvButton:1; // bit 14 - ribbon advance button
BYTE PrintButton:1; // bit 15 - print button
} HiByte;
} BooleanSensorsBits;
} Sensors_FlipLift;
WORD wCardPresence;
WORD wPrintStationSyncMark;
WORD wTopLam;
WORD wBottomLam;
WORD wLamPresentThresh;
WORD wLamAbsentThresh;
WORD wReserved3;
} SENSORDATA, far *LPSENSORDATA;
Feed Laminate #define LAMINATE_FEED TEXT("LAMINATEFEED")
Input: No
Output: No
Data: No
Request Status
#define REQUEST_STATUS TEXT("REQUESTSTATUS")
Input: No
Output: Yes – Printer Status Code see below
Data: No
#define DIAG_ERR_START 0x4080 // diagnostic failure on comp NN (80h-FFh)
#define DIAG_ERR_END 0x40FF // diagnostic failure on comp NN (80h-FFh)
#define FLASH_ACT 0x8019 // flash task active error
#define DATA_ERR 0x4800 // communications data error
#define ILLEG_REQ 0x0002 // illegal request resulted from last command
#define DOOR_OPEN 0x0403 // Door open
#define HTR_ERR 0x8013 // heater error
#define PAPER_JAM 0x3B05 // media jam
#define LOST_HOME 0x8004 // lost home position
#define PH_JAM 0x8001 // printhead jam
#define FLP_ST_JAM 0x8005 // flip station jam
#define TMP_FAIL 0x8000 // temperature shutdown
#define FLIP_OUT 0x8006 // card lost after flip
#define NO_MEDIA 0x3A00 // medium not present
#define LAM_FAIL 0x8012 // laminate failure
#define RIB_FAIL 0x3600 // ribbon failure
#define IMAGE_FAIL 0x8002 // image conversion error
#define CLN_FAIL 0x8003 // cleaning tape failure
#define CARD_JAMERR 0x800B // card jammed in laminator
#define MAGFLUXRB 0x8025 // no flux transitions detected during readback
#define READBACKERR 0x8027 // EIN Data Error
#define WAIT_MODE 0x0402 // logical unit not ready, command required
// (aka printer halted after error)
#define EIN_READY 0x0004 // EIN ready
#define READ_EIN 0x0003 // reading EIN
#define BUSY 0x0001 // printer busy - can't receive print image
#define NO_ERRORS 0x0000 // no additional sense information
#define eLamCardNotInsertedErr 0x8028 // card failed to insert into laminator
#define eBottomNoGapErr 0x8020 // no gap detected in bottom laminate
#define eTopNoGapErr 0x8021 // no gap detected in top laminate
#define eTempRangeErr 0x8022 // CJ temp out of range
#define eCardNotSeatedErr 0x8023 // card not properly seated in truck
#define eCardCarrierStallErr 0x8024 // lost steps driving to print position
#define eMagFluxVerifyErr 0x8026 // no flux transitions detected during verify
#define eTopLamOutErr 0x8029 // top laminate out
#define eBottomLamOutErr 0x802A // bottom laminate out
#define eLamCardJamErr 0x802B // card jammed in laminator
#define eLamCardExitErr 0x802C // card didn't exit laminator
#define eCardDoorOpenErr 0x802D // card hopper door opened
#define eMissingDongleErr 0x802E // Dongle is missing or wrong serial number
// RFID errors, i-series only!
#define eRfidBoardNoResponse 0x801A // rfid board did not respond
#define eNoRfidOnRibbon 0x801B // no rfid ribbon present
#define ePanelDecErr 0x801C // problem decrementing panel count
Request Status without clearing error codes
#define REQUEST_STATUS_NO_CLEAR TEXT("REQUESTSTATUSNOCLR")
Input: No
Output: Yes – Printer Status Code see above
Data: No
Get Device ID
#define GET_DEVICE_ID TEXT("GETDEVICEID")
Input: No
Output: Yes – Printer’s device id string
Data: No
Get Data Block
#define GET_DATA_BLOCK TEXT("GETDATABLOCK")
Input: No
Output: Yes – BLOCKDATA structure
Data: No
// these are all backwards because one of the compilers is weird and does
// bitfields strangely
typedef union tagDATABLOCK{
WORD DataBlockWord;
struct {
// these are backwards because this compiler does bitfields backwards
struct {
BYTE MAG_TRACK1_DATA:1; // bit 8 - ESC * # K - mag track 1 data
BYTE MAG_TRACK2_DATA:1; // bit 9 - ESC * # L - mag track 2 data
BYTE MAG_TRACK3_DATA:1; // bit 10 - ESC * # M - mag track 3 data
BYTE YELLOW_DATA_PLANE:1; // bit 11 - ESC * # O - yellow data
// plane
BYTE MAGENTA_DATA_PLANE:1; // bit 12 - ESC * # P - magenta data
// plane
BYTE CYAN_DATA_PLANE:1; // bit 13 - ESC * # Q - cyan data plane
BYTE BLK_DATA_PLANE1:1; // bit 14 - ESC * # T - 1st black data
// plane
BYTE BLK_DATA_PLANE2:1; // bit 15 - ESC * # W - 2nd black data
// plane
} HiByte;
// these are backwards because this compiler does bitfields backwards
struct {
BYTE BLK_COUNT:4; // bits 0-3 - count of ESC * # V - image data
BYTE RESERVED:3; // bits 4-6 - reserved
BYTE PRINT_DATA:1; // bit 7- ESC * # C - print data
} LoByte;
} DataBlockBits;
} DATABLOCK, far *LPDATABLOCK;
Request Features
#define REQUEST_FEATURES TEXT("REQUESTFEATURES")
Input: No
Output: Yes – FEATUREDATA structure
Data: No
typedef struct tagFEATUREDATA
{
WORD wCmdLen;
CHAR bCmdId[2];
WORD wFeatures;
} FEATUREDATA, far *LPFEATUREDATA;
wFeatures can be a combination of the following:
#define FEATURE_UV_ENABLE 0x01
#define FEATURE_ID_CODE 0x02
#define FEATURE_ID_KEY 0x04
Clear Password
#define CLEAR_PASSWORD TEXT("CLEARPASSWORD")
Input: No
Output: No
Data: No
Notes:
- You must call SEND_PASSWORD and send the old password first
Accept EIN & Print Card
#define ACCEPT_EIN TEXT("ACCEPTEIN")
Input: No
Output: No
Data: No
NOTE: for the following commands anything in <>'s is pulled out of the user supplied pData
buffer
Move Card Carrier
#define MOVE_CARD_CARRIER TEXT("MOVECARDCARRIER")
Input: Yes, position to move to as an ASCII number (see MOVE_ defines below)
Output: No
Data: No
Reprint
#define REPRINT TEXT("REPRINT")
Input: Yes, number of times to reprint as an ASCII number
Output: No
Data: No
Retry - Number of times to retry communications
#define RETRY TEXT("RETRY")
Input: Yes, number of times to retry as an ASCII number
Output: No
Data: No
Get Retries - retrieves retry setting from monitor
#define GET_RETRIES TEXT("GETRETRIES")
Input: No
Output: Number of retries
Data: No
Flush buffer
#define FLUSH_BUFFER TEXT("FLUSHBUFFER")
Input: Yes, buffer to flush as an ASCII number (see FLUSH_ defines below)
Output: No
Data: No
Set Features
#define SET_FEATURES TEXT("SETFEATURES")
#define SET_FEATURES_DATA TEXT("SETFEATURESDATA")
Input: No
Output: No
Data: Yes, SET_FEATURES_DATA should be a REG_SZ type that is the path to the
features file to use to upgrade the printer as a NUL terminated Unicode string.
Send Password
#define SEND_PASSWORD TEXT("SENDPASSWORD")
Input: Yes, CRC16 of text password, which serves as the "encrypted" password
Output: No
Data: No
Notes:
- Once set, this is sent to the printer before every print job
- To change it, send this password, then the CLEAR_PASSWORD command,
then the new password
Send Smart Card Command Data
#define SEND_SMARTCARD TEXT("SENDSMARTCARD")
#define SMARTCARD_DATA TEXT("SMARTDATA")
Input: Yes, data size
Output: Yes, same as RECEIVE_SMARTCARD
Data: Yes, a command to send to the smart card. Please use REG_BINARY for the type.
Move a card to the probe position
#define MOVE_TO_SMART_PROBE TEXT("PICKPROBE")
Input: No
Output: No
Data: No
Smart card programming complete
#define FINISH_SMARTCARD TEXT("SMARTCARDACCEPT")
Input: No
Output: No
Data: No
Reject smart card
#define REJECT_SMARTCARD TEXT("SMARTCARDREJECT")
Input: No
Output: No
Data: No
Receive smart card data
#define RECEIVE_SMARTCARD TEXT("RCVSMARTCARD")
Input: No
Output: Yes, use SMARTCARDDATA structure
Data: No
Smart Card Calibration test
#define SMART_CARD_CALIBRATION TEXT("SMARTCALB")
Input: No
Output: No
Data: No
Select Smartcard Encoder
#define SMART_ENCODER_SELECT TEXT("SMARTENCSEL")
Input: Yes
0, 1, or 2 depending on encoder
0 contact
1 iClass
2 Mifare
Output: No
Data: No
NOTE: The following commands are to ask the Language Monitor to perform certain
functions, they are NOT passed on to the printer.
Set Format String
#define SET_FORMAT_STRING TEXT("SETFORMATSTRING")
#define FORMAT_STRING_DATA TEXT("FORMATSTRINGDATA")
Input: No
Output: No
Data: Yes, FORMAT_STRING_DATA should be a REG_SZ type that is the
format string to use for logging as a NUL terminated Unicode string.
Notes:
- This doesn't actually talk to the printer, it just sets the string
the language monitor uses for logging
- This string is set globally, for all printers the monitor handles
- Whether or not to log each printer is set in a per-printer config
in the DevMode.
The format string can include any of the following:
%H Hour of current time, 24-hour time
%I Hour of current time, 12-hour time
%M Minute of current time
%S Second of current time
%m Current month as number
%b Month as abbreviated name
%B Month as full name
%d Day of month as number
%a Abbreviated weekday name
%A Full weekday name
%y 2-digit year
%Y 4-digit year
%s Printer serial number
%C First MAC Address located on
system
%P First IP Address located on system
%R Mag readback data
%D Mag data written to card
%E Printer error code
%J Job ID
%U Username that submitted the job
%% Literal percent sign
Get Format String
#define GET_FORMAT_STRING TEXT("GETFORMATSTRING")
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just returns the current
string that the language monitor is logging with as ASCII characters
#define SET_LOG_PATH TEXT("SETLOGPATH")
#define LOG_FILE_PATH TEXT("LOGFILEPATH")
Input: No
Output: No
Data: Yes, LOG_FILE_PATH should be a REG_SZ type that is the
path to the Log file to use for logging as a NUL terminated Unicode string.
Notes:
- This doesn't actually talk to the printer, it just sets the path
the language monitor uses for the log file
- This path is set globally, for all printers the monitor handles
- Whether or not to log in each printer is set in a per-printer config
in the DevMode.
Get Log Path
#define GET_LOG_PATH TEXT("GETLOGPATH")
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just returns the current
log file path
- Size needed is determined like one of the normal Windows functions.
#define SET_LOGGING TEXT("SETLOGGING")
#define LOGGING_NO_TEXT BOOL_NO_TEXT
#define LOGGING_YES_TEXT BOOL_YES_TEXT
Input: Yes
Output: No
Data: No
Notes:
- This doesn't actually talk to the printer, it just sets the logging setting
- This value is set per printer
- The Yes/No value should be concatenated on to the end of the string, so
that the actual string is "SETLOGGING0" or some such
Get Logging Setting
#define GET_LOGGING TEXT("GETLOGGING")
#define LOGGING_NO BOOL_NO
#define LOGGING_YES BOOL_YES
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just gets the logging setting
- One of the state values below will be returned as a byte
Set UV Path
#define SET_UV_PATH TEXT("SETUVPATH")
#define UV_FILE_PATH TEXT("UVFILEPATH")
Input: No
Output: No
Data: Yes, UV_FILE_PATH should be a REG_SZ type that is the
path to the UV file to open and send to the printer as a NUL
terminated Unicode string.
Notes:
- This doesn't actually talk to the printer, it just sets the path
the language monitor uses for the UV file
- This path is set globally, for all printers the monitor handles
- Whether or not to use UV in each printer is set as SET_SEND_UV_FILE
Get UV Path
#define GET_UV_PATH TEXT("GETUVPATH")
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just returns the current
UV panel path
- Size needed is determined like one of the normal Windows functions.
#define SET_DISABLE_OTHER_BUTTON TEXT("SETDISABLEOTHER")
#define DISABLE_OTHER_BUTTON_NO_TEXT BOOL_NO_TEXT
#define DISABLE_OTHER_BUTTON_YES_TEXT BOOL_YES_TEXT
Input: Yes
Output: No
Data: No
Notes:
- This doesn't actually talk to the printer, it just sets the send disable other
buttons command
- This value is set per printer
- The Yes/No value should be concatenated on to the end of the string, so
that the actual string is "SETDISABLEPRINT0" or some such
Get Disable Other Buttons
#define GET_DISABLE_OTHER_BUTTON TEXT("GETDISABLEOTHER")
#define DISABLE_OTHER_BUTTON_NO BOOL_NO
#define DISABLE_OTHER_BUTTON_YES BOOL_YES
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just gets the send disable other
buttons state
- One of the state values below will be returned as a byte
Set Disable Error Checking
#define SET_DISABLE_ERROR_CHECKING TEXT("SETDISABLECHECK")
#define DISABLE_ERROR_CHECKING_NO_TEXT BOOL_NO_TEXT This is normal
#define DISABLE_ERROR_CHECKING_YES_TEXT BOOL_YES_TEXT This is none
#define DISABLE_ERROR_CHECKING_REDUCED_TEXT REDUCED_TEXT This is reduced
Input: Yes
Output: No
Data: No
Notes:
- This doesn't actually talk to the printer, it just sets the disable error checking
command
- This value is set per printer
- The Yes/No value should be concatenated on to the end of the string, so
that the actual string is "SETDISABLECHECK0" or some such
Get Disable Error Checking
#define GET_DISABLE_ERROR_CHECKING TEXT("GETDISABLECHECK")
#define DISABLE_ERROR_CHECKING_NO BOOL_NO This is normal
#define DISABLE_ERROR_CHECKING_YES BOOL_YES This is none
#define DISABLE_ERROR_CHECKING_REDUCED REDUCED This is reduced
Input: No
Output: Yes
Data: No
Notes:
- This doesn't actually talk to the printer, it just gets the disable error checking
state
- One of the state values below will be returned as a byte
hPrinter
handle to a printer from OpenPrinter
pValueName
pointer to a string of TCHAR type. UNICODE should be defined in the project.
Make sure it is NUL terminated. This is the command to execute. In some
cases, an argument can come after the command. If such a command is
entered, the remainder of the string after the command will be converted to
single byte characters and sent to the printer.
pType
Type of data. Set to REG_SZ.
pData
Output Data buffer. Set to NULL.
nSize
size of pData. If pData is NULL, this should be 0
Return Values
ERROR_SUCCESS if the function succeeds, otherwise an error value.
Registry holding area for messages.
#define ATL_MESSAGE_KEY TEXT("AtlMessages")
SetPrinterDataEx is used to set data to be passed to the printer/driver. The
ATL_MESSAGE_KEY refers to the location in the registry that the data is stored
for retrieval by the Language Monitor.
pointer to a string of TCHAR type. UNICODE should be defined. Make sure
string is NUL terminated. Use ATL_MESSAGE_KEY for this.
pValueName
pointer to a string of TCHAR type. UNICODE should be defined in the project.
Make sure it is NUL terminated. This is the command to execute. In some
cases, an argument can come after the command. If such a command is
entered, the remainder of the string after the command will be converted to
single byte characters and sent to the printer.
pType
Type of data. Set to REG_SZ.
pData
Output Data buffer. Set to NULL.
nSize
size of pData. If pData is NULL, this should be 0
Return Values
ERROR_SUCCESS if the function succeeds, otherwise an error value.
The StartDoc function must be called first to let the printer driver know that a
print is being started. After sending all the pages of image data, EndDoc must
be called to inform the driver that the print is complete.
4.1 StartDoc Definition
int StartDoc(HDC hdcPrinter, DOCINFO *DocInfo);
hdcPrinter
Handle to the device context for the print job.
DocInfo
Pointer to a DOCINFO structure containing the name of the document file and
the name of the output file.
Return Values
If the function succeeds, the return value is greater than zero. This value is the
print job identifier for the document. If the function fails, the return value is less
than or equal to zero. To get extended error information, call GetLastError.
4.2 EndDoc Definition
intEndDoc(HDC hdcPrinter);
hdcPrinter
Handle to the device context for the print job.
Return Values
If the function succeeds, the return value is greater than zero. If the function
fails, the return value is less than or equal to zero. To get extended error
information, call GetLastError.
Prior to sending each page of image data, StartPage must be called. After all
data for a page is sent, EndPage must be called. If you are creating a doublesided card the sequence of calls should be like this:
StartPage(hdcPrinter);
Send Front Side Image Data
EndPage(hdcPrinter);
StartPage(hdcPrinter);
Send Back Side Image Data
EndPage(hdcPrinter);
EndDoc(hdcPrinter);
int StartPage(HDC hdcPrinter);
…
int EndPage(HDC hdcPrinter);
StartDoc(hdcPrinter, &DocInfo);
hdcPrinter
Handle to the device context for the print job.
Return Values for either function
If the function succeeds, the return value is greater than zero. If the function
fails, the return value is less than or equal to zero. To get extended error
information, call GetLastError.
4.4 Image Data
If Black Extraction of data is enabled, the driver will extract that data from the
image data sent down from the application and send it separately to the printer.
Image Data can be sent in several ways to the printer. The entire image can be
sent as one large bitmap, or each piece of the image can be sent separately.
When sending a single bitmap use SetDIBitsToDevice. If sending pieces
separately, the following function calls can be used:
TextOut - for sending text strings
Pixel - for sending individual pixels
Output - for drawing lines
BitBlt/DeviceBitmapBits - for bitmap images
The SetDIBitsToDevice function sets the pixels in the specified rectangle on the
device that is associated with the destination device context using color data
from a device-independent bitmap (DIB).
SetDIBitsToDevice (HDC hdcPrinter, int XDest, int YDest, DWORD dwWidth,
DWORD dwHeight, int XSrc, int YSrc, UINT uStartScan,
UINT cScanLines, CONST VOID *lpvBits,
CONST BITMAPINFO *lpbmi, UINT fuColorUse);
hdcPrinter
Handle to the device context.
XDest
Specifies the x-coordinate, in logical units, of the upper-left corner of the
destination rectangle.
YDest
Specifies the y-coordinate, in logical units, of the upper-left corner of the
destination rectangle.
dwWidth
Specifies the width, in logical units, of the DIB.
dwHeight
Specifies the height, in logical units, of the DIB.
XSrc
Specifies the x-coordinate, in logical units, of the lower-left corner of the DIB.
YSrc
Specifies the y-coordinate, in logical units, of the lower-left corner of the DIB.
uStartScan
Specifies the starting scan line in the DIB.
cScanLines
Specifies the number of DIB scan lines contained in the array pointed to by
the lpDibBits parameter.
Pointer to DIB color data stored as an array of bytes. For more information,
see the following Remarks section lpbmi.
lpbmi
Pointer to a BITMAPINFO structure that contains information about the DIB.
fuColorUse
Specifies whether the bmiColors member of the BITMAPINFO structure
contains explicit red, green, blue (RGB) values or indexes into a palette. This
value should be set to DIB_RGB_COLORS.
Return Values
If the function succeeds, the return value is the number of scan lines set. If the
function fails, the return value is zero. To get extended error information, call
GetLastError.
4.6 TextOut Definition
The TextOut function writes a character string at the specified location, using the
currently selected font.
BOOL TextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString);
hdc
Identifies the device context.
nXStart
Specifies the logical x-coordinate of the reference point that Windows uses to
align the string.
nYStart
Specifies the logical y-coordinate of the reference point that Windows uses to
align the string.
lpString
Points to the string to be drawn. The string does not need to be zeroterminated, since cbString specifies the length of the string.
If the function succeeds, the return value is nonzero. If the function fails, the
return value is zero. To get extended error information, call GetLastError.
4.7 Output Definition
GDI calls this function when an application calls functions, such as LineTo,
Rectangle, and Ellipse.
WORD Output(LPPDEVICE lpDestDev, WORD wStyle, WORD wCount,
Address of a PDEVICE or PBITMAP structure that specifies the destination
device or bitmap.
wStyle
Type of output to draw. The Zebra P640 Photo ID Printer Driver supports the
following codes:
OS_BEGINNSCAN (80) Begins a series of scan lines
OS_ENDNSCAN (81) Ends a series of scan lines
OS_SCANLINES (4) Draws a set of horizontal line segments
wCount
Number of POINT structures in the array pointed to by the lpPoints
parameter.
lpPoints
Address of an array of POINT structures. The array has wCount elements.
For most output styles, this parameter contains the device coordinates for
each point in the figure.
lpPPen
Address of a PPEN structure that specifies the physical pen that is used to
use to draw lines and borders. This parameter is NULL if no lines or borders
are to be drawn.
lpPBrush
Address of a PBRUSH structure that specifies the physical brush that is used
to use to fill the interiors of figures and draw scan lines. This parameter is
NULL if no interiors or scan lines are to be drawn.
lpDrawMode
Address of a DRAWMODE structure that contains information to use when
drawing, such as binary-raster operation, background mode, and foreground
and background color.
Address of a RECT structure that contains coordinates for the clipping
rectangle. If this parameter is NULL, the clipping rectangle is the entire
display surface.
Return Values are as follows:
1 Function was successful.
0 Unrecoverable error occurred.
-1 Function does not support the specified style.
4.8 Pixel Definition
GDI calls this function when simulating output or when an application calls the
SetPixel or GetPixel function.
DWORD Pixel(LPPDEVICE lpDestDev, WORD X, WORD Y, DWORD dwPhysColor,
LPDRAWMODE lpDrawMode);
This function sets or retrieves the color of the specified pixel. The function sets
the given pixel to the color given by the dwPhysColor parameter if the
lpDrawMode parameter specifies a binary-raster operation. The Pixel function
returns the physical color of the pixel if the lpDrawMode parameter is NULL.
lpDestDev
Address of a PDEVICE or PBITMAP structure that specifies the destination
device or bitmap.
X and Y
x- and y-coordinate of the pixel to retrieve or set.
dwPhysColor
Physical color value used to set the pixel.
lpDrawMode
Address of a DRAWMODE structure that specifies the binary-raster operation
to use to combine the physical color with the existing pixel color. If
lpDrawMode is NULL, the Pixel function returns the current color of the
specified pixel.
Return Values
Returns either the physical color of the specified pixel or 1 if the function is
successful, 0x80000000L otherwise.
This function will copy a DIB to a device-specific bitmap.
void DeviceBitmapBits(LPPDEVICE lpBitmap, WORD fGet, WORD iStart,
WORD cScans, LPSTR lpDIBits, LPBITMAPINFO lpBitmapInfo,
LPDRAWMODE lpDrawMode, LPINT lpTranslate);
lpBitmap
Address of a PBITMAP structure that specifies a device-specific memory
bitmap.
fGet
Flag that specifies whether the function sets or retrieves bitmap bits. If this
parameter is zero, the function sets the bits; if the parameter is 1, the function
retrieves the bits.
iStart
Starting scan number.
cScans
Number of scans to set or retrieve.
lpDIBits
Address of a buffer that contains or receives the bitmaps bits. If the fGet
parameter is zero, the function copies data from the buffer into the bitmap; if
fGet is 1, the function copies the bits to the buffer from the bitmap. If this
parameter is NULL, the function fills the biSizeImage member in the
BITMAPINFO structure pointed to by the lpBitmapInfo parameter, but does
not copy bitmap bits.
lpBitmapInfo
Address of a BITMAPINFO structure that specifies the dimensions and format
of the DIB. The function must check the biPlanes and the biBitCount
members. If biPlanes is not 1 or biBitCount is not 1 or 24, the function
returns an error value. The function compares the widths of the devicespecific bitmap and the DIB. If the widths are not equal, the function clips to
the smaller of the two bitmaps.
lpDrawMode
Address of a DRAWMODE structure that specifies the text (foreground) and
background colors to use if color conversion is required.
lpTranslate
Address of an array of color translation values for converting palette colors to
actual device colors. The Zebra P640 Photo ID Printer Driver ignores this
parameter.
Returns one of these values:
>0 Number of scanlines set or retrieved
0 Error
The BitBlt function performs a bit-block transfer of the color data corresponding
to a rectangle of pixels from the specified source device context into a destination
device context.
BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
hdcDest
Handle to the destination device context.
nXDest
Specifies the logical x-coordinate of the upper-left corner of the destination
rectangle.
nYDest
Specifies the logical y-coordinate of the upper-left corner of the destination
rectangle.
nWidth
Specifies the logical width of the source and destination rectangles.
nHeight
Specifies the logical height of the source and the destination rectangles.
hdcSrc
Handle to the source device context.
nXSrc
Specifies the logical x-coordinate of the upper-left corner of the source
rectangle.
nYSrc
Specifies the logical y-coordinate of the upper-left corner of the source
rectangle.
dwRop
Specifies a raster-operation code. These codes define how the color data for
the source rectangle is to be combined with the color data for the destination
rectangle to achieve the final color.
The following list shows the raster operation codes that are supported by the
Zebra P640 Photo ID Printer Driver:
Value Description
Fills the destination rectangle using the color
BLACKNESS
associated with index 0 in the physical palette. (This
color is black for the default physical palette.)
Merges the colors of the source rectangle with the
specified pattern by using the Boolean AND operator.
Merges the colors of the inverted source rectangle with
the colors of the destination rectangle by using the
Boolean OR operator.
Copies the inverted source rectangle to the
destination.
Combines the colors of the source and destination
rectangles by using the Boolean OR operator and then
inverts the resultant color.
Copies the specified pattern into the destination
bitmap.
Combines the colors of the specified pattern with the
colors of the destination rectangle by using the
Boolean XOR operator.
Combines the colors of the pattern with the colors of
the inverted source rectangle by using the Boolean OR
operator. The result of this operation is combined with
the colors of the destination rectangle by using the
Boolean OR operator.
Combines the colors of the source and destination
rectangles by using the Boolean AND operator.
Copies the source rectangle directly to the destination
rectangle.
Combines the inverted colors of the destination
rectangle with the colors of the source rectangle by
using the Boolean AND operator.
Combines the colors of the source and destination
rectangles by using the Boolean XOR operator.
Combines the colors of the source and destination
rectangles by using the Boolean OR operator.
Fills the destination rectangle using the color
associated with index 1 in the physical palette. (This
color is white for the default physical palette.)
Return Values
If the function succeeds, the return value is nonzero. If the function fails, the
return value is zero. To get extended error information, call GetLastError.
Magnetic encoder data is sent to the printer before the image is sent, but after
the document is started with the StartDoc escape command. The magnetic
stripe data can be sent anytime after the StartDoc escape command. If more
than one card is being printed as a single document, the magnetic encoder data
must be sent prior to the beginning of each card. This would mean prior to every
page with a YMC ribbon, and prior to every second page with a YMCK ribbon.
5.1 Sending Magnetic Encoder Data Method
This method imbeds the data as text to be printed with control characters that
allow the Windows printer driver to identify the text as Mag encoder data and
direct it to the magnetic encoder instead of printing it. This approach can be used
with a generic application such as a word processor to encode cards. The format
of the data is as follows:
Where the startchar is the "~" (tilde) character, the separator is the "="(equal)
character and the track number is 1, 2, or 3. The information is the data to be
encoded on the given track. There is no end character, but each track must be
sent separately. This can be done with three TextOut functions. Do not append a
new line at the end of each track data. If you are using a word processor to send
the data, a newline character will work to separate the tracks.
Example:
StartDoc(hdcPrinter, &DocInfo);
if (NoImage) //if you do not send any image (i.e. only send mag data),
//StartPage and EndPage are needed
StartPage(hdcPrinter);
lstrcpy(lpszString, "~1=");
lstrcat(lpszString, Track1); //do not append new line!!!
cbString = lstrlen(lpszString);
TextOut(hdcPrinter,0,0, lpszString, cbString);
Functionality of the Photo ID Printer’s magnetic encoder can be tested using
Microsoft Notepad. After starting up Notepad, go into Page Setup from the File
menu and set the printer’s margins to 0.1” and clear the Header and Footer
values. In the data area of Notepad enter data similar to the following:
Test Card Magnetic Encoding
~1=TEST CARD FOR MAG ENCODING
~2=1234567890
~3=0987654321
Select Print from the File menu. “Test Card Magnetic Encoding” should be
printed on the card. Encoded on tracks 1, 2 and 3 should be the data after
“~1=”, “~2=” and “~3=” respectively.
NOTE: Do not enter data on the first line in Notepad, it will be outside the print
margin. Hit Enter at least once. It is also a good idea to tab over once to ensure
the print data is within the margin.
NOTE: The magnetic encoder needs data to be in all capital letters. If you
enter lower case text the driver will convert it to uppercase.
The two magnetic data formats supported by Zebra P640 Photo ID Printers are
ISO and AAMVA. The format of the data encoded is dependent on the selection
made on the Magnetic Encoding Property Sheet under Printing Preferences. The
following table defines the data lengths and format:
Track Density Length
1210 BPI76717971
275 BPI37523752
3210 BPI104527973
Total
Notes:
1. The data length does not include the start sentinel, end sentinel or
2. The host software must limit the amount of data for each track as
3. The character codes must be limited as described in the following
Table 1Table 2Table 3
0Xh 1Xh 2Xh 3Xh 0Xh1Xh 2Xh3Xh
X0h SP 0 @1 P 00h 0 X0h SP 0 @6 P
X1h !1 1 A Q 01h 1 X1h !6 1 A Q
X2h "1 2 B R 02h 2 X2h "6 2 B R
X3h #3 3 C S 03h 3 X3h #6 3 C S
X4h $ 4 D T 04h 4 X4h $ 4 D T
X5h %4 5 E U 05h 5 X5h %6 5 E U
X6h &1 6 F V 06h 6 X6h &6 6 F V
X7h '1 7 G W 07h 7 X7h '6 7 G W
X8h ( 8 H X 08h 8 X8h ( 8 H X
X9h ) 9 I Y 09h 9 X9h ) 9 I Y
XAh *1 :1 J Z 0Ah :1 XAh *6 :6 J Z
XBh +1 ;1 K [2 0Bh ;5 XBh +6 ;6 K [6
XCh ,1 <1 L \2 0Ch <1 XCh ,6 <6 L \6
XDh - =1 M ]2 0Dh =5 XDh - =6 M ]6
XEh . >1 N ^4 0Eh >1 XEh . >
XFh / ?4 O _1
0Fh ?5 XFh / ?4 O _6
4,6
N ^
4,6
Notes:
1. These characters are available for hardware control purposes only
and cannot contain information characters.
2. These characters are reserved for additional national characters
when required. They are not to be used internationally.
3. This character is reserved for optional additional graphic symbol.
4. These characters shall have the following meaning for this
application:
% - Start sentinel
? - End sentinel
^ - field separator
Warning! The start sentinel and end sentinel characters should
not be sent to the Windows printer driver as track data. The printer
will automatically program the start and end sentinel characters on
the magnetic stripe.
5. These characters shall have the following meaning for this
application:
; - Start sentinel
? - End sentinel
= - field separator
Warning! The start sentinel and end sentinel characters
should not be sent to the Windows printer driver as track data.
The printer will automatically program the start and end sentinel
characters on the magnetic stripe.
6. All values may exist as data on the track. Additionally, the three
control characters (%, ?, ^) can also exist as data in a data field and
should not be misinterpreted as start sentinel, end sentinel and field
separator.