當前位置: 華文世界 > 科技

輕松玩轉windows控制台( 四):控制台視窗大小的設定

2024-02-13科技

寫在前面

在上一篇文章中,詳細的介紹了透過格式字串對文字進行各種設定(原文連結:輕松玩轉windows控制台( 三):魔改文字和玩轉光標),比如給文字加上底線、高亮顯示文字等等,又著重介紹了如何靈活控制當前光標的位置,可以定位在控制台螢幕的任意位置,可以前進、後退、上下左右四個方向任意移動等的功能。

為後期的控制台遊戲開發提供了一些準備知識,突破了我們對控制台一成不變黑視窗的印象,原來隨著我們技能的提升,控制台是可以被我們隨心所欲玩轉的。

控制台就像一個盲盒,每次偵錯控制台程式時,它的大小和位置都是未知的,今天,我們就來學習一下,如何設定控制台視窗的大小。

控制台視窗的2個大小

我們通常所說的控制台視窗的大小,其實指的是控制台程式的顯示面積占據整個螢幕的區域,我們把這個大小,稱為控制台的「顯示區域」,或可見區域、可視區域都可以。如圖:

我的桌面是黑色的,和控制台的背景很相似,但是仔細看,還是能看到邊框痕跡的。紅框內的控制台視窗的大小,稱為控制台的「顯示區域」(可見區域)。

控制台視窗內輸入輸出數據,以及滑鼠、鍵盤等裝置的響應事件、以及操作的歷史記錄等等,都被儲存在控制台的「螢幕緩沖區」(Screen Buffer),螢幕緩存區也是有大小的,這個大小指的是能儲存的數據的多少。這樣說實際上是不準確的,但是為了降低學習的復雜度,這樣處理是最合適的,否則按下面的講法:

每個控制台都有一個包含輸入事件記錄佇列的輸入緩沖區。當控制台的視窗獲得鍵盤焦點時,控制台會將每個輸入事件(例如單次擊鍵、滑鼠移動或滑鼠按鈕單擊)設定為它放置在控制台輸入緩沖區中的輸入記錄。

這種描述雖然嚴謹,但是牽涉到了滑鼠時間、鍵盤事件、緩沖區的數據結構等等,會讓我們的學習曲線在開始的時候就會變得陡峭,基本上就變成了從入門到放棄。在前期是不需要深入學習的,後期會在我的實戰課中逐漸學習到的。

視窗的顯示區域指的是當前控制台視窗的外觀大小,螢幕緩沖區指的是當前控制台視窗的數據儲存的容量的大小,我們先來講解下視窗顯示區域如何設定大小。

設定視窗可見區域的大小

控制台視窗尺寸的設定,有很多種方法,本文先介紹兩種最簡單移動的方法。一個是透過DOS命令mode來進行設定,另一個是透過windows的控制台函式來進行設定。

我們先介紹第一種。DOS命令中有一個mode命令,mode是「模式」的意思,可以設定控制台的模式,也可以設定印表機的模式,等等。

控制台在DOS命令一般稱為「con」,是console的簡寫。設定控制台的視窗大小,實際上就是設定它在螢幕上的顯示區域,有多少行多少列可見。

比如說我們設定了展示出20行,但是如果我們輸入和輸出的內容超過了20行,那麽除非移動捲軸,否則是看不到的。舉個例子:

我們開啟了一個控制台視窗,如果螢幕輸入和顯示的內容超過了螢幕的顯示區域,就會自動出現捲軸,如下圖所示:

我們輸入了一個dir命令,顯示的內容的行數已經超過了視窗顯示區域的行數,所以可見區域以外的部份,就需要透過捲軸上下捲動來顯示被遮蔽的內容,無論如何捲動,控制台視窗的可見區域大小都不會被改變的。

可見區域的行數和列數就是視窗的尺寸。透過剛才介紹的mode命令,就可以進行設定。命令如下:

mode con lines = 40 cols = 20

mode con 是設定console(控制台)的mode(模式)的意思。lines 是行,col是colum的簡寫,後面加s是因為復數。

下面是一段演示如何透過程式來利用mode命令設定控制台視窗尺寸的程式碼:

#include <stdio.h>#include <stdlib.h>int main() { int lines = 20,cols = 30; char console_size[50]; sprintf(console_size,"mode con lines=%d cols=%d",lines,cols); system(console_size); printf("input lines: "); scanf("%d",&lines); printf("input cols: "); scanf("%d",&cols); sprintf(console_size,"mode con lines=%d cols=%d",lines,cols); system(console_size); printf("new lines = %d\nnew cols = %d\n",lines,cols); system("pause"); return 0;}

