当前位置:C++技术网 > 精选软件 > win32使用退格键BackSpace从后到前的删除字符串的字符

win32使用退格键BackSpace从后到前的删除字符串的字符

更新时间:2016-01-01 19:37:05浏览次数:1+次

    我们使用Windows的标准控件,都可以自动对字符串进行键盘响应。那么一般来说,我们是不需要自己去实现退格键删除字符串的。然而要自己实现各种强大的编辑功能,就不能依赖这些小控件了。那么我们就需要自己来实现这些基本的功能,实现自己定制的控件。
    当然这个其实并不难,如果你从未想过这个问题,可能一下子不知道从何下手,这个很正常。还需要说明一点,这里可以实现的并不只是使用退格键删除哦,你可以任意指定删除的键,也可以打破原有的定义。这就是基础的用处,让你可以随心所欲。就算不能够用这些基本的技术做开发,至少这些背景基础知识一定会让你的开发更加顺手的。

    我们删除字符串的效果如下图所示:

使用退格键删除字符串最后一个字符的动态效果图

【使用退格键删除字符串最后一个字符的动态效果图】
    所有的键盘消息都是最先从WM_KEYDOWN消息开始。也就是键盘的一个按键被按下后,就触发这个消息,那你就可以来处理这个消息,来实现你想要的功能。
    而键盘上这么多按键,必然每一个按键都有独一无二的编号,让我们可以区分按键,这个编号就是虚拟键码。Virtual Key就是虚拟的按键的意思,缩写为VK,表示虚拟键码的宏。所以我们后面看到的VK_XXX都是表示虚拟键码的宏定义,其实就是一个数字而已。
    那么我们这里要实现按下退格键就删掉字符串末尾的一个字符,就要检测WM_KEYDOWN消息附带的虚拟键码参数,如果这个参数是退格键VK_BACK,那么就表示按下了这个退格键,然后我们就开始处理删除最后一个字符的操作。删除最后一个字符的原理,就是将最后一个字符替换成字符串结尾的空字符。因为我们使用的是中性字符,所以我们的字符也是中性的,一定要用_T(')、TEXT(')等来表示。注意,是两个单引号,不是双引号,因为是字符而不是字符串。
    而WM_KEYDOWN消息的wParam参数就是虚拟键码参数,使用if判断就可以了。我们可以获取字符串的长度,然后将最后一个字符设置为空字符即可。这样我们就将原始的字符串缩短了一个字符,也就是对原始字符串做修改。如果你要在其他地方还要用到这个字符串,请一定先保存一份,因为这个会毁坏原来的字符串的。比如说你要支持撤销,这样可以用原始的字符串来计算恢复。代码如下:
if (VK_BACK==wParam)
{
    int len = lstrlen(cjjjs);
    if (len!=0)
    {
        cjjjs[len-1]=_T(');
    }
}
TextOut(hdc,0,0,cjjjs,lstrlen(cjjjs));
InvalidateRect(hwnd,NULL,TRUE);
    从代码可以看到,TextOut始终都是显示字符串cjjjs,改变的只是原始的字符串而已。
    当然,你还可以只是通过改变显示字符的个数来达到删除效果。这个当然是障眼法而已。如果用这个方法,最终要是想要得到删除后的字符串,则需要另外做处理。而通过直接处理原始字符串的方法,直接返回的字符串就是删除后的字符串。这部分将单独来分析。本文就讲述如何实现删除效果,而删除后的处理,要另外写一篇来详细展开。使用减少显示字符的数量的方式模拟删除效果的代码如下:
static int iDelCount=0;
iDelCount++;
TextOut(hdc,0,0,cjjjs,lstrlen(cjjjs)-iDelCount);
InvalidateRect(hwnd,NULL,TRUE);
    从代码中可以看出,原始的字符串并没有改变,每次删除只是对删除的字符数计数,然后在TextOut输出时,减少输出的字符数,从而达到删除的效果。
    当然,以上两种删除字符串的方法中,最后输出字符串的TextOut都是在WM_PAINT消息中执行的。所以,退格键响应的最后一步是让客户区无效,产生WM_PAINT消息,这样就可以让客户区重绘,显示出被删掉之后的字符串的效果。
    如果你对于InvalidateRect函数最后一个参数即擦除背景不理解,请阅读《InvalidateRect无效矩形的图文分析和在字符串中移动光标》和《InvalidateRect是否删除背景效果分析以及实现下划线删除线》,就不重复解释了。
    下面是本文分析的完整代码:
#include "windows.h"
#include <tchar.h>
// - 项目是Unicode字符集
TCHAR cjjjs[100]=_T("C++技术网http:www.cjjjs.com");
TCHAR tip[100]=_T("提示:按下键盘的←(退格键)可以删除了字符");
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    static RECT rect;
    static int iDelCount=0;
    switch (message)
    {
     case WM_PAINT:
         hdc = BeginPaint(hwnd,&ps);
         SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT));
         TextOut(hdc,0,0,cjjjs,lstrlen(cjjjs)-iDelCount);
         TextOut(hdc,0,50,tip,lstrlen(tip));
         EndPaint(hwnd,&ps);
         return 0;
     case WM_KEYDOWN:
        if (VK_BACK==wParam)
        {
            //直接在原字符串上删除
            int len = lstrlen(cjjjs);
            if (len!=0)
            {
                cjjjs[len-1]=_T(');
            }
            //只是减少显示的字符个数,原字符串不受影响
            //iDelCount++;
        }
         InvalidateRect(hwnd,NULL,TRUE);
         return 0;
     case WM_DESTROY:
         PostQuitMessage(0);
         return 0;
     default:
         return DefWindowProc(hwnd, message, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
    TCHAR ClassName[] = _T("MyClass");
    TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
    WNDCLASS wndClass;
    wndClass.cbClsExtra=0;
    wndClass.cbWndExtra=0;
    wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.hCursor=LoadCursor(NULL,IDC_HAND);
    wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndClass.hInstance = hInstance;
    wndClass.lpfnWndProc = WinProc;
    wndClass.lpszClassName = ClassName;
    wndClass.lpszMenuName=NULL;
    wndClass.style=CS_HREDRAW|CS_VREDRAW;

    if(!RegisterClass(&wndClass))return 0;
    HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,440,400,NULL,NULL,hInstance,NULL);
    ShowWindow(hwnd,SW_SHOWNORMAL);

    MSG msg;
    while (GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}