开始使用 DOS conio 进行编程

通过使用 conio 编程创建各种实用且令人兴奋的应用程序。
43 位读者喜欢这篇文章。
Person using a laptop

如此多的 DOS 应用程序采用文本用户界面 (TUI) 的原因之一是它非常容易实现。控制控制输入输出 (conio) 的标准方法是使用许多 C 程序员的 conio 库。这是 DOS 上的事实标准库,它因 Borland 的专有 C 编译器作为 conio.h 实现而广受欢迎。您还可以在 TK Chia 的 IA-16 DOS 版本的 GNU C 编译器中的 libi86 非标准例程库中找到类似的 conio 实现。该库包括 conio.h 函数的实现,这些函数模仿 Borland Turbo C++ 来设置视频模式、显示彩色文本、移动光标等等。

多年来,FreeDOS 在标准发行版中包含了 OpenWatcom C 编译器。OpenWatcom 支持其自己的 conio 版本,该版本在 conio.h 中为特定的控制台输入和输出函数实现,并在 graph.h 中实现以设置颜色和执行其他操作。由于 OpenWatcom C 编译器长期以来被许多开发人员使用,因此这种 conio 实现也非常流行。让我们开始使用 OpenWatcom conio 函数。

设置视频模式

您所做的一切都会通过硬件立即显示在屏幕上。这与 Linux 上的 ncurses 库不同,在 Linux 上,一切都通过终端仿真显示。在 DOS 上,一切都在硬件上运行。这意味着 DOS conio 程序可以轻松访问视频模式,并以使用 Linux ncurses 难以实现的方式利用屏幕区域。

首先,您需要设置视频模式。在 OpenWatcom 上,您可以使用 _setvideomode 函数执行此操作。此函数采用几个可能的值之一,但对于大多数在标准 80x25 屏幕的彩色模式下运行的程序,请使用 _TEXTC80 作为模式。

#include <conio.h>
#include <graph.h>

int
main()
{
  _setvideomode(_TEXTC80);
  … 

当您完成程序并准备退出返回 DOS 时,您应该将视频模式重置回之前的任何值。为此,您可以使用 _DEFAULTMODE 作为模式。

 _setvideomode(_DEFAULTMODE);
  return 0;
}

设置颜色

1981 年彩色/图形适配器之后构建的每台 PC 都支持16 种文本颜色和 8 种背景颜色。背景颜色使用颜色索引 0 到 7 进行寻址,文本颜色可以是 0 到 15 之间的任何值

  0 黑色   8 亮黑色
  1 蓝色   9 亮蓝色
  2 绿色   10 亮绿色
  3 青色   11 亮青色
  4 红色   12 亮红色
  5 洋红色   13 亮洋红色
  6 棕色   14 黄色
  7 白色   15 亮白色

您可以同时设置文本颜色和其后面的颜色。使用 _settextcolor 函数设置文本“前景色”,使用 _setbkcolor 设置文本“背景色”。例如,要将颜色设置为红色背景上的黄色文本,您可以使用这对函数

 _settextcolor(14);
 _setbkcolor(4);

定位文本

conio 中,屏幕坐标始终为,并从左上角的 1,1 开始。对于标准的 80 列 25 行显示器,右下角为 25,80。

使用 _settextposition 函数将光标移动到特定的屏幕坐标,然后使用 _outtext 打印要显示的文本。如果您已设置颜色,则您的文本将使用您上次定义的颜色,而与屏幕上已有的内容无关。

例如,要在第 12 行和第 36 列(或多或少位于屏幕中心)打印文本“FreeDOS”,请使用以下两个函数

  _settextposition(12, 36);
  _outtext("FreeDOS");

这是一个小的示例程序

#include <conio.h>
#include <graph.h>

int
main()
{
    _setvideomode(_TEXTC80);

    _settextcolor(14);
    _setbkcolor(4);

    _settextposition(12, 36);
    _outtext("FreeDOS");

    getch();

    _setvideomode(_DEFAULTMODE);

    return 0;
}

