在Win32控制台应用程序中设置光标位置

20
我如何在Win32控制台应用程序中设置光标位置?最好避免创建句柄并使用Windows控制台功能。(我整个早上都在探索这条黑暗小巷;它会带来更多问题而不是解决问题。)我似乎在大学时使用stdio相对简单地完成了这个任务,但现在找不到任何示例。有什么想法或建议将不胜感激。谢谢。
其他细节: 以下是我现在正在尝试的内容:
COORD pos = {x, y};
HANDLE hConsole_c = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL );
char * str = "Some Text\r\n";
DWDORD len = strlen(str);

SetConsoleCursorPosition(hConsole_c, pos);
WriteConsole(hConsole_c, str, len, &dwBytesWritten, NULL);
CloseHandle(hConsole_c)

文本字符串str永远不会被发送到屏幕上,是否还有其他需要做的事情?谢谢。


好问题,这就是我在这篇文章中的原因。在没有图形卡的个人电脑(XT、AT和386)上,即使作为一名高中学生,使用Turbo Pascal很容易完成这项任务。我能够创建一个界面,用于输入虚构的票务预订系统的详细信息......并且得到了A+的好成绩。为什么现在变得如此困难呢? - Michael Stimson
5个回答

17
使用控制台函数,您可以使用 SetConsoleCursorPosition。如果没有它们(或者至少不是直接使用它们),您可以在ncurses库中使用类似于gotoxy的东西。
编辑:对它的包装器非常简单。
// Untested, but simple enough it should at least be close to reality...
void gotoxy(int x, int y) { 
    COORD pos = {x, y};
    HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(output, pos);
}

“gotoxy”是我想到的,但我发现即使使用“SetConsoleCursorPosition”API正确设置了光标位置,但当我尝试使用“printf”将文本发送到控制台时,文本会输出到调用API之前光标所在的位置。 - Jim Fell
@Jim:知道是哪个编译器做的会很有趣。我已经用微软的编译器使用了类似这样的代码多年,从未见过您描述的行为。 - Jerry Coffin
请查看我添加到问题中的附加细节。谢谢。 - Jim Fell
@Jim:你正在创建并写入屏幕缓冲区(基本上只是一块内存块),但没有写入控制台本身,或将你创建的屏幕缓冲区与控制台关联。 - Jerry Coffin
Jerry,感谢你的建议。最终我编写了一个包装类来处理所有控制台操作。 - Jim Fell

15

请参考SetConsoleCursorPosition API。

编辑:

使用WriteConsoleOutputCharacter()函数,该函数接受控制台中活动缓冲区的句柄,并允许您设置其位置。

int x = 5; int y = 6;
COORD pos = {x, y};
HANDLE hConsole_c = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole_c);
char *str = "Some Text\r\n";
DWORD len = strlen(str);
DWORD dwBytesWritten = 0;
WriteConsoleOutputCharacter(hConsole_c, str, len, pos, &dwBytesWritten);
CloseHandle(hConsole_c);

“SetConsoleCursorPosition” 是一个 Windows 控制台函数,我已经表明我不想使用它。 - Jim Fell
所以,最后我选择了Hans的建议,使用GetStdHandle(STD_OUTPUT_HANDLE)来获取现有控制台的句柄,但结果发现我还需要使用WriteConsoleOutputCharacter()。我不知道为什么这个调用起作用,但现在它正常工作了。谢谢! - Jim Fell

4

是的,你忘记调用SetConsoleActiveScreenBuffer了。创建自己的屏幕缓冲区有什么意义呢?使用GetStdHandle(STD_OUTPUT_HANDLE)来获取现有控制台的句柄。


1
#include <windows.h>
#include <iostream.h>
using namespace std;
int main(int argc, char *argv[])
{
  int x,y;
  cin>>x>>y;
  SetCursorPos(x,y); //set your co-ordinate
  Sleep(500);
  mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0); // moving cursor leftdown
  mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0); // moving cursor leftup //for accessing your required co-ordinate
  system("pause");
  return EXIT_SUCCESS;
}

需要更多信息。SetCursorPos没有任何方法可用。 - Gavin Williams
1
@GavinWilliams 这个方法在win 7中存在,不确定win 10是否也有。 - udit043

1
你可能正在使用 ANSI转义代码序列,它们无法与Windows 32位控制台应用程序一起使用。

嗯,那是一个可能性。谢谢。 - Jim Fell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接