Предлагать пользователю окно ввода?[C ++] - PullRequest
12 голосов
/ 17 ноября 2010

Моя цель - просто использовать всплывающее окно, чтобы попросить пользователя ввести данные. Я довольно долго искал, и почти все результаты говорят о том, что создание MessageBox действительно просто:

MessageBox (NULL, "Hello World" , "Hello", MB_OKCANCEL);

Но создание всплывающего окна, требующего ввода, более сложное, и прямого способа сделать это не существует. Все результаты, которые я смог найти в Google, были датированы где-то с 2001 по 2005 год. Думаю, я здесь спрашиваю, появилось ли какое-то более прямолинейное решение в последние годы.

Надеюсь, что-то приятное и прямолинейное, как в Java:

int number = JOptionPane.showInputDialog ("Enter an integer");

Если это не так, могу я получить краткое объяснение, как это сделать?


Редактировать: Я ничего не мог заставить работать. :( Я закончил писать код для работы на Java, а затем написал одну строчку кода C ++ для вызова файла .jar.: - / Так как проблема чувствительна ко времени, это было лучше, чем ничего.

Ответы [ 8 ]

7 голосов
/ 17 ноября 2010

Если вы используете Visual C ++ Express, существует ряд бесплатных редакторов ресурсов, которые можно использовать для создания диалогов. ResEdit - один из лучших, которые я нашел.

Вам необходимо создать диалоговый ресурс в файле .RC, который вы добавите в свой проект.

Затем, Это очень простой случай вызова DialogBox - который загрузит диалоговое окно из файла ресурсов и поместит его на экран.Переданный в DialogProc будет вызываться с рядом уведомлений.Как правило, вы захотите вернуть FALSE для всего, но обработайте WM_INITDIALOG как место для инициализации элемента управления редактирования текстом, и WM_COMMAND будет отправлено при нажатии кнопки.

7 голосов
/ 17 ноября 2010

Ничего подобного нет для чистого C ++. По сути, то, что вы пытаетесь сделать, может быть достигнуто только с помощью API-вызова к ОС или с помощью некоторой библиотеки GUI, такой как Qt (которую я рекомендую, потому что она намного проще, чем вызов нативных API, и она также мультиплатформенная)

Используя Qt, вы можете отобразить диалог ввода почти так же, как вы делаете это на Java:

bool ok;
QString text = QInputDialog::getText(
        "MyApp 3000", "Enter your name:", QLineEdit::Normal,
        QString::null, &ok, this );
if ( ok && !text.isEmpty() ) {
    // user entered something and pressed OK
} else {
    // user entered nothing or pressed Cancel
}

Вы можете скачать библиотеку Qt здесь: qt.nokia.com / products / developer-tools /

3 голосов
/ 17 ноября 2010

Microsoft не считает ваш вариант использования достаточно распространенным для оптимизации, как в случае MessageBox.Они ожидают, что вы создадите диалоговое окно со многими элементами управления, возможно, с некоторым сложным взаимодействием с элементами управления, и ответите только после того, как диалоговое окно полностью заполнено. То, что вы запрашиваете, - это просто упрощенная версия этого.

Редактор ресурсов - это самый простой способ создания диалога, но он не включен в бесплатную экспресс-версию Visual Studio.Вы бы разработали диалоговое окно с текстовым элементом управления для приглашения и элементом редактирования для заполнения пользователем. Вы предоставляете диалоговое окно с функцией Windows DialogBox, и оно возвращается, когда пользователь нажимает кнопку OK или X вугол диалога.У Microsoft есть некоторая документация для этого здесь .

Существует несколько платформ, которые пытаются упростить этот процесс, таких как MFC, WTL, Qt и wx, но именно так высделал бы это с чистым Windows API.

1 голос
/ 15 октября 2018

Мой ответ основан на ответе Стивена Куана на Как загрузить и вызвать функцию VBScript из C ++? Добавлена ​​полная поддержка UTF-8, которую можно получить из комментариев кода в файле CPP. В отличие от использования Microsoft Script Control для создания InputBox, его можно использовать в исполняемых файлах, библиотеках и элементах управления x86 и x64.

"inputbox.h":

extern "C" char *InputBox(char *Prompt, char *Title = (char *)"", char *Default = (char *)"");
extern "C" char *PasswordBox(char *Prompt, char *Title = (char *)"", char *Default = (char *)"");

"inputbox.cpp":

#include "inputbox.h"

// Windows API
#include <windows.h>

// VBScript InputBox
#include <atlbase.h>
#include <activscp.h>
#include <comdef.h>

// UTF-8 Support
#include <wchar.h>
#include <string>
#include <vector>

using std::string;
using std::vector;

typedef std::basic_string<wchar_t> tstring;

static tstring StringWiden(string Str)
{
    const size_t wchar_tCount = Str.size() + 1;

    vector<wchar_t> Buffer(wchar_tCount);

    return tstring{ Buffer.data(), (size_t)MultiByteToWideChar(CP_UTF8, 0, Str.c_str(), -1, Buffer.data(), wchar_tCount) };
}

static string StringShorten(tstring Str)
{
    int nBytes = (size_t)WideCharToMultiByte(CP_UTF8, 0, Str.c_str(), (int)Str.length(), NULL, 0, NULL, NULL);

    vector<char> Buffer((size_t)nBytes);

    return string{ Buffer.data(), (size_t)WideCharToMultiByte(CP_UTF8, 0, Str.c_str(), (int)Str.length(), Buffer.data(), nBytes, NULL, NULL) };
}

static string StringReplaceAll(string Str, string SubStr, string NewStr)
{
    size_t Position = 0;
    const size_t SubLen = SubStr.length(), NewLen = NewStr.length();

    while ((Position = Str.find(SubStr, Position)) != string::npos)
    {
        Str.replace(Position, SubLen, NewStr);
        Position += NewLen;
    }

    return Str;
}

static string CPPNewLineToVBSNewLine(string NewLine)
{
    size_t Position = 0;

    while (Position < NewLine.length())
    {
        if (NewLine[Position] == '\n' || NewLine[Position] == '\r')
            NewLine.replace(Position, 2, "\" + vbNewLine + \"");

        Position += 1;
    }

    return NewLine;
}

class CSimpleScriptSite :
    public IActiveScriptSite,
    public IActiveScriptSiteWindow
{
public:
    CSimpleScriptSite() : m_cRefCount(1), m_hWnd(NULL) { }

    // IUnknown

    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)();
    STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);

    // IActiveScriptSite

    STDMETHOD(GetLCID)(LCID *plcid) { *plcid = 0; return S_OK; }
    STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) { return TYPE_E_ELEMENTNOTFOUND; }
    STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) { *pbstrVersion = SysAllocString(L"1.0"); return S_OK; }
    STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) { return S_OK; }
    STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) { return S_OK; }
    STDMETHOD(OnScriptError)(IActiveScriptError *pIActiveScriptError) { return S_OK; }
    STDMETHOD(OnEnterScript)(void) { return S_OK; }
    STDMETHOD(OnLeaveScript)(void) { return S_OK; }

    // IActiveScriptSiteWindow

    STDMETHOD(GetWindow)(HWND *phWnd) { *phWnd = m_hWnd; return S_OK; }
    STDMETHOD(EnableModeless)(BOOL fEnable) { return S_OK; }

    // Miscellaneous

    STDMETHOD(SetWindow)(HWND hWnd) { m_hWnd = hWnd; return S_OK; }

