C ++ win32 Как сделать поле пароля доступным для выбора и включить копирование и вставку? - PullRequest
0 голосов
/ 15 октября 2018

Итак, мне нужно поле для ввода пароля для отображения уже известного пароля.Но так как я не хочу напрямую показывать пароль пользователю, я решил использовать поле пароля вместо обычного поля.Поскольку сама программа работает, я покажу только код, в котором я создаю поле редактирования, поскольку это единственное место, где я буду вносить в него изменения в соответствии с требованиями этой программы.

Это фрагмент кодаМой блок редактирования

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 и Ctrl + V , что, похоже, не относится к полю пароля по умолчанию с этой настройкой.

Снова, как я сказал.Это не программа для входа в систему.Это программа, в которой вы выбираете платформу или аналогичную, и в этом окне появляется ваше сохраненное имя пользователя и пароль, уже заполненные в полях ввода и готовые для копирования, вставленные в соответствующую программу.Проблема в том, что я использую ES_PASSWORD для поля пароля, он автоматически делает поле редактирования неспособным выбрать и скопировать, что не будет работать с намерением этой программы.Поэтому мне нужно найти способ включить эти функции в поле редактирования, сохраняя при этом звездочку.

Как бы я справился с этим? Был бы очень признателен за некоторый код для иллюстрации решения.

1 Ответ

0 голосов
/ 15 октября 2018

Так мне удалось так решить проблему.Но решение - это скорее патч-работа, чем прямое решение, поэтому я бы не сказал, что этот ответ поможет другим, но он помог мне в том, для чего я собираюсь его использовать.

Так что я сделалчтобы сохранить это поле пароля, но я сделал статическую переменную

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;

Затем у меня есть WNDPROCWndProcPassword forward объявлен и реализован внизу следующим образом:

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_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.Это также устраняет все ограничения и звуки ошибок при взаимодействии с полем ввода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...