CEdit背景设置透明不成功,求纠正!!!!!!!

hua_zhixing_ 2012-10-26 11:18:34
写了个CEdit的继承类,美化效果不理想,全部代码如下。
我想实现一个下划线、背景透明的编辑框,刚运行的时候效果有了,但在上面输入文字时,文字背景就变成白色了,帮忙看看代码哪有问题,头文件就不贴了。

HBRUSH COwnEdit::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CEdit::OnCtlColor(pDC, pWnd, nCtlColor);

// TODO: 在此更改 DC 的任何特性

// TODO: 如果默认的不是所需画笔,则返回另一个画笔
//pDC->SetBkColor(GetSysColor(COLOR_3DFACE));
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
//return hbr;
}




void COwnEdit::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CEdit::OnPaint()
CRect rect;
this->GetRect(&rect);
CDC* pDC=GetDC();
int nStyle = GetStyle() & ES_MULTILINE;
dc.MoveTo(rect.left,rect.bottom);
dc.LineTo(rect.right,rect.bottom);
CString str;
this->GetWindowText(str);

CFont* pFont=this->GetFont();
CFont oldFont;
dc.SelectObject(pFont);

dc.DrawText(str,&rect,DT_LEFT | DT_TOP);
dc.SetBkMode(TRANSPARENT);
//pDC->SetBkColor(GetSysColor(COLOR_3DFACE));
//pDC->SetBkMode(TRANSPARENT);
}


HBRUSH COwnEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
// TODO: 在此更改 DC 的任何特性

// TODO: 如果不应调用父级的处理程序,则返回非 null 画笔
//pDC->SetBkColor(GetSysColor(COLOR_3DFACE));
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
//return NULL;
}


BOOL COwnEdit::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
// TODO: 在此添加专用代码和/或调用基类

//return CEdit::OnChildNotify(message, wParam, lParam, pLResult);
// We only want to handle WM_CTLCOLOREDIT messages - 32 bit only
if (message != WM_CTLCOLOREDIT)
{
return CEdit::OnChildNotify(message, wParam, lParam, pLResult);
}
HDC hdcChild = (HDC)wParam;
// Text is black – you can modify this by adding
// another variable for text color
// SetTextColor(hdcChild, RGB(0,0,0));
//SetBkColor(hdcChild, m_BackColor);
SetBkMode(hdcChild, TRANSPARENT);
//hdcChild->SetBkMode(TRANSPARENT);

return TRUE;
}


void COwnEdit::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus(pOldWnd);

m_BackColor = RGB(255,255,0);
CDC* pDC = GetDC();
Invalidate(FALSE);
// TODO: 在此处添加消息处理程序代码
pDC->SetBkMode(TRANSPARENT);
}


void COwnEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// I am setting normal back color to white
// – you can modify this as you see fit
m_BackColor = RGB(255,255,255);
// Force a repaint
CDC* pDC = GetDC();
Invalidate(FALSE);
//pDC->SetBkMode(TRANSPARENT);
}

void COwnEdit::SetBkGrndColor()
{
// Delete the old brush
m_Brush.DeleteObject();
// Create a new brush in the specified color
m_Brush.CreateSolidBrush(m_BackColor);
CDC* pDC = GetDC();
pDC->SetBkMode(TRANSPARENT);
//pDC->SetBkColor(m_BackColor);
// Select the brush into this window’s device context
pDC->SelectObject(&m_Brush);
CRect rc;
// Get the client area of the edit control
GetClientRect(&rc);
ScreenToClient(&rc);
// Apply the device context to the client area of the edit control
//pDC->Rectangle(0, 0, rc.Width(), rc.Height());
// Rewrite the text since the backcolor paint
// overwrote the existing text
pDC->SetTextColor(RGB(0,0,0));
pDC->TextOut(2, 2, m_Text.GetBuffer(m_Text.GetLength()));
}
...全文
390 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
hua_zhixing_ 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

