纯 Win32 C(++) - 除了替换控件的窗口过程之外,还有其他方法可以禁用“键入时”按钮吗?

问题描述 投票:0回答:1

目前,我在无模式对话框中的编辑框中使用自定义窗口过程,以便向用户提供实时反馈,即,如果必填字段为空/无效,则禁用命令按钮,否则启用它以及过滤用户输入(即仅允许十六进制数字,...)

这应该在“您打字时”发生,而不是在失去或获得焦点时发生。

为了实时过滤用户输入(包括剪贴板粘贴),窗口程序是可行的方法,但是有没有其他优雅的方法至少可以处理常见情况“如果编辑框为空,则禁用“确定”按钮”,以便我可以避免为每个编辑框编写自定义窗口过程,否则会有特定的但可重用类型的过滤过程?

        oldWindowProc = (WNDPROC)GetWindowLongA(hPassword, GWL_WNDPROC);
        custom_user_data3 = (WNDPROC*)HeapAlloc(GetProcessHeap(), 0, sizeof(WNDPROC) + 4 * sizeof(HWND));
        custom_user_data3[0] = oldWindowProc;
        custom_user_data3[1] = (WNDPROC)hTestButton;
        custom_user_data3[2] = (WNDPROC)hUrl;
        custom_user_data3[3] = (WNDPROC)hUsername;
        custom_user_data3[4] = (WNDPROC)hPassword;

        SetWindowLongA(hPassword, GWL_USERDATA, (LONG)custom_user_data3);

另一个控件的 HWND 被传输(转换为 WNDPROC,但实际上是 HWND)到自定义窗口过程,因此它可以使用 EnableWindow 对它们进行操作。

在窗口内进行操作,然后我这样做:

    if (msg == WM_KEYUP || msg == WM_KEYDOWN || msg == WM_CHAR)
    {
        // IsWindow: Precaution to not break functionality in case of renaming of controls
        if (IsWindow(hwnd_testbutton) && IsWindow(hwnd_username_edit) && IsWindow(hwnd_password_edit) &&
            IsWindow(hwnd_url_edit) &&
            ((GetWindowTextLengthA(hwnd_url_edit) <= 0) || (GetWindowTextLengthA(hwnd_username_edit) <= 0) || (GetWindowTextLengthA(hwnd_password_edit) <= 0)))
        {
            EnableWindow(hwnd_testbutton, false);
        }
        else
        {
            EnableWindow(hwnd_testbutton, true);
        }
    }
c winapi edit hwnd wndproc
1个回答
0
投票

您需要的一切1已在对话框管理器中实现:每当子级编辑控件的内容发生更改时2都会向父级发送

EN_CHANGE
通知。父级是对话框,它的对话框过程在您的控制之下。

剩下的挑战是将文档提出的密码音译为人类可读的:

编辑控件的父窗口通过

WM_COMMAND
消息接收此通知代码。

对话框程序需要处理

WM_COMMAND
消息。参数的解码取决于此表中概述的消息源。
EN_CHANGE
通知落入由
Control
:

指定的行
  • HIWORD
    (wParam)
    是通知代码(即
    EN_CHANGE
  • LOWORD
    (wParam)
    保存发送者的控制ID
  • lParam
    是发送者的窗口句柄 (
    HWND
    )

以下示例说明了如何响应更改通知。它实现了一个对话框过程 (

DlgProc
),用于处理来自编辑控件 (
EN_CHANGE
) 的
IDC_EDIT
通知,以切换按钮 (
IDC_BTN
) 的启用状态。

main.c:

#include <Windows.h>

#include "resources.h"

#include <stdbool.h>

#pragma comment(linker, "\"/manifestdependency:type='win32' \
                         name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
                         processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
                         language='*'\"")

LRESULT CALLBACK DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_CLOSE:
        // End the modal dialog loop; a modeless dialog would call
        // `DestroyWindow()` instead
        EndDialog(hDlg, 0);
        return TRUE;

    case WM_COMMAND:
        // Filter on `EN_CHANGE` notifications sent from the `IDC_EDIT` control
        if (LOWORD(wParam) == IDC_EDIT && HIWORD(wParam) == EN_CHANGE)
        {
            // Determine whether the edit control contains any text
            HWND hwnd_edit = (HWND)lParam;
            bool non_empty = GetWindowTextLengthW(hwnd_edit) > 0;
            // En-/disable `IDC_BTN` accordingly
            HWND hwnd_btn = GetDlgItem(hDlg, IDC_BTN);
            EnableWindow(hwnd_btn, non_empty);

            // Message handled
            return TRUE;
        }
        break;

    default:
        break;
    }

    // Default processing
    return FALSE;
}

int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PWSTR cmdline, int cmdshow)
{
    return (int)DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_MAIN), NULL, DlgProc);
}

资源.h:

#pragma once

#define IDD_MAIN 101

#define IDC_EDIT 1001
#define IDC_BTN 1002

资源.rc:

#include "winres.h"

#include "resources.h"

IDD_MAIN DIALOGEX 0, 0, 160, 40
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "EN_CHANGE Demo"
FONT 9, "Segoe UI", 0, 0, 0x0
BEGIN
    EDITTEXT IDC_EDIT 10, 10, 100, 20
    PUSHBUTTON "Test", IDC_BTN 115, 10, 35, 20, WS_DISABLED
END

这相当简单:入口点会启动一个在“资源脚本”中声明的模式对话框。唯一值得一提的是按钮(IDC_BTN)有

WS_DISABLED
窗口样式
设置。这与编辑控件 (IDC_EDIT) 默认不保留文本相关。


1

不是“一切”。过滤输入需要不同的解决方案。这是一个好问题

2

我不知道这里的“它”是什么。我认为它是对话框管理器,但编辑控件是特殊

© www.soinside.com 2019 - 2024. All rights reserved.