15

我的目标是简单地使用一个弹出框来询问用户输入。我已经搜索了很多,几乎所有的结果都说创建一个 messageBox 真的很容易:

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

但是创建一个接受输入的弹出窗口涉及更多,并且没有直接的方法来做到这一点。我在谷歌上能找到的所有结果都是从 2001 年到 2005 年的某个地方。我想我在这里问的是近年来是否出现了一些更直接的解决方案。

希望像 Java 中的一些好的和直截了当的东西:

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

如果不是这种情况,我能否简要说明如何操作?


编辑:我什么都做不了。:( 我最终编写了代码来用 Java 完成这项工作,然后编写了一行 C++ 代码来调用 .jar 文件。:-/ 由于这个问题是时间敏感的,所以总比没有好。

4

8 回答 8

8

如果您使用的是 Visual C++ Express,则有许多免费的资源编辑器可用于创建对话框。ResEdit是我发现的更好的之一。

您需要在添加到项目的 .RC 文件中创建对话框资源。

然后,这是一个非常简单的调用DialogBox的案例——它将从您的资源文件中加载对话框并将其放置在屏幕上。传入的 DialogProc 将被调用并带有许多通知。通常,您希望对所有内容都返回 FALSE,但将 WM_INITDIALOG 处理为使用文本初始化编辑控件的地方,并且单击按钮时将发送 WM_COMMAND。

于 2010-11-17T08:36:15.137 回答
7

纯 C++ 没有这样的东西。基本上你想要做的事情只能通过使用对操作系统的 API 调用或使用像 Qt 这样的 GUI 库来实现(我建议这样做,因为它比调用本机 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/

于 2010-11-17T04:16:37.880 回答
3

Microsoft 认为您的用例不够普遍,无法针对MessageBox. 他们希望您布置一个带有许多控件的对话框,可能与控件进行一些复杂的交互,并且仅在对话框完全填充后才响应。您所要求的只是其简化版本。

资源编辑器是创建对话框的最简单方法,但它不包含在 Visual Studio 的免费 Express 版本中。您将设计对话框,其中包含一个用于提示的文本控件和一个供用户填写的编辑控件。您使用DialogBoxWindows 功能呈现该对话框,并在用户点击 OK 按钮或窗口角落的 X 时返回对话。Microsoft 在这里有一些文档。

有一些平台可以尝试简化该过程,例如 MFC、WTL、Qt 和 wx,但这是使用纯 Windows API 的方式。

于 2010-11-17T04:40:34.360 回答
3

我的回答是基于 Stephen Quan 对How to load & call a VBScript function from inside C++ 的回答?添加了完整的 UTF-8 支持,您可以从 CPP 文件中的代码注释中收集。与使用 Microsoft Script Control 创建 InputBox 不同,这可用于 x86x64 可执行文件、库和控件。

“输入框.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 *)"");

“输入框.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::wstring;
using std::vector;

static wstring StringWiden(string Str) {
  const size_t wchar_tCount = Str.size() + 1;
  vector<wchar_t> Buffer(wchar_tCount);
  return wstring { Buffer.data(), (size_t)MultiByteToWideChar(CP_UTF8, 0, Str.c_str(), -1, Buffer.data(), wchar_tCount) };
}

static string StringShorten(wstring 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] == '\r' || NewLine[Position] == '\n')
      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);
      SendDlgItemMessageW((HWND)wParam, GetDlgCtrlID(TextBox), EM_SETPASSWORDCHAR, L'\x25cf', 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) {
  // Initialize
  HRESULT hr = S_OK;
  hr = CoInitialize(NULL);
  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);
  wstring 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();

  // Result
  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

我还删除了 VBScript InputBox 标题栏中的默认 Windows 应用程序图标,因为我见过很多人抱怨在那里看到它有多难看。

如果您有任何问题,请告诉我。

于 2018-10-15T00:23:49.553 回答
2

我不得不承认,多年来我在输入框的方式上并没有做太多的事情,但你基本上必须走出 C++ 才能获得任何类型的图形输入框。出于可移植性的原因,语言中根本没有为这种东西内置机制。我不记得它是否也适用于 C++,但 C 甚至不假设你有一个控制台。无论如何,最好的选择是您已经尝试过的方法:Win32 API、Qt 等。但是,如果您可以使用控制台,请随意使用 iostream 库来完成工作。

于 2010-11-17T04:15:35.110 回答
1

使用控制台窗口更适合程序提示用户、继续、再次提示用户等的通信模式。

为此,您可以使用标准库的工具,例如cincout

于 2010-11-17T04:37:11.887 回答
1

与 Visual Basic 和其他语言不同,C++ 中没有类似命令的“内置”输入框。与只能调用的 MessageBox 不同,InputBox() 需要编写。事实上,我已经这样做了。下面的文章描述了如何将这样的 InputBox 实现为小型静态库的一部分,该静态库可以在任何 Win32 c++ 程序中使用,无需资源。Github 上的源代码。它可以按如下方式使用:

LPWSTR GetString(LPCTSTR szCaption, LPCTSTR szPrompt, LPCTSTR szDefaultText = L"");

例如:

LPWSTR result = SG_InputBox::GetString(
     L"Code Project Demo", 
     L"What is your name");
于 2019-08-01T19:25:56.177 回答
0

试试这个: 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;
}
于 2016-10-02T21:25:29.023 回答