自绘CEdit是一个难点, 简单的自绘, 可以看我很早以前的博文.

http://blog.csdn.net/psbeond/article/details/386223

文章只讲了如何背景贴图(透明的原理就是先把父窗口背景贴到edit上,再贴edit背景).

但完美自绘Edit,还有很多路要走. 比如设置输入位置左上角偏移等等.


------------------……
[/Quote]

LibUIDK是你们公司的吗?还要收费的啊?现在的网络环境,只得望而却步了,呵呵。。。

完美自绘Edit确实要走的路很多,不同事件都会影响到背景的绘制。
hua_zhixing_ 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

被无视的感觉真无奈!
http://topic.csdn.net/u/20121023/16/ed3c04e5-bdd6-45f5-b7ff-283b7b3a1e2c.html
[/Quote]

不好意思,你说得太简洁了,我没理解上,注意力在解决问题上去了,呵呵,当然很谢谢你!
hua_zhixing_ 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

下面是 Slider 的做法:
1.先得到Id:
C/C++ code

void CYourSlider::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
#ifdef SELF_GET
UINT id=::GetDlgCtrlID(this……
[/Quote]

您提供的CreatePatternBrush代码我没运行成功,我按照我自己的思路已经实现了,谢谢你!

我是通过获取父窗口的背景,然后直接作为控件的背景画上去,效果不错。获取父窗口背景是一个一个像素拷贝的,应该有更好的方法,但原理肯定是一样的,有一个问题需要注意,如果直接从父窗口的CDC拷贝图像数据的话,会很慢,而且通过GetCurrentBitmap得到的只是临时对象,在xp下可能可能会出现内存不能读/写的错误,我的做法是先把父窗口背景图片数据整个先拷贝下来,再处理。方法感觉方法有点笨,看到效果没影响就没继续找好方法了。
psbeond 2012-10-29
  • 打赏
  • 举报
回复
自绘CEdit是一个难点, 简单的自绘, 可以看我很早以前的博文.

http://blog.csdn.net/psbeond/article/details/386223

文章只讲了如何背景贴图(透明的原理就是先把父窗口背景贴到edit上,再贴edit背景).

但完美自绘Edit,还有很多路要走. 比如设置输入位置左上角偏移等等.


------------------------------------------------------------------------


sumos 2012-10-27
  • 打赏
  • 举报
回复
schlafenhamster 2012-10-27
  • 打赏
  • 举报
回复
“我理解是,先把控件所在位置的窗口背景存到Brush里,然后每次更新界面都用这个Brush来画背景”
对。
这是vc6上多次使用的代码,没问题的。

“是否可以实现在自绘的Edit类里实现获取主窗口的背景”可以,但有个问题是‘自绘的Edit类’里如何区分不同的实例。(不同的实例有不同的背景,因位置不同)
hua_zhixing_ 2012-10-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

C/C++ code

CBrush* CDrawEditDlg::CreateBackgroundBrush(CDC* pDC,int ctrlId)
{
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);//DeleteDC needed
CBitmap* pOldBitmap = dcMem.SelectObject(&m_……
[/Quote]

我理解是,先把控件所在位置的窗口背景存到Brush里,然后每次更新界面都用这个Brush来画背景,是这样吗?但你的代码没成功,帮忙再看看,好吗?我是在OnCtlColor里返回这个Brush的,不知道用法是否有误?

还有,是否可以实现在自绘的Edit类里实现获取主窗口的背景?
schlafenhamster 2012-10-27
  • 打赏
  • 举报
回复
补一个:
void CYourSlider::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect rc;
GetWindowRect(&rc);
ScreenToClient(&rc);
// use 2 buffer , because a bit flicking
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap (&dc, rc.Width(), rc.Height());
HBITMAP OldBitmap = (HBITMAP) memDC.SelectObject (MemBitmap);
// back ground
UINT id=::GetDlgCtrlID(this->m_hWnd);
CBrush *pBkgBrush=0;
for(int jj=0;jj<MAX_CTRL;jj++)
{
if(m_aInfo[jj].CtrlId==id)
{
pBkgBrush=m_aInfo[jj].pBkdBrush;
break;
}
}
if(pBkgBrush)
{
// afxDump << rc << "\n";
memDC.FillRect(rc,pBkgBrush);//PatternBrush
}
。。。
schlafenhamster 2012-10-27
  • 打赏
  • 举报
回复
下面是 Slider 的做法:
1.先得到Id:

void CYourSlider::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
#ifdef SELF_GET
UINT id=::GetDlgCtrlID(this->m_hWnd);
//afxDump << id << "\n";
m_aInfo[m_CtrlCount].CtrlId=id;
m_CtrlCount++;
#endif
//
CSliderCtrl::PreSubclassWindow();
}


2。获取对应Id的控件背景:

BOOL CYourSlider::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
//
#ifdef SELF_GET

UINT id=::GetDlgCtrlID(this->m_hWnd);
afxDump << id << "\n";
for(int jj=0;jj <= m_CtrlCount;jj++)
{
if((m_aInfo[jj].CtrlId > 0) && (m_aInfo[jj].CtrlId==id) && (m_aInfo[jj].pBkdBrush==0))
{// brush
CDC *pDCdlg=GetParent()->GetDC();
CRect rc;
GetWindowRect(&rc);
ScreenToClient(&rc);
afxDump << rc << "\n";
CDC dcMemCtrl;
dcMemCtrl.CreateCompatibleDC(pDC);//DeleteDC needed
CBitmap CtrlBmp;//DeleteObject needed
CtrlBmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
CBitmap *pOldBitmap = dcMemCtrl.SelectObject(&CtrlBmp);
dcMemCtrl.BitBlt(0, 0, rc.Width(), rc.Height(), pDC,rc.left, rc.top,SRCCOPY);
CBitmap *nowBMP=dcMemCtrl.SelectObject(pOldBitmap);//
// copy to CB for checking
#ifdef TEST
OpenClipboard();
EmptyClipboard();
SetClipboardData(CF_BITMAP,nowBMP->GetSafeHandle());
CloseClipboard();
#endif
CBrush *pBackBr=new CBrush;
pBackBr->CreatePatternBrush(nowBMP);
m_aInfo[jj].pBkdBrush=pBackBr;
//
DeleteObject(CtrlBmp);
dcMemCtrl.DeleteDC();
ReleaseDC(pDCdlg);
return TRUE;
}
}
#endif
return TRUE;
}

