
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;
}