2004/2/16 by Jack
由於Win32 SDK與作業系統核心版本緊密的的關係,導致Win32 API在各個不同版本間,或多或少都可能有些微差異,程式設計師再使用函式時,必須注意說明文件的註解,就以Timer來說,即使是同樣的函式在不同的核心版本中所使用的解析度並不相同,當然也不乏更嚴重的狀況,甚至可能出現應用程式在Win 98 版本可以正常執行而Win NT卻會產生錯誤,反之亦然。
如果應用程式所使用的API函式已經確定有版本上的問題,解決之道有二個;其一是依據平台版本各自編譯,其二是在應用程式中加入判斷使用者作業系統版本的機制,然後根據實際的版本執行相對應的程式碼。
就程式設計師的考量而言,使用第一種方式,系統必須為功能完全相同的應用程式,產生二種不同的版本,這會直接增加軟體維護的負擔,而第二種辦法,則將版本問題透過程式自行判斷以選擇正確的程式碼執行,但是必須額外撰寫判斷版本的程式碼,如果純以系統的角度來看,第二種方式的軟體維護負擔較輕,整體系統結構看起來也比較優雅。
使用第二種做法的關鍵是,如何取得使用者的作業系統版本?
在Win32 平台上,要取得作業系統相關的資料有二種方式,第一種是透過系統登錄檔中所儲存的機碼,第二種則是透過GetVersionEX()來取得。
在這裡我們要介紹的是透過GetVersionEX()取得並判斷作業系統的版本。
首先來看看GetVersionEX()函式的原型:
dwOSVersionInfoSize
OSVERSIONINFO資料結構的大小,可以利用sizeof(OSVERSIONINFO)取得
dwMajorVersion
作業系統的主要版本編號,其值分別代表以下作業系統版本
dwMinorVersion
作業系統次版本編號
dwBuildNumber
建立序號
[Windows Me/98/95:低字組內含建立序號,高字組為主要及次要版本編號]
dwPlatformId
作業平台識別代號
szCSDVersion
附加資訊字串,如Service Pack 3
了解這些成員所代表意義,接下來就能在程式中利用判斷的語法,偵測使用者的作業系統版本。
g++ -o c_getversion.exe resource.o c_getversion.cpp -mwindows
如果應用程式所使用的API函式已經確定有版本上的問題,解決之道有二個;其一是依據平台版本各自編譯,其二是在應用程式中加入判斷使用者作業系統版本的機制,然後根據實際的版本執行相對應的程式碼。
就程式設計師的考量而言,使用第一種方式,系統必須為功能完全相同的應用程式,產生二種不同的版本,這會直接增加軟體維護的負擔,而第二種辦法,則將版本問題透過程式自行判斷以選擇正確的程式碼執行,但是必須額外撰寫判斷版本的程式碼,如果純以系統的角度來看,第二種方式的軟體維護負擔較輕,整體系統結構看起來也比較優雅。
使用第二種做法的關鍵是,如何取得使用者的作業系統版本?
在Win32 平台上,要取得作業系統相關的資料有二種方式,第一種是透過系統登錄檔中所儲存的機碼,第二種則是透過GetVersionEX()來取得。
在這裡我們要介紹的是透過GetVersionEX()取得並判斷作業系統的版本。
首先來看看GetVersionEX()函式的原型:
BOOL GetVersionEx( LPOSVERSIONINFO lpVersionInformation );要取得作業系統版本,就必須先準備LPOSVERSIONINFO型態的資料結構,以下是資料結構的定義:
typedef struct _OSVERSIONINFO{ DWORD dwOSVersionInfoSize; DWORD dwMajorVersion; DWORD dwMinorVersion; DWORD dwBuildNumber; DWORD dwPlatformId; TCHAR szCSDVersion[ 128 ]; } OSVERSIONINFO;以下是OSVERSIONINFO資料結構各個成員所代表的意義:
dwOSVersionInfoSize
OSVERSIONINFO資料結構的大小,可以利用sizeof(OSVERSIONINFO)取得
dwMajorVersion
作業系統的主要版本編號,其值分別代表以下作業系統版本
作業系統版本 | dwMajorVersion |
Windows 95 | 4 |
Windows 98 | 4 |
Windows Me | 4 |
Windows NT 3.51 | 3 |
Windows NT 4.0 | 4 |
Windows 2000 | 5 |
Windows XP | 5 |
Windows Server 2003 family | 5 |
作業系統次版本編號
作業系統次版本 | dwMinorVersion |
Windows 95 | 0 |
Windows 98 | 10 |
Windows Me | 90 |
Windows NT 3.51 | 51 |
Windows NT 4.0 | 0 |
Windows 2000 | 0 |
Windows XP | 1 |
Windows Server 2003 family | 2 |
建立序號
[Windows Me/98/95:低字組內含建立序號,高字組為主要及次要版本編號]
dwPlatformId
作業平台識別代號
作業平台版本 | dwPlatformId |
VER_PLATFORM_WIN32s | Win32s on Windows 3.1. |
VER_PLATFORM_WIN32_WINDOWS | Windows?95, Windows?98, or Windows?Me. |
VER_PLATFORM_WIN32_NT | Windows?NT, Windows?2000, Windows XP, or Windows Server?2003 family. |
附加資訊字串,如Service Pack 3
了解這些成員所代表意義,接下來就能在程式中利用判斷的語法,偵測使用者的作業系統版本。
//-------------------start resource.h--------------- #include #include "resource.h" ID_ICON_1 ICON "icon1.ico" ID_ICON_2 ICON "icon2.ico" //-----------------end--------------------- //-------------------start resource.rc--------------- #include #include "resource.h" ID_ICON_1 ICON "icon1.ico" ID_ICON_2 ICON "icon2.ico" //-----------------end--------------------- 編譯視窗資源的指令為:編譯指令為:
windres -o resource.o -i resource.rc
//-------------------start c_getversion.cpp--------------- #include #include #include "resource.h" const char* szAppName = "MyWndClass"; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int nTopXY(UINT, UINT); int get_SystemVer(void); char szVersion [80]; //程式進入點 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; int wnd_W; int wnd_H; wnd_W=400; wnd_H=300; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON_1)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU); wc.lpszClassName = szAppName; wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON_2)); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "視窗類別登記失敗!", "發生錯誤!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, szAppName, "顯示作業系統版本", WS_OVERLAPPEDWINDOW, nTopXY(wnd_W, GetSystemMetrics(SM_CXSCREEN)), nTopXY(wnd_H, GetSystemMetrics(SM_CYSCREEN)), wnd_W,wnd_H, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "視窗建立失敗!", "發生錯誤!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hMyDC; PAINTSTRUCT ps; char szText[] = "顯示作業系統版本!!"; switch(msg) { case WM_CREATE: get_SystemVer(); break; case WM_PAINT: hMyDC=BeginPaint(hwnd, &ps); TextOut(hMyDC,100,100,szText,lstrlen(szText)); TextOut(hMyDC,100,120,szVersion,lstrlen(szVersion)); EndPaint(hwnd, &ps); break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } } int nTopXY(UINT wnd_XY, UINT wnd_Dim) { int resl; resl=((wnd_Dim/2)-(wnd_XY/2)); return resl; } int get_SystemVer(void){ OSVERSIONINFO osvi; memset(&osvi, 0, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&osvi); switch(osvi.dwPlatformId){ case VER_PLATFORM_WIN32s: wsprintf (szVersion, "Microsoft Win32s %d.%d (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); break; case VER_PLATFORM_WIN32_WINDOWS: if (osvi.dwMinorVersion==0){ wsprintf (szVersion, "Microsoft Windows 95 %d.%d (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); } else if (osvi.dwMinorVersion==10){ wsprintf (szVersion, "Microsoft Windows 98 %d.%d (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); } else if (osvi.dwMinorVersion==90){ wsprintf (szVersion, "Microsoft Windows Me %d.%d (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); } break; case VER_PLATFORM_WIN32_NT: if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0){ wsprintf (szVersion, "Windows 2000 With %s",osvi.szCSDVersion); } else if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1){ wsprintf (szVersion, "Windows XP %s",osvi.szCSDVersion); } else if (osvi.dwMajorVersion<=4){ wsprintf (szVersion, "Windows NT %d.%d with %s", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion); } break; } return 0; } //-----------------end---------------------
g++ -o c_getversion.exe resource.o c_getversion.cpp -mwindows
全站熱搜
留言列表