Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2021年3月12日に更新

第3章2 コンソールサイズの変更

イチからゲーム作りで覚えるC言語
第3章1 WindowsAPIを使う・sleep関数 : PREV
NEXT : 第3章3 文字の出力位置を変更 :

概要

Windows API を使い、コンソール画面を制御する機能を確認していきます。

まずはコンソール画面の縦横のサイズを変更するプログラムを作成していきましょう。

画面サイズ変更

Windows 上のコンソールサイズを制御するために、 Windows の機能(Windows API)を用いて、画面サイズを変更できます。

ではでは、画面サイズを変更する関数、changeConsoleSize 関数を作っていきます。

 
mode_ex.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
BOOL changeConsoleSize(int x, int y) {
    HANDLE hStdout;
    COORD coord;
    coord.X = x;
    coord.Y = y;

    SMALL_RECT rectConsoleSize;
    rectConsoleSize.Left = 0;
    rectConsoleSize.Top = 0;
    rectConsoleSize.Right = 1;
    rectConsoleSize.Bottom = 1;

    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

    // Step1. 一度コンソール表示サイズをぎゅっと小さくする
    SetConsoleWindowInfo(hStdout, TRUE, &rectConsoleSize);

    // Step2. バッファサイズを目的の大きさに設定する
    if (!SetConsoleScreenBufferSize(hStdout, coord)) {
        return FALSE;
    }

    // Step3. ウィンドウサイズを目的の大きさに設定にする
    rectConsoleSize.Right = x - 1;
    rectConsoleSize.Bottom = y - 1;
    SetConsoleWindowInfo(hStdout, TRUE, &rectConsoleSize);
    return TRUE;
}

int main() {
    int x, y;
    printf("コンソールのサイズを入力してください。\n例:10 5\n入力:");
    scanf("%d %d", &x, &y);
    changeConsoleSize(x, y);
    printf("サイズ変更完了!\n");
}

実行すると、下のようなイメージになります。

コンソールサイズの変更

コンソールのサイズが変わりました!

横、縦の文字数分のサイズに変更されます。

コード解説

コンソールに文字が表示されるとき、裏にコンソールバッファという領域があります。 コンソールバッファは X,Y の2次元の領域で、この一部分がコンソール上に表示されています。

この実際に表示されている領域がコンソールウィンドウです。

コンソールウィンドウはコンソールバッファの一部なので、コンソールウィンドウ はコンソールバッファよりも小さいきい必要があります。

コンソールウィンドウのサイズを今より大きくする場合は、

  1. まずコンソールバッファを大きくする
  2. コンソールウィンドウのサイズをバッファに合わせて大きくする

の順番が必要となります。

また、コンソールウィンドウのサイズを今より小さくする場合は、

  1. まずコンソールウィンドウのサイズを小さくする
  2. コンソールバッファを小さくする(コンソールウィンドウに合わせる)

という順番が必要となります。

コンソールウィンドウを大きくする、小さくすることの両方に対応させるため、 今回はまずウィンドウをぐっと小さくしてから、目的のサイズまで大きくする、という手順のプログラムとしています。

サイズ変更のための関数

コンソールバッファは SetConsoleScreenBufferSize 関数でサイズを変更できます。また、 コンソールウィンドウは SetConsoleScreenBuffer 関数でサイズを変更できます。

では、コードを順に追ってみます。

mode_ex.c
   HANDLE hStdout;
   COORD coord;
   coord.X = x;
   coord.Y = y;

HANDLE型

4 行目で HANDLE 型が登場します。これは、Windows OS 上で表示されるウィンドウ(ボタンやメニューバー、など全般)への ポインタを扱う型です。

後ほど、このコンソールウィンドウ(標準出力先)へのポインタを取得して格納する変数として衣装します。

COORD型

5 行目で COORD 型が登場します。COORD は直訳すると数学座標です。 構造体で下のように定義されています。

COORD定義
typedef struct _COORD {
  SHORT X;  // 座標X
  SHORT Y;  // 座標Y
} COORD, *PCOORD;

2次元の座標x、yの情報をもつ構造体です。 COORD型は、ウィンドウバッファのサイズを設定するときの引数で使用します。

SMALL_RECT 型

