Вызов пользователя с полем ввода? [С++]
Моя цель - просто использовать всплывающее окно, чтобы спросить пользователя о вводе. Я искал вокруг совсем немного, и почти все результаты говорят о том, что создание messageBox очень просто:
MessageBox (NULL, "Hello World" , "Hello", MB_OKCANCEL);
Но создание всплывающего окна, которое принимает ввод, более активно, и нет прямого способа сделать это. Все результаты, которые я смог найти в Google, были датированы где-то с 2001 по 2005 год. Наверное, я здесь спрашиваю, появилось ли еще несколько прямых решений в последние годы.
Надеюсь, что-то хорошее и прямое, как в Java:
int number = JOptionPane.showInputDialog ("Enter an integer");
Если это не так, могу ли я получить краткое объяснение, как это сделать?
Изменить: Я не мог заставить работать.:( Я закончил писать код, чтобы выполнить работу на Java, а затем написал одну строку кода на С++ для вызова файла .jar.: -/Поскольку проблема была чувствительной к времени, она была лучше, чем ничего.
Ответы
Ответ 1
Для чистого С++ нет ничего подобного. В основном то, что вы пытаетесь сделать, может быть достигнуто только с помощью вызова API в ОС или с помощью какой-либо библиотеки графического интерфейса, такой как 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/
Ответ 2
Если вы используете Visual С++ Express, существует ряд бесплатных редакторов ресурсов, которые можно использовать для создания диалогов. ResEdit является одним из лучших, которые я нашел.
Вам необходимо создать ресурс диалога в файле .RC, который вы добавите в свой проект.
Тогда, это очень простой случай вызова DialogBox - который загрузит диалоговое окно из вашего файла ресурсов и поместит его на экран, Прошедший в DialogProc будет вызываться с несколькими уведомлениями. Обычно вам нужно возвращать FALSE для всего, но обрабатывайте WM_INITDIALOG как место для инициализации элемента управления редактированием с текстом, а WM_COMMAND будет отправляться при нажатии кнопки.
Ответ 3
Корпорация Майкрософт не рассматривает ваш вариант использования как достаточно общий для оптимизации, как и для MessageBox
. Они ожидают, что вы выложите диалог со многими элементами управления на нем, возможно, с некоторым сложным взаимодействием с элементами управления, и ответьте только после полного заполнения диалогового окна. То, о чем вы просите, - это просто упрощенная версия.
Редактор ресурсов - это самый простой способ создать диалог, но не включенный в бесплатную экспресс-версию Visual Studio. Вы создадите диалоговое окно с текстовым элементом управления для приглашения и элементом управления редактированием для пользователя. Вы представляете диалог с помощью функции DialogBox
Windows, и он возвращается, когда пользователь нажимает кнопку "ОК" или "Х" в углу диалога. У Microsoft есть документация для здесь.
Есть несколько доступных платформ, которые пытаются упростить процесс, например MFC, WTL, Qt и wx, но так вы можете сделать это с помощью чистого API Windows.
Ответ 4
Я должен признать, что на самом деле я не очень много сделал для ввода ящиков в возрасте, но вам в основном нужно выйти за пределы С++, чтобы получить любое графическое окно ввода. Просто нет механизма, встроенного в язык для такого рода материалов по причинам мобильности. Я не помню, применил ли он и к С++, но C даже не предполагает, что у вас есть консоль. Во всяком случае, ваш лучший выбор был бы тем, что вы уже пытались: Win32 API, Qt и т.д. Однако, если вы можете использовать консоль, не стесняйтесь использовать библиотеку iostream для выполнения этой работы.
Ответ 5
Использование консольного окна лучше подходит для режима связи, когда программа запрашивает пользователя, продолжает, снова запрашивает пользователя и т.д.
И для этого вы можете использовать стандартные библиотеки, такие как cin
и cout
.
Ответ 6
попробуйте следующее:
InputBox в С++ 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;
}
Ответ 7
Мой ответ основан на ответе Стивена Куана на Как загрузить и вызвать функцию 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, потому что многие люди, которых я видел, жалуются на то, как ужасно видеть их там.
Дайте знать, если у вас появятся вопросы.