C++ win32 如何使密码字段可选并启用复制和粘贴?

C++ win32 How do I make a password field selectable and enable copying and pasting?

本文关键字:复制 启用 win32 何使 密码 字段 C++      更新时间:2023-10-16

所以我目前需要一个密码字段,用于显示已知的密码。但由于我不想直接向用户显示密码,因此我决定使用密码字段而不是普通字段。由于程序本身正在工作,我只会显示我创建编辑字段的代码,因为这是我根据该程序的要求对其进行更改的唯一地方。

这是我的编辑框的代码片段

std::wstring password = account.GetPassW();
HWND hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), 
password.c_str(), WS_CHILD | WS_VISIBLE | ES_PASSWORD, 85, 30, 245,
20, hWnd, NULL, NULL, NULL
);

account 是struct UserAccount类型的变量,GetPassW()是一个从std::string转换为std::wstring的函数,因为字符串最初是作为第一个字符串加载和存储的。

如果它是普通的登录表单,则此代码工作正常,但这不是登录表单,这是一个登录恢复表单,出于安全原因,密码字段显示星号 (*(。并且此密码字段必须支持使用Ctrl +A进行选择,并使用Ctrl +CCtrl+V进行复制粘贴,而此设置的默认密码字段似乎并非如此。

就像我说的。这不是用于登录某些内容的程序。这是一个程序,您可以在其中选择一个平台或类似平台,此窗口会弹出您存储的用户名和密码,这些用户名和密码已经填充到输入框中,准备复制粘贴到相应的程序中。问题是由于我对密码框使用ES_PASSWORD,它会自动使编辑框无法选择和复制,这与该程序的意图不符。所以我需要找到一种方法来启用编辑框的这些功能,同时保留星号的东西。

我怎么会相处?非常感谢一些代码来说明解决方案。

所以我设法解决了这个问题。但是该解决方案更像是一个补丁工作而不是直接解决方案,所以我不会说这个答案会对其他人有所帮助,但它对我打算使用它的地方有用。

所以我所做的是将其保留为密码字段,但我做了一个静态变量

static WNDPROC wndProcPasswordOld;
static UserAccount currentAccount;
static HWND hWndEditPassword;

然后我初始化密码框的地方,我现在有这个

hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), password.c_str(),
WS_CHILD | WS_VISIBLE | ES_PASSWORD | ES_READONLY, 85, 30, 245,
20, hWnd, NULL, NULL, NULL);
wndProcPasswordOld = (WNDPROC)SetWindowLongPtr(hWndEditPassword, GWLP_WNDPROC,
(LONG_PTR)WndProcPassword);
// This is further down
currentAccount = account;

然后我在底部声明并实现了一个名为WndProcPasswordforward 的WNDPROC,如下所示

LRESULT CALLBACK WndProcPassword(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN:
if ((wParam == 'C' || wParam == 'c') && GetKeyState(VK_CONTROL) & 0x8000)
{
std::string data = currentAccount.password;
const char *output = data.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
break;
}
return CallWindowProc(wndProcPasswordOld, hWnd, message, wParam, lParam);
break;
default:
return CallWindowProc(wndProcPasswordOld, hWnd, message, wParam, lParam);
}
return 0;
}

然而,这不会消除声音,但这与我打算如何使用这个程序没什么大不了的,但我决定留下这个答案,因为我找不到任何其他关于如何在仍然让字符显示星号的同时复制编辑字段的信息。

编辑:我现在已经找到了一个比上述更好的解决方案,但我决定保留两者。

WndProcPasswordWM_KEYDOWN事件已更改为WM_KEYUP。 另外所有在 if 语句中WM_KEYUP我还在检查事件是否为

if (((wParam == 'C' || wParam == 'c') && GetKeyState(VK_CONTROL) & 0x8000) || (wParam == VK_CONTROL && (GetKeyState('C') & 0x8000 || GetKeyState('c') & 0x8000)))
{
// copy to clipboard
}

然后我继续将盒子的创建更改为

hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), L"",
WS_CHILD | WS_VISIBLE | ES_READONLY, 85, 30, 245,
20, hWnd, NULL, NULL, NULL);
SetEditText(password);

SetEditText如下所示

void SetEditText(std::wstring text)
{
int buffersize = text.length() + 1;
WCHAR *wchars = new WCHAR[buffersize];
memset(wchars, 0, sizeof(WCHAR) * buffersize);
for (int i = 0; i < text.length(); i++)
wchars[i] = L'*';
SetWindowText(hWndEditPassword, wchars);
delete[] wchars;
}

此更改使控件充当正常的编辑框,唯一的更改是,当您设置文本时,您可以手动将输入替换为星号,并且由于复制是在按键时完成的,您只需在 keyup 事件中添加自己的复制即可。 这也消除了与输入框交互时的所有限制和错误声音。