3。
typedef struct _ctrlInfo
{
CBrush *pBkdBrush;
UINT CtrlId;
} CTRL_INFO,*LPCTRL_INFO;
4。
protected:
CTRL_INFO m_aInfo[MAX_CTRL];// 10
int m_CtrlCount;

关键:
pBackBr->CreatePatternBrush(nowBMP);
hua_zhixing_ 2012-10-27
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

“我理解是,先把控件所在位置的窗口背景存到Brush里,然后每次更新界面都用这个Brush来画背景


对。
这是vc6上多次使用的代码,没问题的。

“是否可以实现在自绘的Edit类里实现获取主窗口的背景”可以,但有个问题是‘自绘的Edit类’里

如何区分不同的实例。(不同的实例有不同的背景,因位置不同)
[/Quote]

我是在vs2010里使用这个代码,没效果,不知道有无使用错误。

在自绘Edit类里我实现了这个方法,先获取父窗口上控件所在位置大小(就可通过这个来区分不同实

例)的背景保存在CImage里,再绘在控件上,效果很好,没有不和谐的地方,但有一个比较严重的问

题,在窗口上多几个Edit控件的话,打开程序时,明显感到控件一个一个慢慢的加载上来,太慢了。我是用GetPixel和SetPixel来获取父窗口背景和保存的,而且慢的原因就在这里,去掉这些代码就没慢的问题了。如果按照我这个思路的话,请问是否有快速获取父窗口背景的方法?
great_kevin 2012-10-26
  • 打赏
  • 举报
