14 Mar 2013

c/c++在控制台任意位置输出

收藏到CSDN网摘

C/C++中有时候需要在屏幕任意位置输出,这样可以在控制台输出定义好的形状,使用\b可以删除上一个字符,但是如果对于模拟LED这种情况就无能为力了,如果实在windows下,可以使用win32 API来设置光标位置解决.
模拟LED:


可以使用win32api来设置光标位置,核心代码:
#include <windows.h>
void gotoxy(int x, int y) // x,y坐标
{
   COORD coord = {x, y};
   SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

类似的,有一个获得光标位置的函数
void getxy(int *x, int *y)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    *x = (int)(csbi.dwCursorPosition.X);
    *y = (int)(csbi.dwCursorPosition.Y);
}

一个完整的例子:控制台LED显示数字
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
using namespace std;

void gotoxy(int x, int y)
{
   COORD coord = {x, y};
   SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

string codes[10][7] = {
    {   " --- ",    // 0
        "|   |",
        "|   |",
        "|   |",
        "|   |",
        "|   |",
        " --- "},
    {   "     ",    // 1
        "    |",
        "    |",
        "    |",
        "    |",
        "    |",
        "     "},
    {   " --- ",
        "    |",
        "    |",
        " --- ",
        "|    ",
        "|    ",
        " --- "},
    {   " --- ",
        "    |",
        "    |",
        " --- ",
        "    |",
        "    |",
        " --- "},
    {   "     ",
        "|   |",
        "|   |",
        " --- ",
        "    |",
        "    |",
        "     "},
    {   " --- ",
        "|    ",
        "|    ",
        " --- ",
        "    |",
        "    |",
        " --- "},
    {   " --- ",
        "|    ",
        "|    ",
        " --- ",
        "|   |",
        "|   |",
        " --- "},
    {   " --- ",
        "    |",
        "    |",
        "    |",
        "    |",
        "    |",
        "     "},
    {   " --- ",
        "|   |",
        "|   |",
        " --- ",
        "|   |",
        "|   |",
        " --- "},
    {   " --- ",
        "|   |",
        "|   |",
        " --- ",
        "    |",
        "    |",
        " --- "}};

void printNum(int prev, int start_y, const char &c)
{
    int x, y = start_y;
    x = prev*6; // prev_num+gap
    for (int i=0;i<7;i++) {
        gotoxy(x,y++);
        cout << codes[(int)(c-'0')][i];
    }
}

void LEDprint(int num, int start_y = 0)
{
    stringstream is;
    string nums;
    is << num;
    is >> nums;
    for (size_t i=0;i<nums.size();i++) printNum(i,start_y,nums[i]);
}

void LEDprint(string nums, int start_y = 0)
{
    for (size_t i=0;i<nums.size();i++) printNum(i,start_y,nums[i]);
}

int main()
{
    LEDprint(1234567890);
    LEDprint("0123456",7);
    return 0;
}

一个更复杂,更完整的例子
#include <windows.h>
#include <stdio.h>

void ConPrint(char *CharBuffer, int len);
void ConPrintAt(int x, int y, char *CharBuffer, int len);
void gotoXY(int x, int y);
void ClearConsole(void);
void ClearConsoleToColors(int ForgC, int BackC);
void SetColorAndBackground(int ForgC, int BackC);
void SetColor(int ForgC);
void HideTheCursor(void);
void ShowTheCursor(void);

int main(int argc, char* argv[])
{
   HideTheCursor();
   ClearConsoleToColors(15, 1);
   ClearConsole();
   gotoXY(1, 1);
   SetColor(14);
   printf("This is a test...\n");
   Sleep(500);
   ShowTheCursor();
   SetColorAndBackground(15, 12);
   ConPrint("This is also a test...\n", 23);
   SetColorAndBackground(1, 7);
   ConPrintAt(22, 15, "This is also a test...\n", 23);
   gotoXY(0, 24);
   SetColorAndBackground(7, 1);
   return 0;
}

//This will clear the console while setting the forground and
//background colors.
void ClearConsoleToColors(int ForgC, int BackC)
{
   WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
   //Get the handle to the current output buffer...
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   //This is used to reset the carat/cursor to the top left.
   COORD coord = {0, 0};
   //A return value... indicating how many chars were written
   //not used but we need to capture this since it will be
   //written anyway (passing NULL causes an access violation).
   DWORD count;

   //This is a structure containing all of the console info
   // it is used here to find the size of the console.
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   //Here we will set the current color
   SetConsoleTextAttribute(hStdOut, wColor);
   if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
   {
      //This fills the buffer with a given character (in this case 32=space).
      FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);

      FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      //This will set our cursor position for the next print statement.
      SetConsoleCursorPosition(hStdOut, coord);
   }
}

//This will clear the console.
void ClearConsole()
{
   //Get the handle to the current output buffer...
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   //This is used to reset the carat/cursor to the top left.
   COORD coord = {0, 0};
   //A return value... indicating how many chars were written
   //   not used but we need to capture this since it will be
   //   written anyway (passing NULL causes an access violation).
   DWORD count;
   //This is a structure containing all of the console info
   // it is used here to find the size of the console.
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   //Here we will set the current color
   if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
   {
      //This fills the buffer with a given character (in this case 32=space).
      FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      //This will set our cursor position for the next print statement.
      SetConsoleCursorPosition(hStdOut, coord);
   }
}

//This will set the position of the cursor
void gotoXY(int x, int y)
{
   //Initialize the coordinates
   COORD coord = {x, y};
   //Set the position
   SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

//This will set the forground color for printing in a console window.
void SetColor(int ForgC)
{
   WORD wColor;
   //We will need this handle to get the current background attribute
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   CONSOLE_SCREEN_BUFFER_INFO csbi;

   //We use csbi for the wAttributes word.
   if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
   {
      //Mask out all but the background attribute, and add in the forgournd color
      wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
      SetConsoleTextAttribute(hStdOut, wColor);
   }
}

//This will set the forground and background color for printing in a console window.
void SetColorAndBackground(int ForgC, int BackC)
{
   WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
}

//Direct console output
void ConPrint(char *CharBuffer, int len)
{
   DWORD count;
   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), CharBuffer, len, &count, NULL);
}

//Direct Console output at a particular coordinate.
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
   DWORD count;
   COORD coord = {x, y};
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleCursorPosition(hStdOut, coord);
   WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
}

//Hides the console cursor
void HideTheCursor()
{
   CONSOLE_CURSOR_INFO cciCursor;
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

   if(GetConsoleCursorInfo(hStdOut, &cciCursor))
   {
      cciCursor.bVisible = FALSE;
   }
}

//Shows the console cursor
void ShowTheCursor()
{
   CONSOLE_CURSOR_INFO cciCursor;
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

   if(GetConsoleCursorInfo(hStdOut, &cciCursor))
   {
      cciCursor.bVisible = TRUE;
   }
}

No comments :

Post a Comment