Borland C++ 5.5 トラブル |
Last Updated: Feb.3,2007 |
Borland C++ 5.5.1 でファイルオープンダイアログが表示されないトラブルについて。 |
まず、この現象が確認できる Windows GUI アプリのソースを示します。環境は、Windows 98 Second Edition。
// test1.cpp #include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */ ) { OPENFILENAME ofn; TCHAR szFile[MAX_PATH] = ""; ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hInstance = hInstance; ofn.lpstrFile = szFile; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&ofn)) { wsprintf(szFile, "Error: %lu", CommDlgExtendedError()); MessageBox(NULL, szFile, NULL, MB_OK); } else MessageBox(NULL, szFile, "取得したファイル名", MB_OK); return 0; } |
最初は非常に悩みました。VC++ 6.0 では、問題なくコンパイル・実行出来るのですが、BC++ 5.5.1 では、コンパイルは通っても実行が正常に出来ないのです。エラー番号が 1 と表示されていますので、MSDN ライブラリで調べてみると、
CDERR_STRUCTSIZE | The lStructSize member of the initialization structure for the corresponding common dialog box is invalid. |
つまり、OPENFILENAME 構造体の lStructSize メンバの値が無効だと言っているのです。はて、これはどうしたわけか?
次に、commdlg.h を開いて OPENFILENAME 構造体がどのように定義されているかを確認してみることにしました。
typedef struct tagOFNA { DWORD lStructSize; HWND hwndOwner; HINSTANCE hInstance; LPCSTR lpstrFilter; LPSTR lpstrCustomFilter; DWORD nMaxCustFilter; DWORD nFilterIndex; LPSTR lpstrFile; DWORD nMaxFile; LPSTR lpstrFileTitle; DWORD nMaxFileTitle; LPCSTR lpstrInitialDir; LPCSTR lpstrTitle; DWORD Flags; WORD nFileOffset; WORD nFileExtension; LPCSTR lpstrDefExt; LPARAM lCustData; LPOFNHOOKPROC lpfnHook; LPCSTR lpTemplateName; #ifdef _MAC LPEDITMENU lpEditInfo; LPCSTR lpstrPrompt; #endif #if (_WIN32_WINNT >= 0x0500) void * pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif // (_WIN32_WINNT >= 0x0500) } OPENFILENAMEA, *LPOPENFILENAMEA; (中略) #if (_WIN32_WINNT >= 0x0500) #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) #ifdef UNICODE #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W #else #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A #endif // !UNICODE #endif // (_WIN32_WINNT >= 0x0500) |
これを見ると一目瞭然なのですが、_WIN32_WINNT の値が 0x0500 以上かそうでないかによって、構造体のサイズがちがうのです。それでは、この値の正体が一体何なのか?が問題となります。調べてみましたが、ややこしいので(英語が苦手)、簡単に解釈すると、Windows 2000 以上が 0x0500 以上と言うことらしく、Windows NT4 は、0x0400 で、Windows 98 もこの仲間に入るみたいです。
であれば、解決法は 3 通りあります。
1. コンパイルオプションに -D_WIN32_WINNT=0x0400 を指定してコンパイルする。
COMMAND.COM /C BCC32.EXE -W -D_WIN32_WINNT=0x0400 test1.cpp |
2. OPENFILENAME 構造体の lStructSize メンバの値に OPENFILENAME_SIZE_VERSION_400 を指定する。
ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; ofn.hInstance = hInstance; ofn.lpstrFile = szFile; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&ofn)) { |
3. ソースファイルの先頭で、_WIN32_WINNT の値を 0x0400 に定義する。
// test1.cpp #define _WIN32_WINNT 0x0400 #include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */ ) { |
これで、問題は解決しました。
最後に OS の互換性について、この他のマクロ定義の値も含めて表にしておきます。
プラットフォーム | マクロ定義 | |
---|---|---|
Windows Vista | _WIN32_WINNT>=0x0600 | WINVER>=0x0600 |
Windows Server 2003 | _WIN32_WINNT>=0x0502 | WINVER>=0x0502 |
Windows XP | _WIN32_WINNT>=0x0501 | WINVER>=0x0501 |
Windows 2000 | _WIN32_WINNT>=0x0500 | WINVER>=0x0500 |
Windows NT 4.0 | _WIN32_WINNT>=0x0400 | WINVER>=0x0400 |
Windows Me | _WIN32_WINDOWS=0x0500 | WINVER>=0x0500 |
Windows 98 | _WIN32_WINDOWS>=0x0410 | WINVER>=0x0410 |
Windows 95 | _WIN32_WINDOWS>=0x0400 | WINVER>=0x0400 |
Internet Explorer のバージョンによってもいろいろあるようです。
ブラウザ | マクロ定義 | バンドル |
---|---|---|
Internet Explorer 7.0 | _WIN32_IE>=0x0700 | Vista |
Internet Explorer 6.0 SP2 | _WIN32_IE>=0x0603 | XP SP2 |
Internet Explorer 6.0 SP1 | _WIN32_IE>=0x0601 | - |
Internet Explorer 6.0 | _WIN32_IE>=0x0600 | XP |
Internet Explorer 5.5 | _WIN32_IE>=0x0550 | Me |
Internet Explorer 5.01 | _WIN32_IE>=0x0501 | 2000 |
Internet Explorer 5.0, 5.0a, 5.0b | _WIN32_IE>=0x0500 | 98SE |
Internet Explorer 4.01 | _WIN32_IE>=0x0401 | - |
Internet Explorer 4.0 | _WIN32_IE>=0x0400 | 98, 95 OSR2.5 |
Internet Explorer 3.0, 3.01, 3.02 | _WIN32_IE>=0x0300 | 95 OSR2 |
Back | Copyright (c) 2002, 2007 AOK. All Rights Reserved. |