程式啟動時的預設控制台視窗尺寸為20行30列,可以隨時改變視窗尺寸。註意, lines=30,和cols=20,中間不能有空格 ,否則命令不起作用。之所以用sprintf函式,是為了能靈活接收變量的值。程式剛開始執行視窗尺寸如下:

輸入行數15,列數30保持不變,視窗尺寸效果如下:

除了透過system函式執行DOS命令的方式以外,我們一般更常用的辦法,是透過windows提供的控制台函式來設定控制台視窗尺寸。函式原型如下:

BOOL SetConsoleWindowInfo( HANDLE hConsoleOutput, BOOL bAbsolute, const SMALL_RECT *lpConsoleWindow);typedef struct _SMALL_RECT {SHORT Left;SHORT Top;SHORT Right;SHORT Bottom;} SMALL_RECT;

第一個是要用到的控制台函式的原型定義,第二個是函式最後一個參數要用到的結構體型別的定義。我們來詳細解釋下這兩者。

SetConsoleWindowInfo,見名知義,設定控制台視窗資訊,這個函式的作用局勢用來設定控制台的顯示區域的尺寸大小的(和之前的DOS命令一樣,不是設定螢幕緩沖區大小,都只是設定控制台視窗顯示區域的大小,螢幕緩沖區大小後文會介紹)。

函式執行成功,會返回TRUE,失敗返回FALSE。第一個參數需要傳入某個控制台的控制代碼值 ,控制代碼的用法我們在之前的系列文章裏已經介紹過了,這裏不再贅述,一般都是透過GetStdHandle函式獲取到當前控制台視窗的控制代碼值,然後傳入即可。

第二個參數是狀態開關,如果FALSE,則我們傳入的視窗尺寸是相對值,如果是TRUE,則傳入的視窗尺寸是絕對值。相對值是指相對於當前控制台視窗尺寸的偏移量。絕對值,是指重新指定一組新的視窗尺寸,下面的演示程式碼就是使用的是絕對值用法。

最後一個參數,是一個SMALL_RECT結構體。如果狀態開關是TRUE的話,這個結構體存放的是新的視窗的尺寸大小。因為後面控制台系列文章中,要經常用到。下面就詳細介紹下。

RECT是rectangle的簡稱,矩形的含義。每一個表單都是一個矩形的結構。船體一般有4個頂點共同構成一塊矩形區域, 但是如果指定了左上頂點和右下頂點的位置,那麽這個矩形實際上也就被唯一確定了

左上頂點一般由x座標和y座標組成。之前文章已經說過,整個螢幕的座標軸,包括GUI圖形的座標軸,都是把左上頂點作為原點,往下是y軸,往右是x軸。

因此我們控制台視窗也是這樣。左上角是座標軸原點,y軸一般稱為Top(top),x軸一般稱為Left(left)。因為是原點,所以Top和Left一般預設為:Top = 0,left= 0。以此類推,右下角座標的x軸我們一般稱為Right(right),y軸稱為Bottom(bottom)。

實際上bottom就是行數,right就是列數(每一行的可見字元個數)。

small是指這個矩形的4個成員變量的數據型別都是short型別。small表示小,shaort表示短整型。

我們假設控制台的顯示區域(可見區域)是15行40列(每行可見40個字元),給出演示程式碼如下:

#include <windows.h>int main() { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SMALL_RECT newWindowSize = {0, 0, 39, 14}; // 設定新的視窗尺寸,寬度為40字元,高度為15行 SetConsoleWindowInfo(hConsole, TRUE, &newWindowSize); system("pause"); return 0;}

首先透過GetStdHandle獲取標準裝置的控制代碼,參數指定了要獲取控制代碼的標準裝置的型別是什麽,本例是控制台,STD_OUTPUT_HANDLE,指的就是控制台物件的控制代碼。

然後定義一個區域的大小,作為新的控制台視窗的尺寸。從0開始,直到39,一共右40個字元,從0到14,一共15行。狀態標誌一定要是TRUE,表示是透過絕對值來設定新的視窗尺寸。

程式執行效果如圖所示:

總 結

本文主要講解了控制台視窗的大小不僅僅是螢幕上看見的「顯示區域」(可見區域),還包括視窗輸入輸出的數據的儲存大小。

並且透過程式碼詳細演示了如何設定控制台視窗的顯示區域(可見區域)的尺寸,並且給出了2個實作的方法,特別提醒的是,這2個方法只是講解了控制台顯示區域的大小設定,他們的螢幕緩沖區的大小都是作業系統設定的預設值。

下一篇將詳細講解控制台螢幕緩沖區的設定(ScreenBufferSize),包括獲取當前控制台視窗的預設緩沖區的大小,以及如何設定成新的大小等實際操作。

段譽,24年2月12日(年初三),寫於合肥。