DEVMODE and Printer orientation

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

DEVMODE and Printer orientation

Louis Sumberg-2
I've been going round and round in circles for the past few days trying to
get this to work right.  The intent is for the application to first prompt
the user to choose a printer OR suppress the prompt and use the default
printer.  The application may then change the printer orientation based on
its internal criteria.  This is what I have so far, in a workspace.  It
seems to work, though obviously still needs to be wrapped in a method,
presumably in PrinterCanvas.

If anyone sees any glaring errors, please let me know.  BTW, I tried doing
this in VB a couple of years ago and wasn't able to do it (at least not
without resorting to a third party dll).  In addition, Dolphin has been very
forgiving about all my experimentation -- I was not knocked out of Dolphin
even once, which would certainly have been the case numerous times with VB,
it being notoriously intolerant of things being "off" when going into the
Windows API.

-- Louis

"Variables:
pd -- a PrintDialog.
hDC -- a printer device context.
pc -- a PrinterCanvas.
dm -- a DEVMODE structure.
Note: Add pool Win32Constants to workspace before evaluating lines below."
"Create a PrintDialog instance."
pd := PrintDialog new.
"Set PRINTDLG flags to show Print Setup dialog (instead of Print) and to
return a Device Context in winStruct hDC."
pd winStruct flags: (PD_PRINTSETUP | PD_RETURNDC).
"To bypass user input and use the default printer, evaluate the next line."
pd winStruct flags: (PD_RETURNDEFAULT | PD_RETURNDC).
"Create a printer device context through Win PrintDlg, which also allocates
memory for the DEVMODE structure, initializes its members to indicate user
or default input, and returns a handle (in pd winStruct) that identifies
it."
hDC := pd showModal.
"Create references to the returned DEVMODE structure.  It seems necessary to
'lock' the returned handle for the rest to work."
hDevMode := pd winStruct hDevMode.
externalAddressDM := KernelLibrary default globalLock: hDevMode.
dm := DEVMODE fromAddress: externalAddressDM.
"Cleanup -- not sure this is necessary."
KernelLibrary default globalUnlock: hDevMode.
"Display current printer name and orientation (1 = Portrait, 2 =
Landscape)."
devname := dm dmDeviceName asString trimNulls.
dm dmOrientation.
"Create a PrinterCanvas with device context hDC and print a page."
pc := PrinterCanvas withOwnedDC: hDC.
pc startDoc; startPage; text: 'Test 1' at: 50@50; endPage; endDoc.
"Toggle printer orientation."
dm dmOrientation: (dm dmOrientation = 1 ifTrue: [2] ifFalse: [1]).
"Create a printer device context and print a page with new orientation."
hDC := GDILibrary default createDC: nil lpszDevice: devname lpszOutput: nil
lpdvminit: dm.
pc := PrinterCanvas withOwnedDC: hDC.
pc startDoc; startPage; text: 'Test 2' at: 50@50; endPage; endDoc.
"To prompt user with dialog showing changed settings, use this."
pd winStruct flags: (PD_PRINTSETUP | PD_RETURNDC).
(hDC := pd showModal) notNil ifTrue: [
 pc := PrinterCanvas withOwnedDC: hDC.
 pc startDoc; startPage; text: 'Test 3' at: 50@50; endPage; endDoc]

DEVMODE is defined as:

Win32Structure subclass: #DEVMODE
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 classInstanceVariableNames: ''

DEVMODE class>>defineFields is defined as:

defineFields
 "Define the fields of the Win32 DEVMODE structure.
  DEVMODE compileDefinition

 typedef struct _devicemode

  BCHAR  dmDeviceName[CCHDEVICENAME];
  WORD   dmSpecVersion;
  WORD   dmDriverVersion;
  WORD   dmSize;
  WORD   dmDriverExtra;
  DWORD  dmFields;
  union {
   struct {
    short dmOrientation;
    short dmPaperSize;
    short dmPaperLength;
    short dmPaperWidth;
   };
   POINTL dmPosition;
  };
  short  dmScale;
  short  dmCopies;
  short  dmDefaultSource;
  short  dmPrintQuality;
  short  dmColor;
  short  dmDuplex;
  short  dmYResolution;
  short  dmTTOption;
  short  dmCollate;
  BCHAR  dmFormName[CCHFORMNAME];
  WORD  dmLogPixels;
  DWORD  dmBitsPerPel;
  DWORD  dmPelsWidth;
  DWORD  dmPelsHeight;
  union {
   DWORD  dmDisplayFlags;
   DWORD  dmNup;
  }
  DWORD  dmDisplayFrequency;
  #if(WINVER >= 0x0400)
   DWORD  dmICMMethod;
   DWORD  dmICMIntent;
   DWORD  dmMediaType;
   DWORD  dmDitherType;
   DWORD  dmReserved1;
   DWORD  dmReserved2;
  #if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
   DWORD  dmPanningWidth;
   DWORD  dmPanningHeight;
  #endif
  #endif /* WINVER >= 0x0400 */
 } DEVMODE;
"
 self
  defineField: #dmDeviceName type: (ArrayField type: ByteArray length: 32)
offset: 0;
  defineField: #dmSpecVersion type: SWORDField new offset: 32;
  defineField: #dmDriverVersion type: SWORDField new offset: 34;
  defineField: #dmSize type: SWORDField new offset: 36;
  defineField: #dmDriverExtra type: SWORDField new offset: 38;
  defineField: #dmFields type: SDWORDField new offset: 40;
  defineField: #dmOrientation type: SWORDField new offset: 44;
  defineField: #dmPaperSize type: SWORDField new offset: 46;
  defineField: #dmPaperLength type: SWORDField new offset: 48;
  defineField: #dmPaperWidth type: SWORDField new offset: 50;
  defineField: #dmScale type: SWORDField new offset: 52;
  defineField: #dmCopies type: SWORDField new offset: 54;
  defineField: #dmDefaultSource type: SWORDField new offset: 56;
  defineField: #dmPrintQuality type: SWORDField new offset: 58;
  defineField: #dmColor type: SWORDField new offset: 60;
  defineField: #dmDuplex type: SWORDField new offset: 62;
  defineField: #dmYResolution type: SWORDField new offset: 64;
  defineField: #dmTTOption type: SWORDField new offset: 66;
  defineField: #dmCollate type: SWORDField new offset: 68;
  defineField: #dmFormName type: (ArrayField type: ByteArray length: 32)
offset: 70;
  defineField: #dmLogPixels type: SWORDField new offset: 102;
  defineField: #dmBitsPerPel type: SDWORDField new offset: 104;
  defineField: #dmPelsWidth type: SDWORDField new offset: 108;
  defineField: #dmPelsHeight type: SDWORDField new offset: 112;
  defineField: #dmDisplayFlags type: SDWORDField new offset: 116;
  defineField: #dmDisplayFrequency type: SDWORDField new offset: 120;
  defineField: #dmICMMethod type: SDWORDField new offset: 124;
  defineField: #dmICMIntent type: SDWORDField new offset: 128;
  defineField: #dmMediaType type: SDWORDField new offset: 132;
  defineField: #dmDitherType type: SDWORDField new offset: 136;
  defineField: #dmReserved1 type: SDWORDField new offset: 140;
  defineField: #dmReserved2 type: SDWORDField new offset: 144.
 self byteSize: 148

To use DEVMODE, you'll need to evaluate "DEVMODE compileDefinition" which
generates the accessors.  (All the SDWORDFields should really be
DWORDFields -- DEVMODE was generated from a VB type library -- but I don't
think that's a problem.)