用输入框提示用户?[C++]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4201399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Prompting a user with an input box? [C++]
提问by Ryan
My goal is to simply use a pop-up box to ask the user for an input. I've searched around quite a bit and pretty much all the results say that creating a messageBox is really easy:
我的目标是简单地使用弹出框来询问用户输入。我已经搜索了很多,几乎所有的结果都说创建一个 messageBox 真的很容易:
MessageBox (NULL, "Hello World" , "Hello", MB_OKCANCEL);
But that creating a pop-up that takes input is more involved and there isn't a straight forward way to do it. All of the results I could find on Google were dated somewhere from 2001 to 2005. I guess I'm here asking if some more straight forward solution has come about in recent years.
但是创建一个接受输入的弹出窗口更复杂,并且没有直接的方法来做到这一点。我在 Google 上能找到的所有结果的日期都在 2001 年到 2005 年之间。我想我在这里问的是近年来是否出现了一些更直接的解决方案。
Hopefully something nice and straight forward like in Java:
希望有一些像 Java 一样好的和直接的东西:
int number = JOptionPane.showInputDialog ("Enter an integer");
If that isn't the case, could I get a brief explanation of how to do it?
如果不是这种情况,我能否简要说明如何操作?
Edit:I couldn't get anything to work. :( I ended up writing the code to do the work in Java, and then wrote one line of C++ code to call the .jar file. :-/ Since the issue was time sensitive, it was better than nothing.
编辑:我什么也做不了。:(我最终用Java编写了代码来完成这项工作,然后编写了一行C++代码来调用.jar文件。:-/由于这个问题对时间敏感,所以总比没有好。
采纳答案by Raphael
There is nothing like that for pure C++. Basically what you're trying to do can only be achieved by using an API call to the OS or by using some GUI library like Qt (which I recommend cause it's waaaaay easier then calling native APIs and it's also multi-platform)
纯 C++ 没有这样的东西。基本上,您要做的事情只能通过使用对操作系统的 API 调用或使用一些像 Qt 之类的 GUI 库来实现(我建议这样做,因为它比调用本机 API 更容易,而且它也是多平台的)
Using Qt you can show an input dialog pretty much the same way you do it on java:
使用 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
}
You can download the Qt library here: qt.nokia.com/products/developer-tools/
您可以在此处下载 Qt 库:qt.nokia.com/products/developer-tools/
回答by Chris Becke
If you are using Visual C++ Express there are a number of free resource editors that can be used to create dialogs. ResEditis one of the better ones I've found.
如果您使用的是 Visual C++ Express,则有许多免费的资源编辑器可用于创建对话框。ResEdit是我发现的最好的之一。
You need to create a dialog resource in a .RC file that you add to your project.
您需要在添加到项目中的 .RC 文件中创建对话资源。
Then, It is a very simple case of calling DialogBox- which will load the dialog box from your resource file and place it on the screen. The passed in DialogProc will be called with a number of notifications. Typically you would want to return FALSE for everything, but handle WM_INITDIALOG as a place to initialize the edit control with text, and WM_COMMAND will be sent when a button is clicked.
然后,这是调用DialogBox 的一个非常简单的案例- 它将从您的资源文件加载对话框并将其放置在屏幕上。在 DialogProc 中传递的将被调用并带有许多通知。通常,您希望对所有内容都返回 FALSE,但将 WM_INITDIALOG 处理为用文本初始化编辑控件的地方,并且在单击按钮时将发送 WM_COMMAND。
回答by Mark Ransom
Microsoft doesn't consider your use case to be common enough to optimize for, as with MessageBox
. They expect you to lay out a dialog with many controls on it, perhaps with some complex interaction with the controls, and only respond once the dialog is fully filled in. What you're asking for is just the simplified version of that.
Microsoft 不认为您的用例足够常见以进行优化,就像MessageBox
. 他们希望您布置一个带有许多控件的对话框,也许与控件进行一些复杂的交互,并且只有在对话框完全填充后才做出响应。您所要求的只是简化版本。
The resource editor is the easiest way to create a dialog, but that's not included in the free Express version of Visual Studio. You would design the dialog with a text control for the prompt and an edit control for the user to fill in. You present the dialog with the DialogBox
Windows function, and it returns when the user hits the OK button or the X in the corner of the dialog. Microsoft has some documentation for it here.
资源编辑器是创建对话框的最简单方法,但它不包含在 Visual Studio 的免费 Express 版本中。您将设计带有提示文本控件和供用户填写的编辑控件的对话框。您使用DialogBox
Windows 函数显示对话框,当用户点击确定按钮或窗口角落的 X 时,它返回对话。Microsoft在此处提供了一些相关文档。
There are a few platforms available that try to make the process easier, such as MFC, WTL, Qt, and wx, but this is how you'd do it with the pure Windows API.
有一些可用的平台试图使该过程更容易,例如 MFC、WTL、Qt 和 wx,但这是您使用纯 Windows API 实现的方式。
回答by Cheers and hth. - Alf
Using a console window is better suited to the mode of communication where a program prompts the user, continues, prompts the user again, and so on.
使用控制台窗口更适合于程序提示用户、继续、再次提示用户等的通信模式。
And for that you can use the standard library's facilities like cin
and cout
.
为此,您可以使用标准库的功能,例如cin
和cout
。
回答by Gemini14
I have to admit that I haven't really done much in the way of input boxes in ages, but you basically have to go outside C++ in order to get any kind of graphical input box. There's simply no mechanism built into the language for that kind of stuff for portability reasons. I don't remember if it applied to C++ as well, but C doesn't even assume you have a console. Anyway, your best bet would be something along the lines you were already trying: Win32 API, Qt, etc. If you can use the console, however, feel free to just use the iostream library to get the job done.
我不得不承认,多年来我在输入框的方式上并没有真正做过很多事情,但是为了获得任何类型的图形输入框,您基本上必须脱离 C++。出于可移植性的原因,语言中根本没有内置机制来处理这种事情。我不记得它是否也适用于 C++,但 C 甚至不假设你有一个控制台。无论如何,您最好的选择是您已经尝试过的东西:Win32 API、Qt 等。但是,如果您可以使用控制台,请随意使用 iostream 库来完成工作。
回答by Samuel Joseph Venable
My answer is based on Stephen Quan's answer to How to load & call a VBScript function from within C++?Added full UTF-8 support, as you can gather from the code comments in the CPP file. Unlike using Microsoft Script Control to create the InputBox, this can be used in x86 andx64 executables, libraries, and controls.
我的回答基于 Stephen Quan 对How to load & call a VBScript function from inside C++? 添加了完整的 UTF-8 支持,您可以从 CPP 文件中的代码注释中收集到。与使用 Microsoft Script Control 创建 InputBox 不同,这可用于 x86和x64 可执行文件、库和控件。
"inputbox.h":
“输入框.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":
“输入框.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);
}
Create the two above files and then add them to your Visual Studio project.
创建上述两个文件,然后将它们添加到您的 Visual Studio 项目中。
In any file you want the input or password box functions, (found in the header), simply include the header:
在您想要输入或密码框功能的任何文件中(在标题中找到),只需包含标题:
#include "inputbox.h"
// use functions here
I also got rid of the default Windows application icon in the title bar of the VBScript InputBox, because a lot of people I've seen complain about how ugly it is to see that there.
我还去掉了 VBScript InputBox 标题栏中的默认 Windows 应用程序图标,因为我见过的很多人都抱怨在那里看到它有多难看。
Let me know if you have any questions.
如果您有任何问题,请告诉我。
回答by Michael Haephrati
Unlike Visual Basic and other languages, there is no "built in" Input Box like command in c++. Unlike MessageBox that can be just invoked, InputBox() needs to be written. In fact, I have done so. The following articledescribes how to implement such InputBox as part of a small Static Library that can be used, with no Resources, from any Win32 c++ program. Source code at Github. It can be used as follow:
与 Visual Basic 和其他语言不同,C++ 中没有像命令这样的“内置”输入框。与可以直接调用的 MessageBox 不同,InputBox() 需要编写。事实上,我已经这样做了。下面的文章描述了如何将此类 InputBox 实现为一个小型静态库的一部分,该静态库可以从任何 Win32 c++ 程序中使用,无需任何资源。Github 上的源代码。它可以如下使用:
LPWSTR GetString(LPCTSTR szCaption, LPCTSTR szPrompt, LPCTSTR szDefaultText = L"");
For example:
例如:
LPWSTR result = SG_InputBox::GetString(
L"Code Project Demo",
L"What is your name");
回答by Michael Fitzpatrick
try this: InputBox in c++ vs2010
试试这个: C++ vs2010中的InputBox
#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;
}