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

时间:2018-10-14 22:28:40

标签: c++ winapi visual-studio-2017 desktop-application

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

这是我的编辑框的代码段

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 + C 和< kbd> Ctrl + V ,使用此设置的默认密码字段似乎不是这种情况。

再次如我所说。这不是用于登录某些程序的程序。这是一个您选择平台或类似程序的程序,该窗口会弹出,其中已存储您的用户名和密码,该用户名和密码已填充到输入框中,可以复制粘贴到相应的程序中。问题是因为我在密码框中使用了ES_PASSWORD,所以它自动使编辑框无法选择和复制,这对本程序的目的是行不通的。因此,我需要找到一种在保留星号的同时启用编辑框的功能的方法。

我将如何做到这一点? 非常感谢一些代码来说明解决方案。

1 个答案:

答案 0 :(得分:0)

所以我设法解决了这个问题。但是,该解决方案比直接解决方案更多的是修补工作,因此我不会说这个答案会帮助其他人,但对于我打算将其用于什么用途,它对我来说很有用。

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

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;

然后我有一个WNDPROC名为WndProcPassword的正向声明,并在底部按如下方式实现

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;
}

但是这并不能消除声音,但是与我打算如何使用该程序无关紧要,但是我决定离开这个答案,因为我找不到有关如何复制编辑字段的任何其他信息。同时仍然让字符显示星号。

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

WM_KEYDOWN中的WndProcPassword事件已更改为WM_KEYUPWM_KEYUP中if语句中的Extral我也在检查事件是否是

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;
}

此更改使控件充当普通的编辑框,唯一的变化是,在设置文本时,您将输入手动替换为星号,并且由于复制是在按下键的情况下完成的,因此您只需将自己的复制添加到按键事件。 与输入框进行交互时,这也消除了所有限制和错误提示。