首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用命令行界面创建图形化工具?

如何使用命令行界面创建图形化工具?
EN

Stack Overflow用户
提问于 2011-02-25 12:41:41
回答 3查看 559关注 0票数 2

我正在构建一个工具,它既可以是图形化的,也可以是纯命令行界面的。由用户决定使用命令行选项“我的IDE是2008。

我似乎找不到合适的项目属性来确保

  1. 使用命令行接口模式时,将显示标准输出打印。
  2. 在图形化模式下使用该工具时,不会打开命令行框。

有办法吗?的devenv似乎是这样的,所以我非常肯定它是可以做到的!

EN

回答 3

Stack Overflow用户

发布于 2011-02-25 12:46:02

编辑:,我似乎已经回答了你的标题,但是在重新阅读你的问题时,我不确定这就是你要问的。我把答案留在这里,因为它可能对搜索你的标题有用。

是的,您可以这样做,但一般来说,视觉研究并不能很容易地将代码从gui中分离出来(特别是与hello示例非常绑定)。如果你想混合输入,那么你真的想确保这从一开始就做得很好。

我的建议是从命令行选项开始。如果允许您使用boost (出于许可原因),那么使用选项

一旦你做到了,你就可以在上面加上盖伊。此外,我建议使用gui库(如gtk++ ),因为它是跨平台的。

票数 1
EN

Stack Overflow用户

发布于 2011-02-25 12:48:19

将应用程序构建为Win32应用程序(而不是控制台应用程序),并检查参数以确定是否使用控制台窗口。

下面的代码是基于此

若要使用控制台,请创建名为CConsoleAttacher的类。使用它如下,基本上,如果有参数,那么打开一个控制台,如果您从它开始,它将连接到CMD窗口。显然,在Win32应用程序中,当您启动主窗口时,它会从控制台中分离出来,因此在创建应用程序窗口之前需要对此进行早期处理(这正是您想要做的.)

代码语言:javascript
复制
    CConsoleAttacher ca;
    if (ca.hasArguments())
    {
        ca.ConnectToConsole();
    }
    printf ("Test output \n");

创建一个名为CConsoleAttacher的类。

CConsoleAttacher.cpp

代码语言:javascript
复制
#include "StdAfx.h"

#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include "ConsoleAttacher.h"

#ifndef _USE_OLD_IOSTREAMS
using namespace std;
#endif
static const WORD MAX_CONSOLE_LINES = 500;

CConsoleAttacher::CConsoleAttacher(void)
{
    argv = CommandLineToArgvW(GetCommandLineW(), &argc);

}


CConsoleAttacher::~CConsoleAttacher(void)
{
    LocalFree(argv);
}


int CConsoleAttacher::getArgumentCount(void)
{
    return argc;
}


CString CConsoleAttacher::getArgument(int id)
{
    CString arg ;
    if (id < argc)
    {
        arg = argv[id];
    }
    return arg;
}

bool CConsoleAttacher::hasArguments(void)
{
    return argc > 1;
}

void CConsoleAttacher::ConnectToConsole(void)
{
    int hConHandle;
    HANDLE lStdHandle;
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    FILE *fp;

    // allocate a console for this app
    if (!AttachConsole(ATTACH_PARENT_PROCESS))
    {
        if (!AllocConsole())
            return;
    }

    // set the screen buffer to be big enough to let us scroll text
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
    coninfo.dwSize.Y = MAX_CONSOLE_LINES;

    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);

    // redirect unbuffered STDOUT to the console
    lStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );

    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );

    // redirect unbuffered STDIN to the console
    lStdHandle = GetStdHandle(STD_INPUT_HANDLE);
    hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "r" );

    *stdin = *fp;
    setvbuf( stdin, NULL, _IONBF, 0 );

    // redirect unbuffered STDERR to the console
    lStdHandle = GetStdHandle(STD_ERROR_HANDLE);
    hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );

    *stderr = *fp;
    setvbuf( stderr, NULL, _IONBF, 0 );

    // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    // point to console as well
    ios::sync_with_stdio();
}

CConsoleAttacher.h

代码语言:javascript
复制
#pragma once
class CConsoleAttacher
{
private:
    int argc;
    wchar_t** argv;

public:
    CConsoleAttacher(void);
    ~CConsoleAttacher(void);
    int getArgumentCount(void);
    CString CConsoleAttacher::getArgument(int id);
    void ConnectToConsole(void);
    bool hasArguments(void);
};
票数 1
EN

