coniow.h вместо conio.h
Проблема с несовместимыми conio.h
до сих пор часто всплывает при
адаптации старых программ под Studio, применил вчера-сегодня вполне простое и адекватное решение.
Взять вот отсюда оба файла, включить в проект, заинклудить
#include "coniow.h"
вместо
#include <conio.h>
Конечно, рамочек из псевдографики в Юникодовском проекте не будет, придётся заменить на "*
", к примеру. Ну и вставку asm {}
, не работающую в Studio, убрать.
Для корректного отображения русских букв при выполнении программы нужно щелкнуть правой кнопкой мыши по заголовку консольного окна, в контекстом меню выбрать пункт "Свойства" и установить шрифт "Lucida Console" и желаемый размер шрифта. Далее нажать кнопку OK. В XP возникает диалог с 2-мя вариантами - нужно сохранить настройки для всех окон с тем же именем, чтобы не выполнять эту настройку повторно.
Также убедитесь, что файл действительно сохранён в Юникоде (UTF-8, кодовая страница 65001).
Ну и все возможные варианты русификации консоли тоже подключены :) В сумме, вот такой "борландовский консольный интерфейс" условно работает, исходник:
#include <stdio.h> #include <stdlib.h> #include <dos.h> #include <windows.h> #include <locale.h> #include "coniow.h" typedef void (* FUN) (void); //Указатель на функцию void функция(void) - они будут выполнять пункты меню typedef struct ITEM { //Структура для элемента меню int x,y; //Столбец и строка консоли, куда выводим строку меню char *str; //Наименование пункта меню FUN f; //Функция, привязанная к пункту меню }; typedef struct WINDOW { //Окно вывода для всех функций int x1,y1,x2,y2,back,color; //Координаты двух углов, фоновый цвет, цвет вывода }; void Exit () { //Восстановить консоль по умолчанию и выйти window (1,1,80,25); textbackground(BLACK); textcolor(LIGHTGRAY); clrscr(); exit(0); } void flush () { //Очистить буфер клавиатуры fflush(stdin); } void DrawWindow (WINDOW w) { //Нарисовать окно w char c[]={'+','=','+','!','!','+','=','+'}; window (1,1,80,25); textbackground(w.back); textcolor(w.color); gotoxy (w.x1-1,w.y1-1); cprintf ("%c",c[0]); for (int i=w.x1; i<=w.x2; i++) cprintf ("%c",c[1]); cprintf ("%c",c[2]); for (int j=w.y1; j<=w.y2; j++) { gotoxy (w.x1-1,j); cprintf ("%c",c[3]); for (int i=w.x1; i<=w.x2; i++) cprintf (" "); cprintf ("%c",c[4]); } gotoxy (w.x1-1,w.y2+1); cprintf ("%c",c[5]); for (int i=w.x1; i<=w.x2; i++) cprintf ("%c",c[6]); cprintf ("%c",c[7]); } void DrawMenu (int n,ITEM *m,WINDOW w) { //Управление меню int sel=0,back=WHITE,inactivecolor=DARKGRAY,activecolor=RED; DrawWindow (w); //Нарисовать окно textbackground(back); //Поставить цвет фона меню for (int i=0; i<n; i++) { //Вывести меню gotoxy(m[i].x,m[i].y); textcolor(inactivecolor); cprintf ("%s",m[i].str); } while (1) { //Бесконечный цикл обработки нажатий клавиш gotoxy(m[sel].x,m[sel].y); textcolor(activecolor); cprintf ("%s",m[sel].str); //Перепечатать активный пункт выделенным цветом flush(); //очистить буфер клавиатуры int ch=getch(); //Жд)м нажатия клавиши gotoxy(m[sel].x,m[sel].y); //Сбросили цвет активного пункта textcolor(inactivecolor); cprintf ("%s",m[sel].str); if (!ch) { //Это расширенный код? ch=getch(); //Прочитать его switch(ch) { //Обработка расширенных кодов клавиш case 72: case 75: if (sel) sel--; else sel=n-1; break; //Стрелки вверх и влево case 80: case 77: if (sel<n-1) sel++; else sel=0; break; //Стрелки вниз и вправо } } else { //Обработка не-расширенных кодов клавиш switch(ch) { case 13: //Нажата Enter textbackground(w.back); //Поставить фон и цвет окна функций textcolor(w.color); window (w.x1,w.y1,w.x2,w.y2); //Выводить будем в окно функций m[sel].f(); //Вызов функции, закрепленной за пунктом меню clrscr(); //Убрать, если не очищаем окно после выхода из функции textbackground(back); //Восстановить фон и окно во весь экран window (1,1,80,25); break; case 27: Exit(); //По Esc всегда выход из приложения } } } } //Ниже начинается часть пользователя void File() { //Функция по меню File - пока ничего не делает long int i=0; //Печатать из функций лучше через cprintf while (!kbhit()) { delay (200); cprintf ("Работа функции File, шаг %ld\r\n",++i); } } void Do() { //Функция по меню Do - пока ничего не делает cprintf ("Введите целое число: "); int d; cscanf ("%d",&d); //Вводить из функций лучше через cscanf cprintf ("\r\nВы ввели значение %d\r\nНажмите клавишу для выхода...",d); getch(); getch(); } void main () { setlocale (LC_ALL,"Russian"); setlocale(LC_CTYPE, ".65001"); SetConsoleCP(65001); SetConsoleOutputCP(65001); //Пример для горизонтального меню ITEM menu1[3]={ //Описали меню {1,1,"File",File}, {6,1,"Do",Do}, {9,1,"Exit",Exit} }; WINDOW w={3,3,77,23,BLUE,YELLOW}; //Описали окно вывода функций clrscr(); DrawMenu (3,menu1,w); //Вызвали главную функцию системы /* //Пример для вертикального меню ITEM menu1[3]={ //Описали меню {2,2,"File",File}, {2,3,"Do",Do}, {2,4,"Exit",Exit} }; WINDOW w={8,2,78,24,BLUE,YELLOW}; //Описали окно вывода функций textbackground (WHITE); clrscr(); DrawMenu (3,menu1,w); //Вызвали главную функцию системы */ }
Оба файла в той версии, что использовал, архив .zip:
Скачать coniow.h и coniow.c в архиве .zip (6 Кб)
P.S. Чтобы заработало под Studio 2015, отличающийся более строгими требованиями к неуправляемому коду, пришлось сделать следующее:
- на всякий случай переименовал
coniow.c
вconiow.cpp
; - поставил первой строкой
coniow.cpp
директиву#define _NO_CRT_SECURE_WARNINGS
- в нескольких местах кода
coniow.cpp
заменилbuffer = malloc ( ...
на
buffer = (CHAR_INFO*)malloc (
т.е., выполнил явное приведение типа.
P.P.S. Прикреплённый ниже архив с coniow.c
и coniow.h
также работает в Visual Studio 2015, например, следующий исходник (main.cpp
из архива):
#define _CRT_SECURE_NO_WARNING #include <iostream> #include "coniow.h" using namespace std; int main() { textbackground(BLUE); textcolor(YELLOW); clrscr(); gotoxy(20 ,12); cprintf("Цветной экран как в старом Borland C++ :)"); cin.sync(); cin.get(); return 0; }
coniow.zip, внутри папка с тремя файлами (6 Кб)
12.04.2015, 16:24 [12972 просмотра]