当前位置:C++技术网 > 精选软件 > InvalidateRect是否删除背景效果分析以及实现下划线删除线

InvalidateRect是否删除背景效果分析以及实现下划线删除线

更新时间:2015-12-06 13:11:56浏览次数:1+次

    在《InvalidateRect无效矩形的图文分析和在字符串中移动光标》文章中,通过使用长短字符串来展示了背景文字的字迹,感受到了擦除背景和不擦除背景的区别,算是比较明显的。
    然而这里将使用更为直观的方式展示背景是否擦除带来的两种重绘效果。通过长短字符串的方式只有在两头背景多出的位置才可以看到一些痕迹,而字符串中间则没有看到多余的字迹。其原因就是字符串有一个文字背景,而文字背景的颜色和客户区的颜色一样,所以就都是白色的,看上去似乎只有文字一样,实则不然。
    因为先后两次绘制的字符串字体大小都是一样的,而且绘制的位置也是都在中间,字符串都是居中显示的,所以,始终只有两端的位置才有多余,高度的方向都是同样的高度,所以,后绘制的字符串在高度上就可以完全覆盖原先的字符串,所以看不到多余的痕迹。然而因为字符串始终都是居中的,所以后绘制的字符串短的话,然后又将字符窜居中,就只有两边漏出来,而不是只有一边漏出来。这里就详细解释了现象,在那篇文章没有仔细说明。
    然而,尽管如此,如果后绘制的字符串都长于之前的字符串,你就看不到不删除背景的效果,因为始终是覆盖,所以不可能出现背景的痕迹。也正是因为这样,很多时候,大家都感觉不到是否删除背景有什么区别,甚至很多人以为这个不起作用。而在一些时候,输出的文字又有多余的重叠残余字迹,也一下子想不出为什么,那么本文就给出了详细的答案,是足够去除你心中的疑惑的。
    为了更加清晰的验证是否删除背景有什么差别,这里进一步来用代码验证。而原理就是,绘制文字时,去掉文字背景,让文字直接显示在窗口上,这样就去除了文字背景的干扰。这样,如果上次绘制的文字在下一次绘制文字前没有被删除的话,那么两次绘制的文字就重叠了,如果绘制多次,则一直不停的重叠,最后就是黑乎乎的一团。而如果删除背景的话,就会将上次的绘图内容删除掉,即用背景色来抹掉绘制的内容,最后就只有窗口背景的白色了。你再在此窗口上画图,就只看得到当前绘制的文字了,而不会有其他东西重叠干扰了。
    我们需要注意一个问题,那就是,我们需要改变文字的内容,否则,还是同样的文字内容输出,在同样的位置,字体大小等都是一样的,则会始终在同样的位置输出,即使背景不删除,也是完全的覆盖上一次的文字,看上去就没有变化了。所以,你要么改变文字的位置大小或者文字内容,我选择改变文字内容,这样比较方便些。
    我们先看看效果图,第一张为效果图,第二张为第一次绘制的文字效果:

   

    我们可以看到,第一次绘制的就是一串文字,在擦除背景后再绘制文字(一串下划线字符),则看不到原先的字符串了,只有下划线字符了。而不擦除背景绘制文字时,背景的文字(本次以前绘制的内容)都保留,然后这次就在背景文字上继续绘制。所以此时就将下划线字符画在了字符串的底部,因为下划线字符只占底部一点点空间,所以并没有与字符串重叠,看到的就是给字符串添加下划线的效果。而如果话字符“-”,就可以实现删除线效果,而如果是其他字符,就在中间位置,与原先文字叠加后变得混乱不堪。效果图如下:
   
    在验证使矩形区域变成无效时设置是否擦除背景可以给你的程序提供实现添加下划线和删除线的功能的思路参考。
    完整代码如下:
#include "windows.h"
#include <tchar.h>
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    static TCHAR str[]=_T("C++技术网http://www.cjjjs.com");
    static int i=0;
    static TCHAR ch;
    switch (message)
    {
     case WM_PAINT:
         hdc = BeginPaint(hwnd,&ps);
         GetClientRect(hwnd,&rect);
         SetBkMode(hdc,TRANSPARENT);
         DrawText(hdc,str,-1,&rect,DT_SINGLELINE | DT_VCENTER |DT_CENTER);     
         break;
     case  WM_LBUTTONDOWN:
         hdc = GetWindowDC(hwnd);
         GetClientRect(hwnd,&rect);
         InvalidateRect(hwnd,&rect,FALSE);
         lstrcpy(str,_T("________________________"));
         break;
     case WM_DESTROY:
         PostQuitMessage(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++技术网www.cjjjs.com");
    WNDCLASS wndClass;
    wndClass.cbClsExtra=0;
    wndClass.cbWndExtra=0;
    wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    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;
}