我想重载CEdit,实现自定义绘制。
从CEdit继承了CColorEdit,在对话框上为重载的EditBox定义控件变量m_ColorEdit,然后再修改变量类型为CColorEdit m_ColorEdit。
通过另一个EditBox输入文字,赋值给重载的m_ColorEdit,在CColorEdit::OnPaint()里实现自定义绘制,没有问题。
但是单击了这个重载的EditBox之后,显示的又变成原来的CEdit的内容了,不知还要重载CEdit的哪个消息?
用SPY++跟踪了一下,没有头绪,恳请帮忙。
从CEdit继承了CColorEdit,在对话框上为重载的EditBox定义控件变量m_ColorEdit,然后再修改变量类型为CColorEdit m_ColorEdit。
通过另一个EditBox输入文字,赋值给重载的m_ColorEdit,在CColorEdit::OnPaint()里实现自定义绘制,没有问题。
但是单击了这个重载的EditBox之后,显示的又变成原来的CEdit的内容了,不知还要重载CEdit的哪个消息?
用SPY++跟踪了一下,没有头绪,恳请帮忙。
要不就再处理OnActivate好了。
这里有一个button的处理。
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rect = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState; CString strText;
GetWindowText(strText); // draw the control edges (DrawFrameControl is handy!)
if (state & ODS_SELECTED)
pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);
else
pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH); // Fill the interior color if necessary
rect.DeflateRect( CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)));
if (m_bOverControl)
pDC->FillSolidRect(rect, RGB(255, 255, 0)); // yellow // Draw the text
if (!strText.IsEmpty())
{
CSize Extent = pDC->GetTextExtent(strText);
CPoint pt( rect.CenterPoint().x - Extent.cx/2, rect.CenterPoint().y - Extent.cy/2 ); if (state & ODS_SELECTED)
pt.Offset(1,1); int nMode = pDC->SetBkMode(TRANSPARENT); if (state & ODS_DISABLED)
pDC->DrawState(pt, Extent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
else
pDC->TextOut(pt.x, pt.y, strText); pDC->SetBkMode(nMode);
}
}
void CMyButton::PreSubclassWindow()
{
CButton::PreSubclassWindow(); ModifyStyle(0, BS_OWNERDRAW); // make the button owner drawn
}
代码麽,没什么用,要看也可。// ColorEdit.cpp : 实现文件
//#include "stdafx.h"
#include "CoDPlayerNameEditor.h"
#include ".\coloredit.h"
// CColorEditIMPLEMENT_DYNAMIC(CColorEdit, CEdit)
CColorEdit::CColorEdit()
: m_Color(NULL)//从主对话框传递COLORREF数组指针
{
}CColorEdit::~CColorEdit()
{
}
BEGIN_MESSAGE_MAP(CColorEdit, CEdit)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
ON_CONTROL_REFLECT(EN_SETFOCUS, OnEnSetfocus)
ON_WM_SETFOCUS()
ON_WM_ACTIVATE()
END_MESSAGE_MAP()// CColorEdit 消息处理程序
void CColorEdit::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CEdit::OnPaint()
//HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Call of Duty
//InstallPath
//\main\config_mp.cfg
/*
1 - 红色
2 - 绿色
3 - 黄色
4 - 蓝色
5 - 青色
6 - 粉色
7 - 白色
8 - 黑色
9 - 红色
*/
//COLORREF m_Color[10];
const char ControlChar = '^';
const char ZeroChar = '0';
const char NineChar = '9';
char ColorChar;
int ColorKey = 0; CDC *pdc = GetDC();
CString ColorName;
GetWindowText(ColorName);
CRect ClientRect;
GetClientRect(ClientRect);
pdc->FillSolidRect(ClientRect, RGB(200, 200, 200));
int iLength = ColorName.GetLength();
int iPos = ColorName.Find(ControlChar, 0);
int iPosNext = 0;
int x = ClientRect.left;
CString strSub;
while (iLength && iPosNext != -1)
{
if (iPos == -1)
pdc->SetTextColor(m_Color[0]);
else
{
iPos ++;
ColorChar = ColorName.GetAt(iPos);
if (ColorChar >= ZeroChar && ColorChar <= NineChar)
{
ColorKey = ColorChar - ZeroChar;
pdc->SetTextColor(m_Color[ColorKey]);
iPos++;
}
}
iPosNext = ColorName.Find(ControlChar, iPos);
if (iPosNext != -1)
strSub = ColorName.Mid(iPos, iPosNext - iPos);
else
strSub = ColorName.Right(iLength - iPos);
pdc->TextOut(x, ClientRect.top, strSub);
x += pdc->GetTextExtent(strSub).cx;
iPos = iPosNext;
}
ReleaseDC(pdc);
}BOOL CColorEdit::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return FALSE; return CEdit::OnEraseBkgnd(pDC);
}void CColorEdit::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//if (nIDCtl == IDC_COLOR_EDIT)
//{
////HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Call of Duty
////InstallPath
////\main\config_mp.cfg
// /*
// 1 - 红色
// 2 - 绿色
// 3 - 黄色
// 4 - 蓝色
// 5 - 青色 LG
// 6 - 粉色 Pink
// 7 - 白色
// 8 - 黑色
// 9 - 红色
// */
// COLORREF m_Color[10];
// m_Color[0] = RGB(255, 255, 255);
// m_Color[1] = RGB(255, 0, 0);
// m_Color[2] = RGB(0, 255, 0);
// m_Color[3] = RGB(255, 255, 0);
// m_Color[4] = RGB(0, 0, 255);
// m_Color[5] = RGB(0, 255, 255);
// m_Color[6] = RGB(255, 0, 255);
// m_Color[7] = RGB(255, 255, 255);
// m_Color[8] = RGB(0, 0, 0);
// m_Color[9] = RGB(255, 0, 0);
// const char ControlChar = '^';
// const char ZeroChar = '0';
// const char NineChar = '9';
// char ColorChar;
// int ColorKey = 0; // CDC *pdc = CDC::FromHandle(lpDrawItemStruct->hDC);
// CString ColorName;
// GetWindowText(ColorName);
// CRect ClientRect(lpDrawItemStruct->rcItem);
// pdc->FillSolidRect(ClientRect, RGB(200, 200, 200));
// int iLength = ColorName.GetLength();
// int iPos = ColorName.Find(ControlChar, 0);
// int iPosNext = 0;
// int x = ClientRect.left;
// CString strSub;
// while (iLength && iPosNext != -1)
// {
// if (iPos == -1)
// pdc->SetTextColor(m_Color[0]);
// else
// {
// iPos ++;
// ColorChar = ColorName.GetAt(iPos);
// if (ColorChar >= ZeroChar && ColorChar <= NineChar)
// {
// ColorKey = ColorChar - ZeroChar;
// pdc->SetTextColor(m_Color[ColorKey]);
// iPos++;
// }
// }
// iPosNext = ColorName.Find(ControlChar, iPos);
// if (iPosNext != -1)
// strSub = ColorName.Mid(iPos, iPosNext - iPos);
// else
// strSub = ColorName.Right(iLength - iPos);
// pdc->TextOut(x, ClientRect.top, strSub);
// x += pdc->GetTextExtent(strSub).cx;
// iPos = iPosNext;
// }
// return;
////} //CEdit::OnDrawItem(nIDCtl, lpDrawItemStruct);
}void CColorEdit::OnEnSetfocus()
{
// TODO: 在此添加控件通知处理程序代码
Invalidate();
}void CColorEdit::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus(pOldWnd);
Invalidate();
//this->ShowCaret();
//this->SetCaretPos(CPoint(10, 2)); // TODO: 在此处添加消息处理程序代码
}void CColorEdit::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CEdit::OnActivate(nState, pWndOther, bMinimized); // TODO: 在此处添加消息处理程序代码
Invalidate();
}这里,在OnEnSetfocus()和OnSetfocus()里的Invalidate()有个用处,就是第一次单击鼠标激活控件的时候,控件保持我的绘制内容;再点击一次,就又恢复原来的内容了。而且,二者只要一个响应就可以了。
OnActivate()里的Invalidate()没有用处。
if(GetSafeHwnd() != NULL)
Invalidate(); //这样比较好。
不是简单的自绘啦,否则200分那么容易得的?
不是简单的自绘啦,否则200分那么容易得的?
//我也没有说他又自绘属性呀,不过还是要感谢你的建议。
//在类中加一个刷子br.并创建solidbrush.
HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
// TODO: Return a non-NULL brush if the parent's handler should not be called
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkColor(RGB(0,200,0));
pDC->SetBkMode(TRANSPARENT);
return HBRUSH(br);
}
http://www.codeproject.com/editctrl/ceditbkcolor.asp?msg=35828
而且要在CtlColor中,否则改变不了颜色。HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
// TODO: Return a non-NULL brush if the parent's handler should not be called
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkColor(RGB(0,200,0));
pDC->SetBkMode(TRANSPARENT);
CRect rect;
GetClientRect(&rect);
// pDC->DrawText("abcdefg...",&rect,DT_CENTER);
SetWindowText("abcdefg...");
return (HBRUSH)br;
}
我要根据自定义的颜色控制码显示彩色的(多种颜色)文字。
另外,关于WM_CTLCOLOR,论坛上也有很多人来问,我建议看看MSDN的一篇文章,专门讲EditBox的:Knowledge Base HOWTO: Change the Background Color of an MFC Edit Control
发现一篇好文,楼主不妨看看。
http://www.codeproject.com/editctrl/ceditbkcolor.asp?msg=35828
谢谢,我去看看,不过要折磨我的英文了。
我说过了,我要绘制多种色彩的文字。查找了CodeGuru和CodeProject关于EditControl的文章,没有这样的例子。相似的是彩色语法显示,但是那些要么是继承CView的,要么是从CWnd重新构建的,还真没有继承CEdit的。看来,还真没有人比我在这个问题上认识更深入的吗?
把邮箱告诉我,我发给你!
http://expert.csdn.net/Expert/topic/2993/2993385.xml?temp=.9396479
哪位帮忙看看
谢谢。
http://expert.csdn.net/Expert/topic/2989/2989649.xml?temp=.9427912
然后在OnPaint中BitBlt过去!
不过这种方法我试过!
我是在允许EDIT可编辑的状态下做的,效果不好!
不知道把EDIT变成DISABLE怎么样!
但是单击了这个重载的EditBox之后,显示的又变成原来的CEdit的内容了,不知还要重载CEdit的哪个消息?我没有做过,不过我想这个问题肯定不会重载OnPaint这么简单了。想想单击后控件获得输入焦点光标就会闪烁,这个时候肯定有个类似定时器的消息,而CEdit本身对这个消息的处理的绘制过程中应该并不只是通过OnPaint来重画。我想你可以自己加入对这个消息的处理,使它尽量按自己的意愿重绘。拙见~
我认为还是应该以EDIT为基础,自已从CWnd重新写很烦琐
不过不要只重载OnPaint(),还是重载WindowProc,
然后对其消息进行跟踪、排除性分析,找到有用的。
我想这方面知识有够充足的话,是可以做到的。
我没做过EDIT的子类化,只是个人看法
偶对 mfc 的实现的架构也不是很清楚,应该是用了大量的宏做消息映射,导致宏展开太多太深了,跟都跟不完,我晕~
也许应该把喉结那本深入浅出翻出来啃一下-_-用 raw api 的话可以很简单地挂上控件的 winproc,那天我写个自定义的 Tab(还是 static?忘了,汗)就这么搞的,程序不是很大,我就直接用 api 了,MFC 实在让偶呕吐- -
#include "c_toolkit.h"
#include "TimeEdit.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTimeEditCTimeEdit::CTimeEdit()
{
}CTimeEdit::~CTimeEdit()
{
}
BEGIN_MESSAGE_MAP(CTimeEdit, CEdit)
//{{AFX_MSG_MAP(CTimeEdit)
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTimeEdit message handlersint CTimeEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
EnableWindow(false);
OnTimer(0);
SetTimer(100,1000,NULL);
// TODO: Add your specialized creation code here
return 0;
}void CTimeEdit::OnTimer(UINT nIDEvent)
{
COleDateTime time = COleDateTime::GetCurrentTime(); CString str;
str.Format("%d-%02d-%02d(%s) %02d:%02d:%02d",time.GetYear(),time.GetMonth(),time.GetDay(),GetWeek(time.GetDayOfWeek())
,time.GetHour(),time.GetMinute(),time.GetSecond());
SetWindowText(str);
// TODO: Add your message handler code here and/or call default
// CEdit::OnTimer(nIDEvent);
}CString CTimeEdit::GetWeek(int day)
{ switch(day)
{
case 1:
return "星期日";
case 2:
return "星期一";
case 3:
return "星期二";
case 4:
return "星期三";
case 5:
return "星期四";
case 6:
return "星期五";
case 7:
return "星期六";
default:
break;
}
return "";
}void CTimeEdit::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
CXTMemDC dcm(&dc,rect);
dcm.SetTextColor(RGB(255,0,0));
dcm.SetBkColor(RGB(0,0,0));
CString str;
GetWindowText(str);
dcm.SelectObject(&xtAfxData.font);
dcm.DrawText(str,rect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
}
这是一个只显示时间的CEdit
楼主,我建议全部自己写,而不要继承 edit,那样更麻烦。
Msn:[email protected]
Eml:[email protected]
1.有了CPaintDC dc(this); 就不要 CDC *pdc = GetDC();了吧。
〉〉这个是这样的:我这段代码本来放在别的地方,下面的pDC->不想改了,其实我用CDC *pDC = &dc;也一样,不是关键。2.既然是单击时不行,就在OnLButtonDown里Invalidate();没有必要放在OnSetfocus()里。
〉〉试过了,也不行。单击是好解决的,选择文字等时不太好解决。要实现自定义的复杂功能,可能从EDIT类继承不太合适。谢谢。