编译并运行该程序以查看此输出

Print to the screen with conio

CC BY-SA Jim Hall

文本窗口

释放 conio 威力的诀窍是利用 PC 视频显示器的一个功能,即程序可以通过区域控制视频硬件。这些称为文本窗口,是 conio 的一个非常酷的功能。

文本窗口只是屏幕的一个区域,定义为一个矩形,从特定的开始,到不同的结束。这些区域可以占据整个屏幕,也可以小到单行。定义窗口后,您可以使用背景色清除它并在其中定位文本。

要定义一个文本窗口,从第 5 行第 10 列开始,延伸到第 15 行第 70 列,您可以使用 _settextwindow 函数,如下所示

  _settextwindow(5, 10, 15, 70);

现在您已经定义了窗口,您在其中绘制的任何文本都使用 1,1 作为文本窗口的左上角。将文本放置在 1,1 实际上会将文本放置在第 5 行第 10 列,即窗口在屏幕上开始的位置。

您也可以使用背景色清除窗口。_clearscreen 函数兼具双重职责,可以清除整个屏幕或仅清除当前定义的窗口。要清除整个屏幕,请为该函数提供值 _GCLEARSCREEN。要仅清除窗口,请使用 _GWINDOW。无论使用哪种方式,您都将使用您上次设置的任何背景色填充该区域。例如,要用青色(颜色 3)清除整个屏幕,并用蓝色(颜色 1)清除较小的文本窗口,您可以使用以下代码

  _setbkcolor(3);
  _clearscreen(_GCLEARSCREEN);
  _settextwindow(5, 10, 15, 70);
  _setbkcolor(1);
  _clearscreen(_GWINDOW);

这使得填充屏幕的某些区域变得非常容易。事实上,定义窗口并用颜色填充它是如此常见的事情,以至于我经常创建一个函数来一次完成这两项操作。我的许多 conio 程序都包含这些用于清除屏幕或窗口的函数的某些变体

#include <conio.h>
#include <graph.h>

void
clear_color(int fg, int bg)
{
  _settextcolor(fg);
  _setbkcolor(bg);
  _clearscreen(_GCLEARSCREEN);
}

void
textwindow_color(int top, int left, int bottom, int right, int fg, int bg)
{
  _settextwindow(top, left, bottom, right);
  _settextcolor(fg);
  _setbkcolor(bg);
  _clearscreen(_GWINDOW);
}

文本窗口可以是任何大小,甚至是一行。这对于在屏幕顶部定义标题栏或在屏幕底部定义状态行非常方便。同样,我发现这对我程序来说是一个非常有用的补充,以至于我经常编写函数来为我完成它

#include <conio.h>
#include <graph.h>

#include <string.h>                    /* for strlen */

void
clear_color(int fg, int bg)
{
  … 
}

void
textwindow_color(int top, int left, int bottom, int right, int fg, int bg)
{
  … 
}

void
print_header(int fg, int bg, const char *text)
{
  textwindow_color(1, 1, 1, 80, fg, bg);

  _settextposition(1, 40 - (strlen(text) / 2));
  _outtext(text);
}

void
print_status(int fg, int bg, const char *text)
{
  textwindow_color(25, 1, 25, 80, fg, bg);

  _settextposition(1, 1);
  _outtext(text);
}

将它们放在一起

通过对 conio 的介绍以及我们上面定义的一组函数,您可以创建几乎任何程序的轮廓。让我们编写一个快速示例,演示文本窗口如何与 conio 一起工作。我们将用颜色清除屏幕,然后在第二行打印一些示例文本。这样就留出了在屏幕顶部放置标题行的空间。我们还将在屏幕底部打印状态行。

这是许多类型应用程序的基础。如果您正在编写“监视器”程序(例如控制系统的一部分),则将文本窗口放置在屏幕右侧可能很有用,如下所示

#include <conio.h>
#include <graph.h>