Stack Overflow用户

发布于 2011-02-25 13:55:57

这不是一件容易的事,IIRC。问题是,在Windows上,可执行文件本身有一个标志,无论它是GUI应用程序还是控制台应用程序,例如,cmd.exe在执行其中一个或另一个时的行为有所不同。我建议您将应用程序的核心功能划分为一个库,并构建独立的CLI和GUI前端。

编辑:如果你真的坚持,这对你的目标有很大的帮助。goto是由于历史原因而存在的,它现在可以被if取代:

代码语言:javascript
复制
static
bool
usable_handle (HANDLE h)
{
    return h && h != INVALID_HANDLE_VALUE;
}


static
bool
try_reopen_std_handle (int dest_handle, DWORD os_handle_num, HANDLE os_handle,
    int flags)
{
    if (! usable_handle (os_handle))
        return false;

    int ret = SetStdHandle (os_handle_num, os_handle);
    assert (ret);
    if (! ret)
        return false;

    int base_flags = 0;
#if defined (UNICODE)
    //base_flags = _O_WTEXT;
#endif

    int opened_handle = _open_osfhandle (reinterpret_cast<intptr_t>(os_handle),
        flags | base_flags);
    assert (opened_handle != -1 && "_open_osfhandle");
    if (opened_handle == -1)
        return false;

    int dupd_handle = _dup2 (opened_handle, dest_handle);
    assert (dupd_handle != -1 && "_dup2");

    return dupd_handle == 0;
}


static
bool
try_fdopen (FILE * f, int handle, char const * mode)
{
    FILE * tmp = _fdopen (handle, mode);
    if (tmp && f)
        *f = *tmp;
    return !! tmp;
}


static
HANDLE
try_dup_os_handle (HANDLE src)
{
    if (! usable_handle (src))
        return INVALID_HANDLE_VALUE;

    HANDLE dest = INVALID_HANDLE_VALUE;
    HANDLE const process = GetCurrentProcess ();
    if (DuplicateHandle (process, src, process, &dest, 0, TRUE,
        DUPLICATE_SAME_ACCESS))
        return dest;
    else
        return INVALID_HANDLE_VALUE;
}


static
void
init_std_io ()
{
    // Retrieve inherited standard handles. AttachConsole() will close
    // the existing standard handles, so we duplicate them here first
    // to keep them alive.

    HANDLE os_stdin = try_dup_os_handle (GetStdHandle (STD_INPUT_HANDLE));
    HANDLE os_stdout = try_dup_os_handle (GetStdHandle (STD_OUTPUT_HANDLE));
    HANDLE os_stderr = try_dup_os_handle (GetStdHandle (STD_ERROR_HANDLE));

    // Attach existing console or allocate a new one.

    int ret = AttachConsole (ATTACH_PARENT_PROCESS);
    if (ret)
        OutputDebugString (_T("Attached existing console.\n"));
    else
    {
        ret = AllocConsole ();
        if (ret)
            OutputDebugString (_T("Allocated new console.\n"));
        else
            OutputDebugString (_T("Failed to allocate new console.\n"));
        assert (ret);
    }

    // Open a "POSIX" handle for each OS handle and then fdopen() a C stream
    // for each such "POSIX" handle.
    //
    // Only use the standard handle provided by AttachConsole() if the standard
    // handle from before AttachConsole() is not usable.
    //
    // Finally, re-open standard C stream.

    if (! usable_handle (os_stdin))
        os_stdin = GetStdHandle (STD_INPUT_HANDLE);
    ret = try_reopen_std_handle (0, STD_INPUT_HANDLE, os_stdin, _O_RDONLY);
    if (! ret)
        goto do_stdout;
    try_fdopen (stdin, 0, "r");

do_stdout:
    if (! usable_handle (os_stdout))
        os_stdout = GetStdHandle (STD_OUTPUT_HANDLE);
    ret = try_reopen_std_handle (1, STD_OUTPUT_HANDLE, os_stdout, _O_WRONLY);
    if (! ret)
        goto do_stderr;
    try_fdopen (stdout, 1, "w");

do_stderr:
    if (! usable_handle (os_stderr))
        os_stderr = GetStdHandle (STD_ERROR_HANDLE);
    ret = try_reopen_std_handle (2, STD_ERROR_HANDLE, os_stderr, _O_WRONLY);
    if (! ret)
        goto done_stderr;
    try_fdopen (stderr, 2, "w");

done_stderr:;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5117338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档