2014年3月28日金曜日

遠回りで学ぶWin32 APIでOpenGL 001

はじめに

敢えてGLUTもGLEWもIDEも使わずにOpenGLで描画をするための手順をまとめておく.

エントリポイント

Win32 APIを使う場合,プログラムの開始位置はmain関数ではなく,WinMain関数(MSDNのドキュメント)になる.

// 000_entrypoint.cpp
#include <tchar.h>
#include <Windows.h>

int WINAPI _tWinMain(
    HINSTANCE hInstance,
    HINSTANCE,
    LPTSTR lpCmdLine,
    int nCmdShow
)
{
    return 0;
}

tchar.hとWindows.hが必要になる.ここで,WinMainではなく_tWinMainとなっているのは,文字コード周りの諸々に対応するため.詳しくはこちら(MSDNのドキュメントへ)

コンパイル

Visual Studioに付属しているコンソールを起動するか,環境変数VSINSTALLDIRの位置にあるvcvarsall.batを実行し,環境を設定したら,以下のコマンドを実行する.

cl 000_entrypoint.cpp

コンソール割り当て

WinMain関数を利用する場合,コンソールウィンドウが表示されないため,標準入出力が利用できない.そこで,AllocConsole(MSDNのドキュメント)を使ってコンソールウィンドウを用意する.

// 001_allocate_console.cpp
#include <tchar.h>
#include <Windows.h>
#include <cstdio>
#include <iostream>

using namespace std;

int WINAPI _tWinMain(
    HINSTANCE hInstance,
    HINSTANCE,
    LPTSTR lpCmdLine,
    int nCmdShow
)
{
    if(!AllocConsole()){
        return 0;
    }

    freopen("CONOUT$", "w", stdout);
    freopen("CONIN$", "r", stdin);

    cout << "コンソール割り当てに成功しました." << endl;
    cout << "終了します.何かキーを入力してください." << endl;
    cin.get();

    FreeConsole();

    return 0;
}

AllocConsoleでコンソールウィンドウが用意できたら,freopenに"CONOUT$","CONIN$"という名前を指定してやると,それぞれコンソールへの出力,入力として結び付けられる.最後に,AllocConsoleをした場合はFreeConsoleでコンソールを解放する必要がある.

コンパイル

例外を有効にする必要があるので,/EHscのオプションを追加してビルドする.

cl /EHsc 001_allocate_console.cpp

コンソール割り当てのクラス化

AllocConsole後にFreeConsoleし忘れないように,コンストラクタでAllocConsoleをし,デストラクタでFreeConsoleするようなクラスを作る.

// using_console.h
#ifndef USING_CONSOLE_H_INCLUDED
#define USING_CONSOLE_H_INCLUDED

class using_console {
public:
    //! コンソールを割り当てる
    using_console();
    //! コンソールを解放する
    ~using_console();

    bool isConsoleAllocated() const;

private:
    // コピー禁止
    using_console(using_console const &);
    using_console & operator=(using_console const &);

    //! コンソールが割り当てられたかどうか
    bool mConsoleAllocated;
};

#endif // USING_CONSOLE_H_INCLUDED
// using_console.cpp
#include <tchar.h>
#include <Windows.h>
#include <cstdio>

/*!
    コンソールを割り当て,成功した場合には標準入出力と
    コンソールを結び付ける.
 */
using_console::using_console()
    :   mConsoleAllocated(AllocConsole())
{
    if(isConsoleAllocated()){
        freopen("CONOUT$", "w", stdout);
        freopen("COUIN$", "r", stdin);
    }
}

/*!
    コンソールが割り当てられている場合,
    コンソールを解放する.
 */
using_console::~using_console()
{
    if(isConsoleAllocated()){
        FreeConsole();
    }
}

bool using_console::isConsoleAllocated() const
{
    return mConsoleAllocated;
}

第一回まとめ

  • Win32 APIのエントリポイントはWinMain
  • コンソールを利用するにはAllocConsoleからCONOUT$とCONIN$でfreopen

第二回へ

0 件のコメント:

コメントを投稿