回复
太长了,一时半会儿看不完,学习一下
schlafenhamster 2012-10-26
  • 打赏
  • 举报
回复


BOOL CSelEdit::OnEraseBkgnd(CDC* pDC)
{
CDrawEditDlg *pdlg=(CDrawEditDlg*)GetParent();
CRect rc;
GetWindowRect(&rc);
ScreenToClient(&rc);
// afxDump << rc << "\n";
pDC->FillRect(rc,pdlg->m_pbrEd);//PatternBrush

return TRUE;
// return CEdit::OnEraseBkgnd(pDC);
}
schlafenhamster 2012-10-26
  • 打赏
  • 举报
回复

CBrush* CDrawEditDlg::CreateBackgroundBrush(CDC* pDC,int ctrlId)
{
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);//DeleteDC needed
CBitmap* pOldBitmap = dcMem.SelectObject(&m_bitmap);
// Retrieve the size of our bitmap...
BITMAP bmp;
m_bitmap.GetObject(sizeof(bmp),&bmp);
// and the size of our dlg's client area
CRect rect;
GetClientRect(&rect);
//
CRgn rgnClip;
CRect rc;
GetDlgItem(ctrlId)->GetWindowRect(&rc);
rgnClip.CreateRectRgnIndirect(rc);//DeleteObject needed
CDC* pDCex=GetDCEx(&rgnClip,DCX_PARENTCLIP);//ReleaseDC needed
// Fill the client area of dlg,include the ctrl with our bitmap
pDCex->StretchBlt(rect.left, rect.top,rect.Width(), rect.Height(),
&dcMem,0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
// we create the background brush of SelEdit
CDC dcMemCtrl;
dcMemCtrl.CreateCompatibleDC(pDCex);//DeleteDC needed
CBitmap CtrlBmp;//DeleteObject needed
CtrlBmp.CreateCompatibleBitmap(pDCex,rc.Width(),rc.Height());
pOldBitmap = dcMemCtrl.SelectObject(&CtrlBmp);
ScreenToClient(&rc);
MapWindowPoints(this,rc);
// afxDump << rc << " xx\n";
dcMemCtrl.BitBlt(0, 0, rc.Width(), rc.Height(), pDCex, rc.left, rc.top, SRCCOPY);
CBitmap *nowBMP=dcMemCtrl.SelectObject(pOldBitmap);
// copy to CB for checking
#ifdef TEST
OpenClipboard();
EmptyClipboard();
SetClipboardData(CF_BITMAP,nowBMP->GetSafeHandle());
CloseClipboard();
#endif
CBrush *pBackBr=new CBrush;
pBackBr->CreatePatternBrush(nowBMP);
//
DeleteObject(rgnClip);
DeleteObject(CtrlBmp);
ReleaseDC(pDCex);
dcMemCtrl.DeleteDC();
//
return pBackBr;
}
//
#define ONE_DC

#ifdef ONE_DC // edit not hided !
BOOL CDrawEditDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
if(!m_bInitEditBr)
{// add edit rect
m_bInitEditBr=TRUE;
m_pbrEd=CreateBackgroundBrush(pDC, IDC_SEL_EDIT);
}
schlafenhamster 2012-10-26
  • 打赏
  • 举报
回复
需要把edit的背景制作为一个Brush,在OnEraseBkgnd(CDC* pDC)中用这个Brush刷背景。
sumos 2012-10-26
  • 打赏
  • 举报
回复
响应OnEraseBkgnd绘制背景。

事件OnEnChange刷新控件。这个你缺少了,所以输入后出问题。
schlafenhamster 2012-10-26
  • 打赏
  • 举报
回复
HBRUSH COwnEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)

是REFLECT消息

BOOL COwnEdit::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)

干什么的?

HBRUSH COwnEdit::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

又是干什么的?

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