int
main()
{
  _setvideomode(_TEXTC80);

  clear_color(7, 1);                   /* white on blue */
  _settextposition(2, 1);
  _outtext("test");

  print_header(0, 7, "MONITOR");       /* black on white */

  textwindow_color(3, 60, 23, 79, 15, 3);       /* br white on cyan */
  _settextposition(3, 2);
  _outtext("hi mom");

  print_status(0, 7, "press any key to quit...");       /* black on white */
  getch();

  _setvideomode(_DEFAULTMODE);

  return 0;
}

由于已经编写了自己的窗口函数来完成大部分重复性工作,因此该程序变得非常简单:用蓝色背景清除屏幕,然后在第二行打印“test”。有一个标题行和一个状态行,但有趣的部分在中间,程序在屏幕右边缘附近定义了一个文本窗口并打印了一些示例文本。getch() 函数等待用户按下键盘上的某个键,当您需要等待直到用户准备就绪时,它非常有用

Conio mon

Conio 监视器

我们只需更改几个值即可完全更改此程序的外观和功能。通过将背景设置为绿色,白色窗口上的红色文本,我们就有了纸牌接龙游戏的开始

#include <conio.h>
#include <graph.h>

int
main()
{
  _setvideomode(_TEXTC80);

  clear_color(7, 2);                   /* white on green */
  _settextposition(2, 1);
  _outtext("test");

  print_header(14, 4, "SOLITAIRE");    /* br yellow on red */

  textwindow_color(10, 10, 17, 22, 4, 7);       /* red on white */
  _settextposition(3, 2);
  _outtext("hi mom");

  print_status(7, 6, "press any key to quit...");       /* white on brown */
  getch();

  _setvideomode(_DEFAULTMODE);

  return 0;
}

您可以向此示例程序添加其他代码,以打印牌值和花色、将牌放在其他牌的顶部以及其他功能,以创建完整的游戏。但对于此演示,我们将只绘制一张“卡片”,显示一些文本

Conio solitaire

Conio 纸牌接龙

您可以使用文本窗口创建其他效果。例如,在绘制消息窗口之前,您可以先绘制一个黑色窗口,该窗口偏移一行和一列。文本窗口将显示为在屏幕的该区域上创建阴影给用户。我们可以通过仅更改示例程序中的几个值来完成所有操作

#include <conio.h>
#include <graph.h>

int
main()
{
  _setvideomode(_TEXTC80);

  clear_color(7, 1);                   /* white on blue */
  _settextposition(2, 1);
  _outtext("test");

  print_header(15, 3, "PROGRAMMING IN CONIO");  /* br white on cyan */

  textwindow_color(11, 36, 16, 46, 7, 0);       /* shadow */
  textwindow_color(10, 35, 15, 45, 7, 4);       /* white on red */
  _settextposition(3, 2);
  _outtext("hi mom");

  print_status(0, 7, "press any key to quit...");       /* black on white */
  getch();

  _setvideomode(_DEFAULTMODE);

  return 0;
}

您经常在 DOS 程序中看到这种“阴影”效果,作为增加一些视觉效果的一种方式

Conio Window with shadow

带阴影的 Conio 窗口

DOS conio 函数的功能远不止我在此处展示的这些,但是通过对 conio 编程的介绍,您可以创建各种实用且令人兴奋的应用程序。直接屏幕访问意味着您的程序可以比从屏幕底部滚动文本的简单命令行实用程序更具交互性。利用 conio 编程的灵活性,让您的下一个 DOS 程序成为一个出色的程序。

下载 conio 速查表

当您探索 conio 编程时,手头有一份常用函数列表会很有帮助。我创建了一个双面速查表,其中包含 conio 的所有基础知识,因此下载它并在您的下一个 conio 项目中使用它。

 

接下来阅读什么
标签
photo of Jim Hall
Jim Hall 是一位开源软件倡导者和开发者,以 GNOME 的可用性测试以及作为 FreeDOS 的创始人 + 项目协调员而闻名。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.