天天看点

重绘编辑框CEdit(继承CEdit方式)

编辑框是常用控件之一,同时也是一种完全自实现较为繁琐的控件。本例实现了对编辑框的简单的自绘制,在保留其自身的强大功能的前提下,实现了编辑框的边框、背景、文字颜色以及禁用态的各种颜色的替换。

        要想重绘,我们必须知道要绘什么。通过观察默认的编辑框我们可以很清楚的看到编辑框有三个最基础的部分需要我们绘制,他们分别是3D边框、背景和文字,再进一步分析我们会发现他们是一个基本窗口的两个部分,即客户区和非客户区。这样一来我们就知道应该用什么函数有针对性的绘制什么区域了,由于提供了源码,这里仅就基本原理和技术细节加以讨论,不过多地罗列代码。

        为了绘制非客户区,我重载了OnNcPaint函数,通过这个函数可以很轻松的去掉编辑框3D外观,画成我们自己想要的形式。至于客户区,为了保留编辑框光标闪烁、字符处理、自动回行等功能,我并未重载OnPaint函数。也就是说我并未重绘客户区,而是选择了一个替代的办法。

        我们使用编辑框,用的就是它的文本编辑功能,而我们想要改变的只是文字及背景颜色。通过这种分析我们就会很清楚我们需要做的事情,那就是设置文字颜色和背景色。我用的方法是重载CtlColor函数,在其中根据编辑框禁用和启用的不同状态,设置了不同的颜色,很好的实现了预期目的。

        从严格意义上来说,我并没有对编辑框重绘,只是简单的绘制了边缘,但同样很好的实现预期的效果。当然这个例子还有许多的不尽人意的地方,如果大家有更好的方还希望我们一同交流。

1. 主要实现内容

显示主要有: 边框, 背景, 文字颜色, 禁用态的各种颜色.

2. 边框

边框可以通过重载OnNCPaint实现. 

例如:

void CMyEdit::OnNcpaint()

{

    CRect rect, rc;

    CDC* pDC;

    int  nSaveDC;

    pDC = GetWindowDC();

    GetWindowRect(&rect);

    rect -= rect.TopLoeft();

    rc = rect;

    rc.InflateRect(-GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));

    nSaveDC = pDC->SaveDC();

    pDC->ExcludeClipRect(&rc);

    pDC->FillSolidRect(&rect, RGB(255,255,255));

    pDC->RestoreDC(nSaveDC);

    pDC->FrameRect(&rect, &CBrush(150,150,150));

    ReleaseDC(pDC);

}

3. 背景

背景可以通过重载OnEraseBkgnd实现

BOOL CMyEdit::OnEraseBkgnd(CDC* pDC)

{

    // TODO: Add your message handler code here and/or call default

    return 0;        

    return CEdit::OnEraseBkgnd(pDC);

}

你也可以贴图:

BOOL CMyEdit::OnEraseBkgnd(CDC* pDC)

{

     //TODO: 在此添加消息处理程序代码和/或调用默认值

CDC memDC;

    memDC.CreateCompatibleDC(pDC);

    HBITMAP hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), "C:\\res\\bmp00001.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

    CBitmap* pBmp = CBitmap::FromHandle(hBitmap);

    memDC.SelectObject(pBmp);

    BITMAP bitMap;

    pBmp->GetBitmap(&bitMap);

    CRect rect;

    GetClientRect(&rect);

    //拉伸贴图

    pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, bitMap.bmWidth, bitMap.bmHeight, SRCCOPY);

    memDC.DeleteDC();

    return TRUE;

    //return CEdit::OnEraseBkgnd(pDC);

}

4. 字体颜色

HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)

{    

    pDC->SetBkMode(TRANSPARENT);                    // 透明    

    pDC->SetTextColor(RGB(255, 255, 255));            // 字体色彩    

    return (HBRUSH)GetStockObject(DKGRAY_BRUSH);    // 字体背景(OnEraseBkgnd只是避免闪烁)

}

这里需要注意的是,设置透明是在=WM_CTLCOLOR里设置的,不是在WM_CTLCOLOR中.

有=的是从父窗口反射回来的消息.当然也可以在父窗口的WM_CTLCOLOR中设置透明,不过这样就封装得不好了.