【问题标题】:Create window console inside main win32 window在主 win32 窗口内创建窗口控制台
【发布时间】:2011-07-01 09:40:07
【问题描述】:

我有一个 win32 应用程序,当按下波浪号时,它需要像游戏一样打开控制台。我认为最好的解决方案是使用 CreateWindow 函数。这是正确的吗?当再次按下波浪号时,如何使其与主窗口重叠并隐藏它?谢谢大家

【问题讨论】:

    标签: c++ winapi console


    【解决方案1】:

    这是一些相当古老的代码,甚至还没有真正看过它。希望这是你需要的。如果你只需要一个非常简单的,你也可以调用 AllocConsole();

    void DevConsole::Create(){
    
      CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
      int consoleHandleR, consoleHandleW ;
      long stdioHandle;
      FILE *fptr;
    
      AllocConsole();
      std::wstring strW = L"Dev Console";
      SetConsoleTitle( strW.c_str() );
    
      EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE , MF_GRAYED);
      DrawMenuBar(GetConsoleWindow());
    
      GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo );
    
      stdioHandle = (long)GetStdHandle( STD_INPUT_HANDLE );
      consoleHandleR = _open_osfhandle( stdioHandle, _O_TEXT );
      fptr = _fdopen( consoleHandleR, "r" );
      *stdin = *fptr;
      setvbuf( stdin, NULL, _IONBF, 0 );
    
      stdioHandle = (long) GetStdHandle( STD_OUTPUT_HANDLE );
      consoleHandleW = _open_osfhandle( stdioHandle, _O_TEXT );
      fptr = _fdopen( consoleHandleW, "w" );
      *stdout = *fptr;
      setvbuf( stdout, NULL, _IONBF, 0 );
    
      stdioHandle = (long)GetStdHandle( STD_ERROR_HANDLE );
      *stderr = *fptr;
      setvbuf( stderr, NULL, _IONBF, 0 );
    
    }
    

    【讨论】:

    【解决方案2】:

    在您的应用程序中使用控制台窗口通常很诱人(使用 AllocConsole),但它绝对不是标准的可重用 Windows 控件。它具有许多特殊的行为和功能,使其不同于典型的窗口。

    因此,我同意您的直觉,反对使用真正的“控制台”窗口。制作您自己的带有文本编辑器的窗口,就像您开发任何其他 UI 组件(如 HUD)一样。

    您是否应该使用CreateWindow 很难说:您的GUI 的其余部分如何处理?直连? GDI?一些工具包?您是否在使用其他标准 Windows 控件?

    【讨论】:

    • 我正在使用 DirectX 来绘制一些 3D 对象,所以也许我可以使用精灵,但我怎么能绘制一个矩形呢?我知道我需要两个三角形,但我不明白如何把它们画成一个矩形
    • 我认为最简单的解决方案——即使你使用 DirectX——是使用CreateWindowCreateDialog,显示一个带有只读编辑控件的窗口,以及一个用于键入命令的单行编辑控件。这样您就可以使用所有内置控件。如果在 DirectX 中进行,则需要控件库的支持(在 DirectX 中从头开始制作文本编辑控件并不好)。
    • @tenfour 我认为保留一个单独的控制台主要用于日志记录应该没问题。我见过很多应用程序这样做。
    【解决方案3】:

    我发现这个小教程/代码示例很有用。 http://www.halcyon.com/~ast/dload/guicon.htm

    它创建一个控制台并将 STD_IN 和 STD_OUT 重定向到控制台。 因此您可以轻松使用 std::cin 和 std::cout 等流。

    【讨论】:

      【解决方案4】:

      这里的解决方案不起作用,因为较新版本的 Windows SDK 通过以下方式定义 FILE 结构:

      #ifndef _FILE_DEFINED
          #define _FILE_DEFINED
          typedef struct _iobuf
          {
              void* _Placeholder;
          } FILE;
      #endif
      

      当试图用 = 操作符覆盖标准输入/输出文件结构时,只会复制一个指针。要复制整个 FILE 结构,您必须在 windows.h 包含之前定义 FILE 结构:

      #ifndef _FILE_DEFINED
      struct _iobuf {
              char *_ptr;
              int   _cnt;
              char *_base;
              int   _flag;
              int   _file;
              int   _charbuf;
              int   _bufsiz;
              char *_tmpfname;
              };
      typedef struct _iobuf FILE;
      #define _FILE_DEFINED
      #endif
      
      #include <Windows.h>
      

      如果您无法做到这一点,您仍然可以将自己的 FILE 结构定义为 FILE_COMPLETE 并使用此代码n-p:

      #include <Windows.h>
      #include <io.h>
      #include <fcntl.h>
      
      AllocConsole();
      SetConsoleTitleA("ConsoleTitle");
      typedef struct { char* _ptr; int _cnt; char* _base; int _flag; int _file; int _charbuf; int _bufsiz; char* _tmpfname; } FILE_COMPLETE;
      *(FILE_COMPLETE*)stdout = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT), "w");
      *(FILE_COMPLETE*)stderr = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w");
      *(FILE_COMPLETE*)stdin = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r");
      setvbuf(stdout, NULL, _IONBF, 0);
      setvbuf(stderr, NULL, _IONBF, 0);
      setvbuf(stdin, NULL, _IONBF, 0);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-11
        • 1970-01-01
        • 2010-09-08
        • 1970-01-01
        • 2011-03-18
        • 1970-01-01
        • 2013-06-30
        相关资源
        最近更新 更多