Paradox Community
Search:

 Welcome |  What is Paradox |  Paradox Folk |  Paradox Solutions |
 Interactive Paradox |  Paradox Programming |  Internet/Intranet Development |
 Support Options |  Classified Ads |  Wish List |  Submissions 


Paradox Programming Articles  |  Beyond Help Articles  |  Tips & Tricks Articles  


Win32 API and Printers
Changing Printer Attributes
© 2002 Rick Kelly
www.crooit.com

Preface

Libraries and forms (Paradox 9) presented are available as a download here. Paradox 8 is not supported although Paradox 7-32 surprisingly works. After downloading into the folder of your choice, make that folder :WORK: and run the included form for a demonstration. You'll need to run the form before opening it in design mode as it references table :PRIV:__PJobs that is created in the form's INIT event. (If running Paradox 10, or if the table doesn't get created properly, you should first run the BldSpool.ssl script prior to running the form.)


Introduction

Previous articles in this series:
  1. Retrieve Default Windows Printer and interrogate printer properties
  2. Setting the Default Windows Printer
  3. Retrieve Print Jobs
  4. Control Printers and Print Jobs
  5. Print Directly to a Printer
In this article we’ll cover how to change or update a Windows printer, building upon and reusing the methods presented earlier.

As printers have differing capabilities, each driver communicates which portion of the Windows common feature set it supports through the use of bit level flags. These bit level flags and printer settings are stored in a structure called the DEVMODE. Each printer driver typically references a large amount of device-independent and device-dependent information in DEVMODE that we don’t know or care about. When we make modifications to fields in the device-independent part of DEVMODE, it may also effect changes in the device-dependent portion and we will need to take additional steps to ensure we have a consistent DEVMODE structure before the printer update.

In the first article of this series, we covered retrieval of printer attributes which were returned in a Paradox Record Type structure of custom type W32PrinterInfo. We are adding an additional field of LongInt Type called FieldsCanChange to W32PrinterInfo which contains bit level flags for which DEVMODE fields the print driver supports changes. These bit level flags are mapped into the following custom Paradox Record Type by the W32CanSetPrinterFields method:
Type
;
; Printer attributes that can be changed - driver specific
;
  W32SetPrinterFields =
    record
      Orientation        Logical
      PaperSize          Logical
      PaperLength        Logical
      PaperWidth         Logical
      Scale              Logical
      Copies             Logical
      DefaultPaperSource Logical
      PrintQuality       Logical
      Color              Logical
      Duplex             Logical
      YResolution        Logical
      TTOption           Logical
      Collate            Logical
      FormName           Logical
    endRecord
endType

Const
;
; Printer attributes that can be changed
;
  cnOrientation        = 1
  cnPaperSize          = 2
  cnPaperLength        = 4
  cnPaperWidth         = 8
  cnScale              = 16
  cnCopies             = 256
  cnDefaultPaperSource = 512
  cnPrintQuality       = 1024
  cnColor              = 2048
  cnDuplex             = 4096
  cnYResolution        = 8192
  cnTTOption           = 16384
  cnCollate            = 32768
  cnFormName           = 65536
endConst

method W32CanSetPrinterFields(liFields LongInt) W32SetPrinterFields
var
  spf  W32SetPrinterFields
endVar
;
; Return Available Fields for printer
;
  switch
    case liFields.bitAnd(cnOrientation) = cnOrientation :
      spf.Orientation = True
    otherwise :
      spf.Orientation = False
  endSwitch
  switch
    case liFields.bitAnd(cnPaperSize) = cnPaperSize :
      spf.PaperSize = True
    otherwise :
      spf.PaperSize = False
  endSwitch
  switch
    case liFields.bitAnd(cnPaperLength) = cnPaperLength :
      spf.PaperLength = True
    otherwise :
      spf.PaperLength = False
  endSwitch
  switch
    case liFields.bitAnd(cnPaperWidth) = cnPaperWidth :
      spf.PaperWidth = True
    otherwise :
      spf.PaperWidth = False
  endSwitch
  switch
    case liFields.bitAnd(cnScale) = cnScale :
      spf.Scale = True
    otherwise :
      spf.Scale = False
  endSwitch
  switch
    case liFields.bitAnd(cnCopies) = cnCopies :
      spf.Copies = True
    otherwise :
      spf.Copies = False
  endSwitch
  switch
    case liFields.bitAnd(cnOrientation) = cnOrientation :
      spf.Orientation = True
    otherwise :
      spf.Orientation = False
  endSwitch
  switch
    case liFields.bitAnd(cnDefaultPaperSource) = cnDefaultPaperSource :
      spf.DefaultPaperSource = True
    otherwise :
      spf.DefaultPaperSource = False
  endSwitch
  switch
    case liFields.bitAnd(cnPrintQuality) = cnPrintQuality :
      spf.PrintQuality = True
    otherwise :
      spf.PrintQuality = False
  endSwitch
  switch
    case liFields.bitAnd(cnColor) = cnColor :
      spf.Color = True
    otherwise :
      spf.Color = False
  endSwitch
  switch
    case liFields.bitAnd(cnDuplex) = cnDuplex :
      spf.Duplex = True
    otherwise :
      spf.Duplex = False
  endSwitch
  switch
    case liFields.bitAnd(cnYResolution) = cnYResolution :
      spf.YResolution = True
    otherwise :
      spf.YResolution = False
  endSwitch
  switch
    case liFields.bitAnd(cnTTOption) = cnTTOption :
      spf.TTOption = True
    otherwise :
      spf.TTOption = False
  endSwitch
  switch
    case liFields.bitAnd(cnCollate) = cnCollate :
      spf.Collate = True
    otherwise :
      spf.Collate = False
  endSwitch
  switch
    case liFields.bitAnd(cnFormName) = cnFormName :
      spf.FormName = True
    otherwise :
      spf.FormName = False
  endSwitch
  return spf
endMethod

Referenced Win32 APIs

Other referenced Win32 API's have been covered in earlier articles. Newly introduced methods are:
DocumentProperties(
  hWnd cLong,
  hPrn cLong,
  pDeviceName cPtr,
  pDevModeOutput cLong,
  pDevModeInput cLong,
  fMode cLong) cLong [stdcall "DocumentPropertiesA"]
hWnd - Window Handle - always 0 for our use
hPrn - Handle to the printer
pDeviceName - Printer Name
pDevModeOutput - Pointer to update/merged/retrieved DEVMODE
pDevModeInput - Pointer to input DEVMODE
fMode - Flags indicating operation to perform


Updating Printer

We use the following Paradox DynArray of AnyType to hold what fields to change and their respective new values.
Type
  W32SetPrinter = DynArray[] AnyType
;
; Index Name         Type
; ---------------------------
;
; Comment            String
; Location           String
; SeparatorPage      String
; Orientation        SmallInt
; PaperSize          SmallInt
; PaperLength        SmallInt
; PaperWidth         SmallInt
; Scale              SmallInt
; Copies             SmallInt
; DefaultPaperSource SmallInt
; PrintQuality       SmallInt
; Color              SmallInt
; Duplex             SmallInt
; YResolution        SmallInt
; TTOption           SmallInt
; Collate            SmallInt
; FormName           String
; DefaultPriority    SmallInt
; Priority           SmallInt
; StartTime          LongInt
; UntilTime          LongInt
;
endType
Refer to the first article of this series for an explanation of each field and valid values.

Constants we will be referring to:
Const
;
; Administrative Access
;
  cnPrinterAccessAdminister = 4
  cnPrinterAccessUse        = 8
  cnPrinterStandardRights   = 983040 ;0x000F0000
;
; Printer attributes that can be changed
;
  cnOrientation             = 1
  cnPaperSize               = 2
  cnPaperLength             = 4
  cnPaperWidth              = 8
  cnScale                   = 16
  cnCopies                  = 256
  cnDefaultPaperSource      = 512
  cnPrintQuality            = 1024
  cnColor                   = 2048
  cnDuplex                  = 4096
  cnYResolution             = 8192
  cnTTOption                = 16384
  cnCollate                 = 32768
  cnFormName                = 65536
;
; DocumentProperties Options
;
  cnDMOutBuffer             = 2
  cnDMInBuffer              = 8
endConst
Common procedures referenced are:
Proc cmGetPrinterInfo(var stPrinter String,
                      var liPrinterHandle LongInt,
                      var liMemoryStructure LongInt) Logical
var
  liReturn     LongInt
  liSizeNeeded LongInt
  liSizeUsed   LongInt
  liDevMode    LongInt
  loReturn     Logical
endVar
;
; Get admin access handle to the printer
;
  liPrinterHandle = 0
  liMemoryStructure = 0
  liDevMode = 0
  loReturn = False
  switch
    case cmOpenPrinterAdmin(stPrinter,liPrinterHandle) = False :
    otherwise :
;
; First call is to get buffer size needed
;
      liSizeNeeded = 0
      liSizeUsed = 0
      liReturn = GetPrinter(
        liPrinterHandle,
        2,
        0,
        0,
        liSizeNeeded)
;
; Allocate memory for Printer Info Structure Level 2
;
      liMemoryStructure = GlobalAlloc(fromHex("0x40"),liSizeNeeded)
;
; Get Printer Info Structure
;
      liReturn = GetPrinter(
        liPrinterHandle,
        2,
        liMemoryStructure,
        liSizeNeeded,
        liSizeUsed)
;
; Check if GetPrinter returned a DEVMODE structure pointer
;
      switch
        case liReturn = 1 :
          MoveFromMemory(liDevMode,liMemoryStructure + 28,4)
          switch
;
; DEVMODE structure missing - attempt to
; get one
;
            case liDevMode = 0 :
              loReturn = cmGetDeviceMode(
                stPrinter,
                liPrinterHandle,
                liDevMode)
            otherwise :
              loReturn = True
          endSwitch
      endSwitch
      switch
        case loReturn = False :
          liReturn = GlobalFree(liMemoryStructure)
          liMemoryStructure = 0
          liReturn = ClosePrinter(liPrinterHandle)
          liPrinterHandle = 0
          switch
            case liDevMode <> 0 :
              liReturn = GlobalFree(liDevMode)
          endSwitch
      endSwitch
  endSwitch
  return loReturn
endProc
Proc cmGetDeviceMode(var stPrinter String,
                     var liPrinterHandle LongInt,
                     var liDevMode LongInt) Logical
var
  liSizeNeeded LongInt
  liReturn     LongInt
  loReturn     Logical
endVar
  liDevMode = 0
  loReturn = False
  liSizeNeeded = DocumentProperties(
    0,
    liPrinterHandle,
    stPrinter,
    0,
    0,
    0)
  switch
    case liSizeNeeded > 0 :
;
; Allocate memory for DEVMODE structure
;
      liDevMode = GlobalAlloc(fromHex("0x40"),liSizeNeeded)
;
; Retrieve DEVMODE structure from driver
;
      liReturn = DocumentProperties(
        0,
        liPrinterHandle,
        stPrinter,
        liDevMode,
        0,
        cnDMOutBuffer)
      loReturn = (liReturn = 1)
  endSwitch
  return loReturn
endProc
Proc cmOpenPrinterAdmin(var stPrinter String,
                        var liPrinterHandle LongInt) Logical
;
; Open printer for administrative access
;
var
  liReturn           LongInt
  liAny              LongInt
  liDefaultStructure LongInt
endVar
;
; Build a printer defaults structure
;
; liDataType  LongInt (address pointer)
; liDeviceMode  LongInt (address pointer)
; liDesiredAccess  LongInt
;
  liDefaultStructure = GlobalAlloc(fromHex("0x40"),12)
  liAny = 0
  MoveToMemory(liDefaultStructure,liAny,4)
  MoveToMemory(liDefaultStructure + 4,liAny,4)
  liAny = cnPrinterAccessAdminister
        + cnPrinterAccessUse
        + cnPrinterStandardRights
  MoveToMemory(liDefaultStructure + 8,liAny,4)
;
; Get a handle to the printer
;
  liPrinterHandle = 0
  liReturn = OpenPrinter(stPrinter,liPrinterHandle,liDefaultStructure)
  GlobalFree(liDefaultStructure)
  return liPrinterHandle <> 0
endProc
Proc cmCopyStringToMemory(stAny String) LongInt
var
  liPointer LongInt
  liSize    LongInt
endVar
;
; If string is not blank, allocate memory and copy it
;
  liPointer = 0
  switch
    case stAny.size() > 0 :
      liSize = stAny.size() + 1
      liPointer = GlobalAlloc(fromHex("0x40"),liSize)
      MoveToMemory(liPointer,stAny,liSize)
  endSwitch
  return liPointer
endProc
Our basic outline to updating printer attributes is:
  1. Open printer in administrative mode
  2. Retrieve a Printer Info Level 2 structure
  3. Make sure we have a valid DEVMODE structure
  4. Change the Printer Info Level 2 and DEVMODE structures
  5. Merge device-dependent and independent DEVMODE portions
  6. Save our changes
Now we are ready to update a printer.
method SetPrinterInfo(stPrinter String,
                      var dyPrinterAttributes W32SetPrinter) Logical
var
  loReturn          Logical
  liPrinterHandle   LongInt
  liReturn          LongInt
  liMemoryStructure LongInt
  liDevMode         LongInt
  liAny             LongInt
  liFields          LongInt
  arMemory          Array[] LongInt
  siAny             SmallInt
  stAny             String
  liSupportedFields LongInt
endVar
  liFields = 0
  loReturn = False
  arMemory.empty()
;
; Open printer
;
  switch
    case cmGetPrinterInfo(
           stPrinter,
           liPrinterHandle,
           liMemoryStructure) = False :
    otherwise :
;
; Update Printer Info Structure Level 2 and/or associated DEVMODE
;
      liAny = 0
      liSupportedFields = 0
;
; Do not attempt to set security descriptor
;
      MoveToMemory(liMemoryStructure + 48,liAny,4)
;
; Get pointer to DevMode structure
;
      MoveFromMemory(liDevMode,liMemoryStructure + 28,4)
;
; Get flags for driver field change support
;
      MoveFromMemory(liSupportedFields,liDevMode + 40,4)
;
; Update Comment
;
      switch
        case dyPrinterAttributes.contains("Comment") = False :
        otherwise :
          liAny = cmCopyStringToMemory(
            dyPrinterAttributes["Comment"])
          MoveToMemory(liMemoryStructure + 20,liAny,4)
          arMemory.grow(1)
          arMemory[arMemory.size()] = liAny
      endSwitch
;
; Update Location
;
      switch
        case dyPrinterAttributes.contains("Location") = False :
        otherwise :
          liAny = cmCopyStringToMemory(
            dyPrinterAttributes["Location"])
          MoveToMemory(liMemoryStructure + 24,liAny,4)
          arMemory.grow(1)
          arMemory[arMemory.size()] = liAny
      endSwitch
;
; Update Separator Page
;
      switch
        case dyPrinterAttributes.contains("SeparatorPage") = False :
        otherwise :
          liAny = cmCopyStringToMemory(
            dyPrinterAttributes["SeparatorPage"])
          MoveToMemory(liMemoryStructure + 32,liAny,4)
          arMemory.grow(1)
          arMemory[arMemory.size()] = liAny
      endSwitch
;
; Update Default Priority
;
      switch
        case dyPrinterAttributes.contains("DefaultPriority") = False :
        otherwise :
          try
            liAny = dyPrinterAttributes["DefaultPriority"]
            MoveToMemory(liMemoryStructure + 60,liAny,4)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Default Priority=" +
              strval(dyPrinterAttributes["DefaultPriority"]))
          endTry
      endSwitch
