How to get all possible screen resolutions?

Previous topic - Next topic

Quentin

Sometimes it would be useful to let decide the "customer" in which screen resolution she or he wants to play your game. Currently GLBasic offers no support for this. In fact it's possible to set different screen resolutions with the SETSCREEN command but however one can not be sure if this resolution is working on every graphic card.

To find a remedy we can use a function of the Windows API which will deliver all possible resolutions of a graphic card. The following example program will show how to use this function in own programs.

From this place once more "special thanks to Gernot" for the help to find the right way calling this function.

The core is the function GetScreenModes() which can be called in two ways.

GetScreenModes(0)    
--> will deliver all resolutions which were supported by the graphic car. Some resolutions are shown several times as many resolutions could be used with differnt color depth and frequency. Color depth and frequency are not important for GLBasic at the time as they could not be affected with the normal commands like SETSCREEN (but who knows what future brings)

GetScreenModes(1)
--> will deliver all resolutions too but double entries will be deleted from the list.

Code (glbasic) Select
// --------------------------------- //
// Project: ScreenModes
// Start: Thursday, July 05, 2007
// IDE Version: 4.237

// this structure is needed to use function GetScreenModes()
TYPE tScreenMode
  width
  height
  bits
  frequency
ENDTYPE
GLOBAL ScreenMode[] AS tScreenMode
GLOBAL scrmode AS tScreenMode


// test program part 1
LOADFONT "arial.bmp", 0     // <-- here please enter an own font !!!!!!
GETFONTSIZE fontx, fonty
GetScreenModes(0)
PRINT "All possible resolutions:", 0, 0
y = 2 * fonty
FOREACH scrmode IN ScreenMode[]
  PRINT scrmode.width + " x " + scrmode.height + " Color depth: "+scrmode.bits+" Bits " + "Frequency: "+scrmode.frequency, 0, y
  INC y, fonty
NEXT
SHOWSCREEN
KEYWAIT

// test program part 2
GetScreenModes(1)
PRINT "Distinct resolutions:", 0, 0
y = 2 * fonty
FOREACH scrmode IN ScreenMode[]
  PRINT scrmode.width + " x " + scrmode.height, 0, y
  INC y, fonty
NEXT
SHOWSCREEN
KEYWAIT

// test program part 3
LOCAL maxres = BOUNDS(ScreenMode[], 0) - 1
SETSCREEN ScreenMode[maxres].width, ScreenMode[maxres].height, 1
PRINT "This is the highest resolution possible in fullscreen mode", 0, 0
y = 2 * fonty
FOREACH scrmode IN ScreenMode[]
  PRINT scrmode.width + " x " + scrmode.height, 0, y
  INC y, fonty
NEXT
SHOWSCREEN
KEYWAIT

END

FUNCTION WeNeedOne:
ENDFUNCTION

// In __GLBASIC__ namespace, outside of functions make a pointer to a function
INLINE
    DECLARE_ALIAS(    user32_EnumDisplaySettings, "user32.dll", \
                    "EnumDisplaySettingsA", (const char*, unsigned int, void*), \
                    int);
ENDINLINE

FUNCTION EnumDisplaySettings: disp$, num

    LOCAL retcode

    INLINE
        struct DEVMODE {
              char dmDeviceName[32];
              short dmSpecVersion;
              short dmDriverVersion;
              short dmSize;
              short dmDriverExtra;
              long  dmFields;
              short dmOrientation;
              short dmPaperSize;
              short dmPaperLength;
              short dmPaperWidth;
              short dmScale;
              short dmCopies;
              short dmDefaultSource;
              short dmPrintQuality;
              short dmColor;
              short dmDuplex;
              short dmYResolution;
              short dmTTOption;
              short dmCollate;
              char dmFormName[32];
              short dmUnusedPadding;
              long dmBitsPerPel;
              long dmPelsWidth;
              long dmPelsHeight;
              long dmDisplayFlags;
              long dmDisplayFrequency;
        };
        DEVMODE devmode;
        devmode.dmSize = sizeof(DEVMODE);
        // if disp$ = "", pass NULL instead!
        if (user32_EnumDisplaySettings(LEN(disp_Str) ? disp_Str.c_str() : NULL, num, &devmode))
        {
        scrmode.width = devmode.dmPelsWidth;
        scrmode.height = devmode.dmPelsHeight;
        scrmode.bits = devmode.dmBitsPerPel;
        scrmode.frequency = devmode.dmDisplayFrequency;
        retcode = 1;
        }
        else
        {
        retcode = 0;
        }
    ENDINLINE

    RETURN retcode

ENDFUNCTION


// ------------------------------------------------------------- //
// -=#  SCREENMODES  #=-
// ------------------------------------------------------------- //
FUNCTION GetScreenModes: restrict

  LOCAL found = TRUE
  LOCAL mode = 0
  LOCAL notsorted = TRUE
  LOCAL count, i
  LOCAL swapmode AS tScreenMode

  // get all resolutions possible. If the function returns a "0" or a "1"
  // as frequency then Windows is not sure about the frequency so
  // we will ignore this one as a precaution
  WHILE found
    IF EnumDisplaySettings("", mode)
      IF scrmode.frequency > 1
        DIMPUSH ScreenMode[], scrmode
      ENDIF
    ELSE
      found = FALSE
    ENDIF
    INC mode, 1
  WEND

  // sort the list ascending by the resolution
  // a simple bubble sort should be fast enough
  count = BOUNDS(ScreenMode[], 0)
  WHILE notsorted
    notsorted = FALSE
    FOR i = 0 TO count - 2
      IF ScreenMode[i].width > ScreenMode[i+1].width AND _
         ScreenMode[i].height > ScreenMode[i+1].height
        swapmode = ScreenMode[i]
        ScreenMode[i] = ScreenMode[i+1]
        ScreenMode[i+1] = swapmode
        notsorted = TRUE
      ENDIF
    NEXT
  WEND
 
  // if wanted delete all double entries
  IF restrict = 1
    swapmode.width = 0
    swapmode.height = 0
    FOREACH scrmode IN ScreenMode[]
      IF scrmode.width = swapmode.width AND scrmode.height = swapmode.height
        DELETE scrmode
      ENDIF
      swapmode = scrmode
    NEXT  
  ENDIF
 
ENDFUNCTION // SCREENMODES
To use this functionallity in your own programs just copy the coding to your own one and delete the parts of the test programs.
If someone find this useful, have fun!

Qedo

I only discovered it now. Great function.
Thank you  :booze:

bigsofty

Wow, this still works? Good old Win32 API, it will never die!
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)