9行に SMALLRECT 型が登場します。 SMALLRECT は構造体で定義されており、名前の通り、「小さな(Small)四角形(Rectancle」を意味しています。

2次元座標で、四角い領域の範囲を扱うための情報を格納できます。

mode_ex.c
SMALL_RECT rectConsoleSize;
rectConsoleSize.Left = 0;
rectConsoleSize.Top = 0;
rectConsoleSize.Right = 1;
rectConsoleSize.Bottom = 1;

SMALL_RECT 構造体は下のように定義されています。

SMALL_RECT定義
typedef struct _SMALL_RECT {
  SHORT Left;
  SHORT Top;
  SHORT Right;
  SHORT Bottom;
} SMALL_RECT;

四角形は2つの点で表すことができます。 点1(Left, Top)から点2(Right, Bottom) です。

今回のコードでは、まず、コンソールウィンドウを小さく絞りたいので、 ウィンドウバッファの (0,0)-(1,1) の領域のみを表示するように設定しています。

GetStdHandle 関数

続いて、GetStdHandle 関数を使い、標準入出力にアクセスするための HANDLE(ポインタアドレス)を取得しています。 引数の中には定数で STDOUTPUTHANDLE を指定しており、これは標準出力先( つまり、文字を出力する先のコンソールウィンドウ ) を取得したい、と指定することになります。

mode_ex.c
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

正常に標準出力への HANDLE が取得できれば、 HANDLE は hStdout 変数に入ります。

移行、コンソールウィンドウのサイズや、コンソールバッファサイズの変更などは、この hStdout 変数を通して 実施していきます。

SetConsoleWindowInfo 関数

以下、17行目でコンソールウィンドウのサイズを変更Sるう、 SetConsoleWindowInfo 関数が登場します。

mode_ex.c
   // Step1. 一度コンソール表示サイズをぎゅっと小さくする
   SetConsoleWindowInfo(hStdout, TRUE, &rectConsoleSize);

SetConsoleWindowInfo は以下のように使用します。

SetConsoleWindowInfo定義
SetConsoleWindowInfo(
     HANDLE hConsoleOutput // 標準出力へのHANDLE
    ,BOOL bAbsolute // TRUEなら絶対座標、FALSEなら現在の位置からの相対座標
    ,SMALL_RECT *lpConsoleWindow // 表示する領域
);

四角の領域をもつポインタ変数 rectConsoleSize の中身は (0,0)-(1,1) というデータが入っていますので、 この関数が正常に実行されると、コンソールウィンドウが一瞬、非常に小さくなります。。

SetConsoleScreenBufferSize関数

続いて、20行目から、コンソールバッファのサイズを縮小します。

mode_ex.c
// Step2. バッファサイズを目的の大きさに設定する
if ( !SetConsoleScreenBufferSize(hStdout, coord) ) {
    return FALSE;
}

SetConsoleScreenBufferSize 関数にバッファサイズ(coord変数)を指定して変更しています。 ここでは、coord 辺陬の中身にある通り幅は変数 x、縦は辺陬 y を指定しています。

サイズの拡大

mode_ex.c
// Step3. ウィンドウサイズを目的の大きさに設定にする
rectConsoleSize.Right = x -1;
rectConsoleSize.Bottom = y - 1;
SetConsoleWindowInfo(hStdout, TRUE, &rectConsoleSize);

最後に、辺陬 rectConsoleSize の中身を (0,0)-(x-1, y-1) に更新し、 SetConsoleWindowInfo 関数で、コンソールウィンドウのサイズを目的のサイズまで拡大します。

これでコンソールウィンドウサイズを 横 x、 縦 y 文字のサイズにするという目標が達成できました。

modeコマンド

Windowsコマンドプロンプト上からは mode というコマンドを入力することでウィンドウサイズを変更できます。 例えばmode 50,20 と入力すると、 横 50 文字、縦 20 文字のサイズのコンソールウィンドウにサイズが変更されます。

Windowsコンソールを操作するAPI

Windows のコンソールを制御する関数などは WinCon.h (Windows Console ヘッダの略と思われます)を インクルードすると使えますが、このヘッダは Windows.h が勝手に含んでくれるので とりあえず Windows.h をインクルードしておけば OK です!

うまく動作しないとき

SSH でリモートターミナルで接続している時。 Cygwin の Bash ターミナルなどはうまく動作しません。

また、SetConsoleScreenBuffer関数にはの下のような制限がありますので、うまく動作しないときは エラー原因を確認していくのが良いと思います。

変更後のサイズ、バッファサイズの関係でうまく動作しない場合は、 下記の制限に引っかかっていないかを確認すると良いかもしれません。

SetConsoleScreenBufferの制限

  • システムで許容されている最小サイズより小さくはできない
  • fontsize と ウィンドウ最小サイズより小さくはできない
  • Console Screen buffer より小さくはできない
  • 正常に動作で 0 以外を返す。失敗で 0 を返す。失敗内容は GetLastError関数で取得可能

参考文献

イチからゲーム作りで覚えるC言語
第3章1 WindowsAPIを使う・sleep関数 : PREV
NEXT : 第3章3 文字の出力位置を変更 :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

第4章3 C言語コンソール上で迷路脱出プログラム・迷路の自動生成

#C11仕様#C言語#ゲームプログラミング✎ 2021-05-15
C言語のコンソールゲームで迷路脱出ゲームプログラムの作り方を確認します。迷路は自動生成されます
広告領域
追従 広告領域
目次
第3章2 コンソールサイズの変更
第3章2 コンソールサイズの変更
概要
概要
画面サイズ変更
画面サイズ変更
コード解説
コード解説
サイズ変更のための関数
サイズ変更のための関数
HANDLE型
HANDLE型
COORD型
COORD型
SMALL_RECT 型
SMALL_RECT 型
GetStdHandle 関数
GetStdHandle 関数
SetConsoleWindowInfo 関数
SetConsoleWindowInfo 関数
SetConsoleScreenBufferSize関数
SetConsoleScreenBufferSize関数
サイズの拡大
サイズの拡大
うまく動作しないとき
うまく動作しないとき
参考文献
参考文献
Nodachisoft © 2021