;
; Update Priority
;
      switch
        case dyPrinterAttributes.contains("Priority") = False :
        otherwise :
          try
            liAny = dyPrinterAttributes["Priority"]
            MoveToMemory(liMemoryStructure + 56,liAny,4)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Priority=" +
              strval(dyPrinterAttributes["Priority"]))
          endTry
      endSwitch
;
; Update Start Time
;
      switch
        case dyPrinterAttributes.contains("StartTime") = False :
        otherwise :
          try
            liAny = dyPrinterAttributes["StartTime"]
            MoveToMemory(liMemoryStructure + 64,liAny,4)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Start Time=" +
              strval(dyPrinterAttributes["StartTime"]))
          endTry
      endSwitch
;
; Update Until Time
;
      switch
        case dyPrinterAttributes.contains("UntilTime") = False :
        otherwise :
          try
            liAny = dyPrinterAttributes["UntilTime"]
            MoveToMemory(liMemoryStructure + 68,liAny,4)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Until Time=" +
              strval(dyPrinterAttributes["UntilTime"]))
          endTry
      endSwitch
;
; Update orientation
;
      switch
        case dyPrinterAttributes.contains("Orientation") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnOrientation) = cnOrientation :
          try
            siAny = dyPrinterAttributes["Orientation"]
            liFields = liFields
                     + cnOrientation
            MoveToMemory(liDevMode + 44,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Orientation=" +
              strval(dyPrinterAttributes["Orientation"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Orientation changes")
      endSwitch
;
; Update Paper Size
;
      switch
        case dyPrinterAttributes.contains("PaperSize") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnPaperSize) = cnPaperSize :
          try
            siAny = dyPrinterAttributes["PaperSize"]
            liFields = liFields
                     + cnPaperSize
            MoveToMemory(liDevMode + 46,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Paper Size=" +
              strval(dyPrinterAttributes["PaperSize"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Paper Size changes")
      endSwitch
;
; Update Paper Length
;
      switch
        case dyPrinterAttributes.contains("PaperLength") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnPaperLength) = cnPaperLength :
          try
            siAny = dyPrinterAttributes["PaperLength"]
            liFields = liFields
                     + cnPaperLength
            MoveToMemory(liDevMode + 48,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Paper Length=" +
              strval(dyPrinterAttributes["PaperLength"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Paper Length changes")
      endSwitch
;
; Update Paper Width
;
      switch
        case dyPrinterAttributes.contains("PaperWidth") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnPaperWidth) = cnPaperWidth :
          try
            siAny = dyPrinterAttributes["PaperWidth"]
            liFields = liFields
                     + cnPaperWidth
            MoveToMemory(liDevMode + 50,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Paper Width=" +
              strval(dyPrinterAttributes["PaperWidth"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Paper Width changes")
      endSwitch
;
; Update Scale
;
      switch
        case dyPrinterAttributes.contains("Scale") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnScale) = cnScale :
          try
            siAny = dyPrinterAttributes["Scale"]
            liFields = liFields
                     + cnScale
            MoveToMemory(liDevMode + 52,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Scale=" +
              strval(dyPrinterAttributes["Scale"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Scale changes")
      endSwitch
;
; Update copies
;
      switch
        case dyPrinterAttributes.contains("Copies") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnCopies) = cnCopies :
          try
            siAny = dyPrinterAttributes["Copies"]
            liFields = liFields
                     + cnCopies
            MoveToMemory(liDevMode + 54,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Copies=" +
              strval(dyPrinterAttributes["Copies"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Copies changes")
      endSwitch
;
; Update Default Paper Source
;
      switch
        case dyPrinterAttributes.contains("DefaultPaperSource") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnDefaultPaperSource) = cnDefaultPaperSource :
          try
            siAny = dyPrinterAttributes["DefaultPaperSource"]
            liFields = liFields
                     + cnDefaultPaperSource
            MoveToMemory(liDevMode + 56,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Default Paper Source=" +
              strval(dyPrinterAttributes["DefaultPaperSource"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Default Paper Source changes")
      endSwitch
;
; Update Print Quality
;
      switch
        case dyPrinterAttributes.contains("PrintQuality") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnPrintQuality) = cnPrintQuality :
          try
            siAny = dyPrinterAttributes["PrintQuality"]
            liFields = liFields
                     + cnPrintQuality
            MoveToMemory(liDevMode + 58,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Print Quality=" +
              strval(dyPrinterAttributes["PrintQuality"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Print Quality changes")
      endSwitch
;
; Update Color
;
      switch
        case dyPrinterAttributes.contains("Color") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnColor) = cnColor :
          try
            siAny = dyPrinterAttributes["Color"]
            liFields = liFields
              + cnColor
            MoveToMemory(liDevMode + 60,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Color=" +
              strval(dyPrinterAttributes["Color"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Color changes")
      endSwitch
;
; Update Duplex
;
      switch
        case dyPrinterAttributes.contains("Duplex") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnDuplex) = cnDuplex :
          try
            siAny = dyPrinterAttributes["Duplex"]
            liFields = liFields
                     + cnDuplex
            MoveToMemory(liDevMode + 62,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Duplex=" +
              strval(dyPrinterAttributes["Duplex"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Duplex changes")
      endSwitch
;
; Update YResolution
;
      switch
        case dyPrinterAttributes.contains("YResolution") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnYResolution) = cnYResolution :
          try
            siAny = dyPrinterAttributes["YResolution"]
            liFields = liFields
                     + cnYResolution
            MoveToMemory(liDevMode + 64,siAny,2)
         onFail
           errorClear()
           msgStop(stPrinter,"Invalid YResolution=" +
             strval(dyPrinterAttributes["YResolution"]))
         endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support YResolution changes")
      endSwitch
;
; Update TTOption
;
      switch
        case dyPrinterAttributes.contains("TTOption") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnTTOption) = cnTTOption :
          try
            siAny = dyPrinterAttributes["TTOption"]
            liFields = liFields
                     + cnTTOption
            MoveToMemory(liDevMode + 66,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid TTOption=" +
              strval(dyPrinterAttributes["TTOption"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support TTOption changes")
      endSwitch
;
; Update Collate
;
      switch
        case dyPrinterAttributes.contains("Collate") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnCollate) = cnCollate :
          try
            siAny = dyPrinterAttributes["Collate"]
            liFields = liFields
                     + cnCollate
            MoveToMemory(liDevMode + 68,siAny,2)
          onFail
            errorClear()
            msgStop(stPrinter,"Invalid Collate=" +
              strval(dyPrinterAttributes["Collate"]))
          endTry
        otherwise :
          msgStop(stPrinter,"Driver does not support Collate changes")
      endSwitch
;
; Update Form Name
;
      switch
        case dyPrinterAttributes.contains("FormName") = False :
;
; Does driver support this change?
;
        case liSupportedFields.bitAnd(cnFormName) = cnFormName :
;
; Form Name size limit is 32 bytes
;
          switch
            case dyPrinterAttributes["FormName"].size() > 31 :
              stAny = dyPrinterAttributes["FormName"].substr(1,31)
            otherwise :
              stAny = dyPrinterAttributes["FormName"]
          endSwitch
          liAny = stAny.size() + 1
          MoveToMemory(liDevMode + 70,stAny,liAny)
          liFields = liFields
                   + cnFormName
        otherwise :
          msgStop(stPrinter,"Driver does not support Form Name changes")
      endSwitch
;
; Ensure that driver dependent portion of DEVMODE is updated
;
      liReturn = DocumentProperties(
        0,
        liPrinterHandle,
        stPrinter,
        liDevMode,
        liDevMode,
        cnDMInBuffer + cnDMOutBuffer)

      switch
        case liReturn = 1 :
;
; Update printer attributes - if liReturn <> 1
; the driver doesn't support or is unable to
; make the changes
;
          liReturn = SetPrinter(
            liPrinterHandle,
            2,
            liMemoryStructure,
            0)
          switch
            case liReturn = 1 :
;
; Send out alert to all running applications
; that a system value has been updated
;
              liReturn = SendDevModeMessage(
                cnBroadcast,
                cnSettingChange,
                0,
                stPrinter,
                cnTimeOutNormal,
                1000,
                0)
              loReturn = True
          endSwitch
      endSwitch
;
; Release Memory
;
      liReturn = GlobalFree(liMemoryStructure)
      liReturn = GlobalFree(liDevMode)
;
; Release printer handle
;
      liReturn = ClosePrinter(liPrinterHandle)
  endSwitch
;
; Release any miscellaneous memory
;
  switch
    case arMemory.size() > 0 :
      for siAny from 1 to arMemory.size()
        liAny = arMemory[siAny]
        liReturn = GlobalFree(liAny)
      endFor
  endSwitch
  return loReturn
endMethod

Conclusion

We now have methods that support updating Windows printer attributes. (Hint: Look at the underlying OPAL in the provided libraries and the form and see what else you can discover and learn about<g>)


Next: I tink T-T-T-T-T-T-T-T-That's all folks!


Discussion of this article


 Feedback |  Paradox Day |  Who Uses Paradox |  I Use Paradox |  Downloads 


 The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation.
 Paradox is a registered trademark of Corel Corporation.


 Modified: 15 May 2003
 Terms of Use / Legal Disclaimer


 Copyright © 2001- 2003 Paradox Community. All rights reserved. 
 Company and product names are trademarks or registered trademarks of their respective companies. 
 Authors hold the copyrights to their own works. Please contact the author of any article for details.