Práce s verzemi Windows v C++

V tomto článku si řekneme něco o verzích operačního systému Windows z hlediska programátora. Ukážeme si, jak za běhu programu zjistit, na které platformě a verzi běží, a dále si ukážeme, jak pomocí podmíněného překladu zajistit, aby výsledný kód mohl běžet na požadované verzi Windows. Začněme podmíněným překladem.
Nastavení cílové platformy pro podmíněný překlad

K určení cílové platformy aplikace používáme definované hodnoty, které můžeme definovat například pomocí

#define WINVER 0x0500

nebo ve Visual C++ přímo v nastavení projektu.

Uvedu zde přehled jednotlivých cílových platforem Windows a odpovídajících kombinací definovaných hodnot:

Windows 95 a Windows NT WINVER = 0x0400
Windows 98 a Windows NT _WIN32_WINDOWS=0x0410 a WINVER=0x0400
Windows NT 4.0 _WIN32_WINNT=0x0400 a WINVER=0x0400
Windows 98 _WIN32_WINDOWS=0x0410
Windows 2000 _WIN32_WINNT=0x0500 a WINVER=0x0500
Windows Me _WIN32_WINDOWS=0x0490
Windows XP _WIN32_WINNT=0x0501 a WINVER=0x0501
Dále máme možnost specifikovat požadovanou verzi Internet Exploreru
Internet Explorer 3.0 – 3.02 _WIN32_IE=0x0300
Internet Explorer 4.0 _WIN32_IE=0x0400
Internet Explorer 4.01 _WIN32_IE=0x0401
Internet Explorer 5.0 _WIN32_IE=0x0500
Internet Explorer 5.01-5.5 _WIN32_IE=0x0501
Ve vlastním zdrojovém kódu pak budeme testovat tyto hodnoty, abychom mohli rozhodnout, zda například některé funkce, podporované pouze na určité verzi, máme zahrnout do podmíněného překladu. Jako příklad si uvedeme použití průhledných oken ve Windows 2000 (a vyšší). Funkce SetLayeredWindowAttributes je totiž podporována pouze ve Windows 2000 a vyšší a nikoli na Windows řady 95 (tedy ani např. Windows Me).

#if _WIN32_WINNT >= 0x0500
  SetLayeredWindowAttributes(m_hWnd, 0, (BYTE)120, LWA_ALPHA);
#endif //_WIN32_WINNT >= 0x0500

Zjištění verze Windows za běhu programu

Nyní si ukažme, jak za běhu programu zjistit platformu a verzi Windows, na které program právě běží.

K tomuto účelu slouží funkce

BOOL GetVersionEx(
  LPOSVERSIONINFO lpVersionInfo // informace o verzi
);

jejíž parametr ukazuje na strukturu

