单击Ctrl + A选择编辑控件中的所有文本

问题描述 投票:9回答:4

如何通过按Ctrl + A选择编辑控件中的所有文本?我可以在WndProc中为父窗口捕获Ctrl + A.但我不知道如何捕捉ctrl + a应用于编辑控制。我也尝试使用加速器,但它同样适用于父窗口。谢谢。编辑:1-st最简单的方法这个方法基于@ phord在这个问题中的答案:win32 select all on edit ctrl (textbox)

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        if (msg.message == WM_KEYDOWN && msg.wParam == 'A' && GetKeyState(VK_CONTROL) < 0)
    {
        HWND hFocused = GetFocus();
        wchar_t className[6];
        GetClassName(hFocused, className, 6);
        if (hFocused && !wcsicmp(className, L"edit"))
            SendMessage(hFocused, EM_SETSEL, 0, -1);
    }
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
}

编辑:第二种方法需要使用CreateAcceleratorTable + TranslateAccelerator函数:

//全局变量:

enum {ID_CTRL_A = 1};
HACCEL accel;

//主程序

ACCEL ctrl_a;
ctrl_a.cmd = ID_CTRL_A; // Hotkey ID
ctrl_a.fVirt = FCONTROL | FVIRTKEY;
ctrl_a.key = 0x41; //'A' key
accel = CreateAcceleratorTable(&ctrl_a, 1); //we have only one hotkey

// GetMessage循环的外观

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        if (!TranslateAccelerator(hWnd, accel,  &msg))
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }
}

//在WndProc中我们必须添加下一个案例

case WM_COMMAND:
{
    if (LOWORD(wParam) == ID_CTRL_A && HIWORD(wParam) == 1)
    {
        //on which control there was pressed Ctrl+A
        //there is no way of getting HWND through wParam and lParam
        //so we get HWND which currently has focus.
        HWND hFocused = GetFocus();
        wchar_t className[6];
        GetClassName(hFocused, className, 6);
        if (hFocudsed && !wcsicmp(className, L"edit"))
            SendMessage(hFocused, EM_SETSEL, 0, -1);
    }
}
break;
case WM_DESTROY:
{
   DestroyAcceleratorTable(accel);
   PostQuitMessage(0);
}
break;

如你所见,这很简单。

winapi visual-c++
4个回答
9
投票

无需处理WM_KEYDOWN!我知道这里的大多数例子(以及CodeProject和许多其他地方)都说有,但它无法治愈每当WM_CHAR出现时未处理的蜂鸣声。

相反,试试这个:

LRESULT CALLBACK Edit_Prc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
  if(msg==WM_CHAR&&wParam==1){SendMessage(hwnd,EM_SETSEL,0,-1); return 1;}
  else return CallWindowProc((void*)WPA,hwnd,msg,wParam,lParam);
}

记得使用WPA = SetWindowLong(...)将EDIT控件子类化为此Edit_Prc(),其中WPA是CallWindowProc(...)的窗口过程地址


6
投票

首先更改WindowProc以进行编辑控件:

if (!(pEditProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, (LONG)&EditProc)))
{
    assert(false);
    return false;
}

然后在新窗口proc中,处理ctrl + a:

LRESULT CALLBACK EditProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    if (msg == WM_KEYDOWN) {
        if (GetKeyState(VK_CONTROL) & 0x8000 && wParam == 'A') {
            SendMessage(hwnd, EM_SETSEL, 0, -1);
        }
    }
    return CallWindowProc(pEditProc, hwnd, msg, wParam, lParam);
}

1
投票

好消息!

似乎编辑控件(不是多行)现在在Win10上原生支持Ctrl + A.

我当前的Windows SDK版本是10.0.17763.0。

仅在使用纯Windows API创建的简单GUI APP上进行测试。

MFC APP应该有相同的结果。

测试二进制平台是x86,OS是Win10 x64。


0
投票

Noob proof version?

我还使用加速器表编写了自己的版本。这有点清理了WinMain,我试图尽可能地将所有内容都作为n00b证明(因为我是一个)。枚举也被省略,因为它不需要。

如上所述,我只是使用winapi的初学者,所以如果我错了,请务必纠正我。

在“Resource.h”中,我为将要使用的加速器表定义了两个ID的One,以及一个用于我们将使用的selectall命令的ID。

在Resource.h里面:

#define IDR_ACCEL1 101
#define ID_SELECT_ALL 9003

然后在资源文件内部(在vs2017中这是PROJECTNAME.rc)我们定义加速器表。 PROJECTNAME.rc:

IDR_ACCEL1 ACCELERATORS
{
    0x41, ID_SELECT_ALL, VIRTKEY, CONTROL // ctrl-A
}

描述

0x41是virtkey'a'。

ID_SELECT_ALL(将是命令的ID,这应该是我们在Resource.h文件中定义的ID。

VIRTKEY关键字指示0x41应解释为虚拟键。

CONTROL是将a与(ctrl + a)组合所需的修饰符。

然后在WinMain函数内加载加速器:

HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
if (hAccel == NULL)
{
    MessageBox(NULL, _T("Failed to load accelerator table!"),_T("Error"), MB_OK | MB_ICONEXCLAMATION);
    return 0;
}

注意:在尝试定义hAccel之后,我们会检查是否已分配有效句柄。虽然这不是必需的,但我相信这是更好的惯例。

在此之后,我们将TranslateAccelerator函数添加到消息循环中,因此可以在窗口过程中处理该命令:

BOOL bRet;
while (bRet = GetMessage(&Msg, NULL, 0, 0) > 0)
{
    if (bRet == -1)
    {
        // Error handling can be done here.
    }
    else if (!TranslateAccelerator(hwnd, hAccel, &Msg))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

然后最后在Window程序中我们添加代码如下:

switch(msg)
{
    case WM_COMMAND:
       {
            switch (LOWORD(wParam))
            {
                case ID_SELECT_ALL:
                {
                    HWND hEdit;
                    hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT)  // Define IDC_MAIN_EDIT with an integer value in "Resource.h".
                }
                break;
            }
       break;
       }
}

注意:传递给WM_COMMAND的消息是我们为ctrl + a accel定义的ID。

我希望这能帮助其他人。

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