public:
    LONG m_cRefCount;
    HWND m_hWnd;
};

STDMETHODIMP_(ULONG) CSimpleScriptSite::AddRef()
{
    return InterlockedIncrement(&m_cRefCount);
}

STDMETHODIMP_(ULONG) CSimpleScriptSite::Release()
{
    if (!InterlockedDecrement(&m_cRefCount))
    {
        delete this;
        return 0;
    }
    return m_cRefCount;
}

STDMETHODIMP CSimpleScriptSite::QueryInterface(REFIID riid, void **ppvObject)
{
    if (riid == IID_IUnknown || riid == IID_IActiveScriptSiteWindow)
    {
        *ppvObject = (IActiveScriptSiteWindow *)this;
        AddRef();
        return NOERROR;
    }
    if (riid == IID_IActiveScriptSite)
    {
        *ppvObject = (IActiveScriptSite *)this;
        AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

static HHOOK hHook = 0;
static bool HideInput = false;

static LRESULT CALLBACK InputBoxProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode < HC_ACTION)
        return CallNextHookEx(hHook, nCode, wParam, lParam);

    if (nCode = HCBT_ACTIVATE)
    {
        if (HideInput == true)
        {
            HWND TextBox = FindWindowExA((HWND)wParam, NULL, "Edit", NULL);
            SendDlgItemMessage((HWND)wParam, GetDlgCtrlID(TextBox), EM_SETPASSWORDCHAR, '*', 0);
        }
    }

    if (nCode = HCBT_CREATEWND)
    {
        if (!(GetWindowLongPtr((HWND)wParam, GWL_STYLE) & WS_CHILD))
            SetWindowLongPtr((HWND)wParam, GWL_EXSTYLE, GetWindowLongPtr((HWND)wParam, GWL_EXSTYLE) | WS_EX_DLGMODALFRAME);
    }

    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

static char *InputBoxHelper(char *Prompt, char *Title, char *Default)
{
    HRESULT hr = S_OK;
    hr = CoInitialize(NULL);

    // Initialize
    CSimpleScriptSite *pScriptSite = new CSimpleScriptSite();
    CComPtr<IActiveScript> spVBScript;
    CComPtr<IActiveScriptParse> spVBScriptParse;
    hr = spVBScript.CoCreateInstance(OLESTR("VBScript"));
    hr = spVBScript->SetScriptSite(pScriptSite);
    hr = spVBScript->QueryInterface(&spVBScriptParse);
    hr = spVBScriptParse->InitNew();

    // Replace quotes with double quotes
    string strPrompt = StringReplaceAll(Prompt, "\"", "\"\"");
    string strTitle = StringReplaceAll(Title, "\"", "\"\"");
    string strDefault = StringReplaceAll(Default, "\"", "\"\"");

    // Create evaluation string
    string Evaluation = "InputBox(\"" + strPrompt + "\", \"" + strTitle + "\", \"" + strDefault + "\")";
    Evaluation = CPPNewLineToVBSNewLine(Evaluation);
    tstring WideEval = StringWiden(Evaluation);

    // Run InpuBox
    CComVariant result;
    EXCEPINFO ei = {};

    DWORD ThreadID = GetCurrentThreadId();
    HINSTANCE ModHwnd = GetModuleHandle(NULL);
    hr = pScriptSite->SetWindow(GetAncestor(GetActiveWindow(), GA_ROOTOWNER));
    hHook = SetWindowsHookEx(WH_CBT, &InputBoxProc, ModHwnd, ThreadID);
    hr = spVBScriptParse->ParseScriptText(WideEval.c_str(), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &result, &ei);
    UnhookWindowsHookEx(hHook);


    // Cleanup
    spVBScriptParse = NULL;
    spVBScript = NULL;
    pScriptSite->Release();
    pScriptSite = NULL;

    CoUninitialize();
    static string strResult;
    _bstr_t bstrResult = (_bstr_t)result;
    strResult = StringShorten((wchar_t *)bstrResult);
    return (char *)strResult.c_str();
}

char *InputBox(char *Prompt, char *Title, char *Default)
{
    HideInput = false;

    return InputBoxHelper(Prompt, Title, Default);
}

char *PasswordBox(char *Prompt, char *Title, char *Default)
{
    HideInput = true;

    return InputBoxHelper(Prompt, Title, Default);
}

Создайте два вышеупомянутых файла и затем добавьте их в проект Visual Studio.

В любом файле, который вы хотите, чтобы функции ввода или поля ввода пароля (находились в заголовке), просто включите заголовок:

#include "inputbox.h"

// use functions here

Я также избавился от значка приложения Windows по умолчанию в строке заголовка VBScript InputBox, потому что многие люди, которых я видел, жалуются на то, как ужасно видеть их там.

Дайте мне знать, если у вас есть какие-либо вопросы.

1 голос
/ 17 ноября 2010

Я должен признать, что на протяжении многих лет я не особо много работал с полями ввода, но в основном вам нужно выйти за пределы C ++, чтобы получить какое-либо графическое поле ввода.Просто нет встроенного в язык механизма для такого рода вещей по причинам переносимости.Я не помню, применимо ли это к C ++, но C даже не предполагает, что у вас есть консоль.В любом случае, лучшим вариантом будет то, что вы уже пробовали: Win32 API, Qt и т. Д. Однако, если вы можете использовать консоль, не стесняйтесь просто использовать библиотеку iostream, чтобы выполнить работу.

0 голосов
/ 03 октября 2016

попробуйте это: InputBox в c ++ vs2010

#include "stdafx.h"
#using <system.windows.forms.dll>
#using <Microsoft.VisualBasic.dll>

using namespace System;

int main(array<System::String ^> ^args)
{
    Microsoft::VisualBasic::Interaction::InputBox(L"Hello", L"Title", L"DefResp", 500, 500);
    return 0;
}
0 голосов
/ 17 ноября 2010

Использование консольного окна лучше подходит для режима связи, в котором программа запрашивает пользователя, продолжает, снова запрашивает пользователя и т. Д.

И для этого вы можете использовать стандартные функции библиотеки, такие какcin и cout.

...