typedef struct _OSVERSIONINFO{
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;

s tím, že ve Windows 2000 a vyšších navíc může parametrem být adresa rozšířené struktury

typedef struct _OSVERSIONINFOEX {
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  TCHAR szCSDVersion[ 128 ];
  WORD wServicePackMajor;
  WORD wServicePackMinor;
  WORD wSuiteMask;
  BYTE wProductType;
  BYTE wReserved;
} OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;

Když porovnáte tyto struktury, zjistíte, že „začátek té „rozšířené“ varianty je totožný s variantou OSVERSIONINFO. Můžeme tedy ve všech případech použít rozšířené varianty s tím, že nastavením prvku dwOSVersionInfoSize specifikujeme, zda použít plnou celou strukturu nebo její jednoduchou variantu fungující na všech verzích Windows. V prvním kroku tedy zjistíme, zda jsme ve Windows 2000 nebo vyšších, tím způsobem, že zkusíme použít plnou rozšířenou strukturu. V případě, že funkce vrátí chybu (tedy FALSE), budeme vědět, že nejsme ve Windows 2000, a zavoláme funkci znovu s tím, že předtím pouze nastavíme velikost struktury (dwOSVersionInfoSize) na sizeof(OSVERSIONINFO), tedy na jednoduchou variantu. Tento i další postup přesné specifikace verze, včetně zjištění nainstalovaného Servis Packu a čísla sestavení (ve Windows 2000) je zřejmý z následujícího opisu kódu (členská funkce dialogu ukázkové aplikace), který zjištěné informace „poskládá“ do dvou textových řetězců a zobrazí je ve zmíněném dialogu:

void CUkazkaDlg::ZobrazVerziWindows()
{
  TCHAR chVerze[200];
  OSVERSIONINFOEX osvi;
  BOOL bOsVersionInfoEx;
  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO > &osvi)) )
  {
  // pokud nefunguje, nejsme ve Windows 2000
    osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
    if (! GetVersionEx ( (OSVERSIONINFO > &osvi) )
      return; // někde se stala chyba!
  }
  switch ( osvi.dwPlatformId )
  {
    case VER_PLATFORM_WIN32_NT:
      if ( osvi.dwMajorVersion <= 4 )
        lstrcpy(chVerze, "Windows NT");
      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
        lstrcpy(chVerze, "Windows 2000");
      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
        lstrcpy(chVerze, "Windows XP");
      if ( bOsVersionInfoEx )
      {
        if ( osvi.wProductType == VER_NT_WORKSTATION )
          lstrcat(chVerze, " Professional");
        if ( osvi.wProductType == VER_NT_SERVER )
          lstrcat(chVerze, " Server");
      }
      else
      {
        HKEY hKey;
        char szProductType[80];
        DWORD dwBufLen;
        RegOpenKeyEx( HKEY_LOCAL_MACHINE,
          "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
          0, KEY_QUERY_VALUE, &hKey );
        RegQueryValueEx( hKey, "ProductType", NULL, NULL,
          (LPBYTE) szProductType, &dwBufLen);
        RegCloseKey( hKey );
        if (lstrcmpi( "WINNT", szProductType) == 0 )
          lstrcat(chVerze, " Workstation");
        if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
          lstrcat(chVerze, " Server");
      }
      m_Platforma.SetWindowText(chVerze);
      sprintf(chVerze, "verze %d.%d %s (Build %d)\n",
          osvi.dwMajorVersion,
          osvi.dwMinorVersion,
          osvi.szCSDVersion,
          osvi.dwBuildNumber & 0xFFFF);
      m_Verze.SetWindowText(chVerze);
      break;
    case VER_PLATFORM_WIN32_WINDOWS:
      if ( (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0))
        SendDlgItemMessage(IDC_PLATFORMA, WM_SETTEXT, 0, (LPARAM)"Microsoft Windows 95");
      if ( (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10))
        SendDlgItemMessage(IDC_PLATFORMA, WM_SETTEXT, 0, (LPARAM)"Microsoft Windows 98");
      if ( (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90))
        SendDlgItemMessage(IDC_PLATFORMA, WM_SETTEXT, 0, (LPARAM)"Microsoft Windows ME");
      break;
    case VER_PLATFORM_WIN32s:
        SendDlgItemMessage(IDC_PLATFORMA, WM_SETTEXT, 0, (LPARAM)"Microsoft Win32");
      break;
  }
}
Zde si můžete stáhnout ukázkový projekt win_version.zip (31 kB).

Diskuze (3) Další článek: Tablet PC od Microsoftu bude za rok

Témata článku: Software, Windows, Programování, Internet Explorer, Win +, Struktura, Byte, Win + V, Verze, Window, Práce, Windows +


Určitě si přečtěte

Šéf Spotify: Budeme zdražovat. Náš obsah se zlepšil
Markéta Mikešová
PředplatnéSpotify
Google vymyslel technologii superpřesného GPS. Už ji podporuje Pixel 5 a dorazí i na ostatní telefony

Google vymyslel technologii superpřesného GPS. Už ji podporuje Pixel 5 a dorazí i na ostatní telefony

** Kvalita GPS ve městech občas stojí za starou bačkoru ** Mohou za to odrazy signálu od okolních budov ** Google má jejich 3D model, a tak spolupracuje s výrobci GPS čipů

Jakub Čížek | 40

Jakub Čížek
NavigaceTechnologieGoogle
Vážně dnes ještě někdo krade Adobe? Video můžete stříhat zdarma v Resolve a fotky i vektory zvládne Affinity

Vážně dnes ještě někdo krade Adobe? Video můžete stříhat zdarma v Resolve a fotky i vektory zvládne Affinity

** Kde jsou ty doby, kdy měl skoro každý doma Photoshop ** Photoshop a Premiere Pro od kamaráda nebo z warezu ** Dnes už to nemá smysl, existuje totiž hromada laciných alternativ

Jakub Čížek | 90

Jakub Čížek
Grafický editorStřih videa
Nejlepší notebooky do 20 000 Kč. Tipy, co se dnes vyplatí koupit

Nejlepší notebooky do 20 000 Kč. Tipy, co se dnes vyplatí koupit

** S cenou do 20 tisíc lze vybrat solidní notebook na práci i hry ** Přenosné notebooky nabídnou i kovová těla a rychlý hardware ** Možná největší problém je nedostupnost, nejžádanější kusy jsou vyprodané

David Polesný | 33

David Polesný
VánoceNotebooky
26 užitečných rozšíření pro Chrome: Naučte prohlížeč nové věci

26 užitečných rozšíření pro Chrome: Naučte prohlížeč nové věci

** Prohlížeč Chrome obsahuje širokou škálu funkcí, neumí ale všechno ** Jeho schopnosti můžete rozšířit pomocí rozšíření ** Vybrali jsme pro vás zajímavé a užitečné doplňky

Karel Kilián | 44

Karel Kilián
Doplňky do prohlížečeChromeProhlížeče

Aktuální číslo časopisu Computer

Jak prodloužit výdrž notebooku

Velké testy: gamepady a inkoustové tiskárny

Důkladný test Sony Playstation 5