I received a question about how to use DEVMODE. Below is some sample code that retrieves the screen’s current width/height screen resolution and rotates it for a few seconds if supported by your machine (mostly on Tablet PCs)

 

The user’s question continues:

 

The printer properties you can control start with DM_ORIENTATION and go through DM_DITHERTYPE.  Each constant represents the bit in DM_FIELDS for that property, but there's a gap in the sequence between DM_SCALE and DM_COPIES.  Why aren't the bits for 32, 64 and 128 used?

 

 

There is no rule saying that all values in a bitfield must be used. An API can define bit 1 to mean A, bit 4 to mean B, but bits 2 and 3 do not have to be defined.  Also, APIs evolve as the OS version changes to support newer hardware/software. However, the #define’s below show that 32, 64 and 128 are used for DM_POSITION, DM_NUP, DM_DISPLAYORIENTATION

 

 

DEVMODE is defined in C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\wingdi.h

It’s a little bit complex with some #ifdefs and macros. WINVER is 0x0501 for Windows XP

 

typedef struct _devicemodeA {

    BYTE   dmDeviceName[CCHDEVICENAME];

    WORD dmSpecVersion;

    WORD dmDriverVersion;

    WORD dmSize;

    WORD dmDriverExtra;

    DWORD dmFields;

    union {

      /* printer only fields */

      struct {

        short dmOrientation;

        short dmPaperSize;

        short dmPaperLength;

        short dmPaperWidth;

        short dmScale;

        short dmCopies;

        short dmDefaultSource;

        short dmPrintQuality;

      };

      /* display only fields */

      struct {

        POINTL dmPosition;

        DWORD  dmDisplayOrientation;

        DWORD  dmDisplayFixedOutput;

      };

    };

    short dmColor;

    short dmDuplex;

    short dmYResolution;

    short dmTTOption;

    short dmCollate;

    BYTE   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 */

} DEVMODEA, *PDEVMODEA, *NPDEVMODEA, *LPDEVMODEA;

 

 

From that same file:

 

/* field selection bits */

#define DM_ORIENTATION          0x00000001L

#define DM_PAPERSIZE            0x00000002L

#define DM_PAPERLENGTH          0x00000004L

#define DM_PAPERWIDTH           0x00000008L

#define DM_SCALE                0x00000010L

#if(WINVER >= 0x0500)

#define DM_POSITION             0x00000020L

#define DM_NUP                  0x00000040L

#endif /* WINVER >= 0x0500 */

#if(WINVER >= 0x0501)

#define DM_DISPLAYORIENTATION   0x00000080L

#endif /* WINVER >= 0x0501 */

#define DM_COPIES               0x00000100L

#define DM_DEFAULTSOURCE        0x00000200L

#define DM_PRINTQUALITY         0x00000400L

#define DM_COLOR                0x00000800L

#define DM_DUPLEX               0x00001000L

#define DM_YRESOLUTION          0x00002000L

#define DM_TTOPTION             0x00004000L

#define DM_COLLATE              0x00008000L

#define DM_FORMNAME             0x00010000L

#define DM_LOGPIXELS            0x00020000L

#define DM_BITSPERPEL           0x00040000L

#define DM_PELSWIDTH            0x00080000L

#define DM_PELSHEIGHT           0x00100000L

#define DM_DISPLAYFLAGS         0x00200000L

#define DM_DISPLAYFREQUENCY     0x00400000L

#if(WINVER >= 0x0400)

#define DM_ICMMETHOD            0x00800000L

#define DM_ICMINTENT            0x01000000L

#define DM_MEDIATYPE            0x02000000L

#define DM_DITHERTYPE           0x04000000L

#define DM_PANNINGWIDTH         0x08000000L

#define DM_PANNINGHEIGHT        0x10000000L

#endif /* WINVER >= 0x0400 */

#if(WINVER >= 0x0501)

#define DM_DISPLAYFIXEDOUTPUT   0x20000000L

#endif /* WINVER >= 0x0501 */

 

 

 

Here’s the VFP code to change the screen orientation. Check out the uses of BINTOC and CTOBIN  (see also Tools->Task Pane->Solution Samples->New in VFP9->BINTOC Binary Conversion and Floating Point calculations: comparing with zero). The string offsets are offsets into the DEVMODE structure. They are easy to figure out in a debugger, especially with the macros, unions and nested structures. Just put &(*(DEVMODE *)0).dmDisplayOrientation in the watch window and 0x00000034 (52 base 10) is displayed. (That says interpret the address at 0 as a DEVMODE structure and give the address of the dmDisplayOrientation member.) The SUBSTR function is 1 based, so the SUBSTR offset of dmDisplayOrientation is 53.

 

 

 

 

#define ENUM_CURRENT_SETTINGS       0xffffffff

#define ENUM_REGISTRY_SETTINGS      0xfffffffe

#define DMDO_DEFAULT    0

#define DMDO_90         1

#define DMDO_180        2

#define DMDO_270        3

#define DM_DISPLAYORIENTATION   0x00000080

 

 

CLEAR

*SetDisplay(DMDO_180)

SetDisplay(DMDO_90)

INKEY(3)

SetDisplay(DMDO_DEFAULT)

 

PROCEDURE SetDisplay(nOrientation as Integer)

      *sizeof(DEVMODE)=156

      cDevmode=REPLICATE(CHR(0),36)+BINTOC(156,"2sr")+REPLICATE(CHR(0),118)

      DECLARE integer EnumDisplaySettings IN WIN32API integer,integer,string @

      DECLARE integer ChangeDisplaySettings IN WIN32API string @, integer

 

      IF EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,@cDevmode)=0

            ?"Error"

            RETURN

      ENDIF

      nWidth=CTOBIN(SUBSTR(cDevmode,109,4),"4sr")

      nHeight=CTOBIN(SUBSTR(cDevmode,113,4),"4sr")

      ?"Screen dimensions are ",nWidth,"X",nHeight

      dmFields=CTOBIN(SUBSTR(cDevmode,41,4),"4sr")

      ?TRANSFORM(dmFields,"@0x")

 

      IF BITAND(dmFields,DM_DISPLAYORIENTATION)>0

            fSwap=.f.

            nDisplay = CTOBIN(SUBSTR(cDevmode,53,4),"4sr")

            ?"Current DisplayOrientation=",nDisplay

            IF nOrientation != nDisplay   && if different

                  fLandscape=nWidth>nHeight

                  DO CASE

                  CASE INLIST(nOrientation,DMDO_DEFAULT,DMDO_180)

                        fSwap = !fLandscape     && if it wasn't lasndscape, we need to swap x,y pixels

                  CASE INLIST(nOrientation,DMDO_90,DMDO_270)

                        fSwap = fLandscape

                  ENDCASE

                  IF fSwap

                        nTemp=nWidth

                        nWidth=nHeight

                        nHeight=nTemp

                  ENDIF

                  cDevmode=LEFT(cDevmode,108)+BINTOC(nWidth,"4sr")+BINTOC(nHeight,"4sr")+SUBSTR(cDevmode,117)

                  cDevmode=LEFT(cDevmode,52)+BINTOC(nOrientation,"4sr")+SUBSTR(cDevmode,57)

 

                  n= ChangeDisplaySettings(@cDevmode,0)

                  IF n=0

                        ?"Success"

                  ELSE

                        ?"Failed",n

                  ENDIF

            ENDIF

      ELSE

            ?"Can't get Display Orientation"

      ENDIF

 

RETURN