
Windows API を使い、コンソール画面を制御する機能を確認していきます。
まずはコンソール画面の縦横のサイズを変更するプログラムを作成していきましょう。
Windows 上のコンソールサイズを制御するために、 Windows の機能(Windows API)を用いて、画面サイズを変更できます。
ではでは、画面サイズを変更する関数、changeConsoleSize 関数を作っていきます。
#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次元の領域で、この一部分がコンソール上に表示されています。
この実際に表示されている領域がコンソールウィンドウです。
コンソールウィンドウはコンソールバッファの一部なので、コンソールウィンドウ はコンソールバッファよりも小さいきい必要があります。
コンソールウィンドウのサイズを今より大きくする場合は、
の順番が必要となります。
また、コンソールウィンドウのサイズを今より小さくする場合は、
という順番が必要となります。
コンソールウィンドウを大きくする、小さくすることの両方に対応させるため、 今回はまずウィンドウをぐっと小さくしてから、目的のサイズまで大きくする、という手順のプログラムとしています。
コンソールバッファは SetConsoleScreenBufferSize 関数でサイズを変更できます。また、 コンソールウィンドウは SetConsoleScreenBuffer 関数でサイズを変更できます。
では、コードを順に追ってみます。
HANDLE hStdout;
COORD coord;
coord.X = x;
coord.Y = y;
4 行目で HANDLE 型が登場します。これは、Windows OS 上で表示されるウィンドウ(ボタンやメニューバー、など全般)への ポインタを扱う型です。
後ほど、このコンソールウィンドウ(標準出力先)へのポインタを取得して格納する変数として衣装します。
5 行目で COORD 型が登場します。COORD は直訳すると数学座標です。 構造体で下のように定義されています。
typedef struct _COORD {
SHORT X; // 座標X
SHORT Y; // 座標Y
} COORD, *PCOORD;
2次元の座標x、yの情報をもつ構造体です。 COORD型は、ウィンドウバッファのサイズを設定するときの引数で使用します。
9行に SMALL_RECT 型が登場します。 SMALL_RECT は構造体で定義されており、名前の通り、「小さな(Small)四角形(Rectancle」を意味しています。
2次元座標で、四角い領域の範囲を扱うための情報を格納できます。
SMALL_RECT rectConsoleSize;
rectConsoleSize.Left = 0;
rectConsoleSize.Top = 0;
rectConsoleSize.Right = 1;
rectConsoleSize.Bottom = 1;
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 関数を使い、標準入出力にアクセスするための HANDLE(ポインタアドレス)を取得しています。 引数の中には定数で STD_OUTPUT_HANDLE を指定しており、これは標準出力先( つまり、文字を出力する先のコンソールウィンドウ ) を取得したい、と指定することになります。
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
正常に標準出力への HANDLE が取得できれば、 HANDLE は hStdout 変数に入ります。
移行、コンソールウィンドウのサイズや、コンソールバッファサイズの変更などは、この hStdout 変数を通して 実施していきます。
以下、17行目でコンソールウィンドウのサイズを変更Sるう、 SetConsoleWindowInfo 関数が登場します。
// Step1. 一度コンソール表示サイズをぎゅっと小さくする
SetConsoleWindowInfo(hStdout, TRUE, &rectConsoleSize);
SetConsoleWindowInfo は以下のように使用します。
SetConsoleWindowInfo(
HANDLE hConsoleOutput // 標準出力へのHANDLE
,BOOL bAbsolute // TRUEなら絶対座標、FALSEなら現在の位置からの相対座標
,SMALL_RECT *lpConsoleWindow // 表示する領域
);
四角の領域をもつポインタ変数 rectConsoleSize の中身は (0,0)-(1,1) というデータが入っていますので、 この関数が正常に実行されると、コンソールウィンドウが一瞬、非常に小さくなります。。
続いて、20行目から、コンソールバッファのサイズを縮小します。
// Step2. バッファサイズを目的の大きさに設定する
if ( !SetConsoleScreenBufferSize(hStdout, coord) ) {
return FALSE;
}
SetConsoleScreenBufferSize 関数にバッファサイズ(coord変数)を指定して変更しています。 ここでは、coord 辺陬の中身にある通り幅は変数 x、縦は辺陬 y を指定しています。
// 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の制限
コメント、ありがとうございます。
ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。
Twitter:@NodachiSoft_jpお名前:以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください
お名前: