25年ぶりのWindows98
RUSTを始めたら、ふと25年前にWindows98のプログラミングをしていたことを思い出しました。当時のコードをRUSTにしたらどうなるかやってみたくなり、当時のコードをVisual Studio 2019 で実行してみました。
昔のコード
// windows98.c #include <windows.h> LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); char szWinName[] = "MyWin"; int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hwnd; MSG msg; WNDCLASSEX wcl; wcl.cbSize = sizeof(WNDCLASSEX); wcl.hInstance = hThisInst; wcl.lpszClassName = szWinName; wcl.lpfnWndProc = WindowFunc; wcl.style = 0; wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); wcl.hCursor = LoadCursor(NULL, IDC_ARROW); wcl.lpszMenuName = NULL; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); if (!RegisterClassEx(&wcl)) return 0; hwnd = CreateWindow( szWinName, "Windows 98", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL ); ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
Visual Studio 2019 でコンパイル
新しいプロジェクトの作成から空のプロジェクトを作成して、上記コードをソースファイルを追加します。
エラー・警告が多発
そしてメニューの「ビルド」「ソリューションのリビルド」を実行したところ下のようにエラー・警告が発生しました。VC++の時は、何も発生しませんでしたので予想外でした。
エラーの対処
コードLNK2019、LNK1120をクリックするWEBページが開きますが、読んでみても何のことか理解することができず、ソリューションエクスプローラーを色々見てみることにしました。
このケースですと、windows98がプロジェクト名で太文字になっています。ここを右クリックするとメニューがいっぱい表示され、一番下の「プロパティ」をクリックします。
プロジェクトのプロパティページが開きます。一番左の「構成プロパティ」「リンカー」「システム」をクリックします。右のリストの一番上のサブシステムがコンソール(/SUBSYSTEM:CONSOLE)となっているのを変更します。
リストからWindows(/SUBSYSTEM:WINDOWS)を選択します。
再度ソリューションのリビルドしてみます。エラーは消え警告だけになりました。
コードC2851について、WinMainの仮引数に、_In_ または _In_opt_ の注釈をつけてみました。C6276については、”Windows 98″の前に L をつけて L”Windows 98″ としてみました。再度、ソリューションのリビルドをみてみたところ、エラー・警告は出ることなく終了しました。
C4133について対処することなく終わりましたが、機会があれば追跡したいと思います。今回は下のコードを最終形とします。
コードの最終形
// windows98.c #include <windows.h> LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); char szWinName[] = "MyWin"; int WINAPI WinMain(_In_ HINSTANCE hThisInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPSTR lpszArgs, _In_ int nWinMode) { HWND hwnd; MSG msg; WNDCLASSEX wcl; wcl.cbSize = sizeof(WNDCLASSEX); wcl.hInstance = hThisInst; wcl.lpszClassName = szWinName; wcl.lpfnWndProc = WindowFunc; wcl.style = 0; wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); wcl.hCursor = LoadCursor(NULL, IDC_ARROW); wcl.lpszMenuName = NULL; wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); if (!RegisterClassEx(&wcl)) return 0; hwnd = CreateWindow( szWinName, L"Windows 98", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL ); ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }