Sibainu Relax Room

柴犬と過ごす

Windowsプログラミング 1

25年ぶりのWindows98

RUSTを始めたら、ふと25年前にWindows98のプログラミングをしていたことを思い出しました。当時のコードをRUSTにしたらどうなるかやってみたくなり、当時のコードをVisual Studio 2019 で実行してみました。

昔のコード

copy

// 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について対処することなく終わりましたが、機会があれば追跡したいと思います。今回は下のコードを最終形とします。

コードの最終形

copy

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