从CButton派生出自绘按钮类CBtmpbutton在单文档视类窗口中Create后,编译运行时显示了该按钮的程序窗口一闪即过?
经过试了直接在视类窗口中使用SDK的“button"类创建按钮运行正常,不重载DrawItem()函数则视类窗口也显示正常,所以估计是重载DrawItem()函数有问题但是一直不知道问题具体所在,因为运行时视类窗口显示了按钮控件一闪而过,也不提示任何运行时错误,所以下断点运行,程序一直在DrawItem()函数内循环,故也不知道该怎么找出这样的问题,下面贴出手动添加的代码的部分,请大家帮指导指导!:
// Btmpbutton.h : header file(以下为定义CBtmpbutton类的头文件Btmpbutton.h)
//
#include <bitset>
using std::bitset;
class CBtmpbutton : public CButton
{
// Construction
public:
CBtmpbutton();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBtmpbutton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL// Implementation
public:
static UINT m_testfocusid;
CString m_titlestr;
CRect m_rect;
CDC* m_pDC;
void DrawTestFocusButton();
void DrawPendButton();
void DrawPassButton();
bitset<18> m_bitset;
CBitmap m_bitmap1;
virtual ~CBtmpbutton(); // Generated message map functions
protected:
//{{AFX_MSG(CBtmpbutton)
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};
以下为:Btmpbutton.cpp中的手动增加代码了的函数:
1
UINT CBtmpbutton::m_testfocusid = 1;//手动增加代码的地方1:这里初始化了CBtmpbutton类的静态变量。
CBtmpbutton::CBtmpbutton()
{}
2
void CBtmpbutton::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);//手动增加代码的地方2:这里增加BS_OWNERDRAW风格。
}3
void CBtmpbutton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
m_rect = lpDrawItemStruct->rcItem;
UINT buttonid = lpDrawItemStruct->CtlID;
m_pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
int nSaveDC=m_pDC->SaveDC();
GetWindowText(m_titlestr);
switch(buttonid)
{
case 1:
if(m_bitset.test(0))
DrawPassButton();
else
{
if(1 == (m_testfocusid))
DrawTestFocusButton();
else
DrawPendButton();
}
break;
case 2:
if(m_bitset.test(1))
DrawPassButton();
else
{
if(2 == (m_testfocusid))
DrawTestFocusButton();
else
DrawPendButton();
}
break;
case 3:
......
}
m_pDC->RestoreDC(nSaveDC);
}
经过试了直接在视类窗口中使用SDK的“button"类创建按钮运行正常,不重载DrawItem()函数则视类窗口也显示正常,所以估计是重载DrawItem()函数有问题但是一直不知道问题具体所在,因为运行时视类窗口显示了按钮控件一闪而过,也不提示任何运行时错误,所以下断点运行,程序一直在DrawItem()函数内循环,故也不知道该怎么找出这样的问题,下面贴出手动添加的代码的部分,请大家帮指导指导!:
// Btmpbutton.h : header file(以下为定义CBtmpbutton类的头文件Btmpbutton.h)
//
#include <bitset>
using std::bitset;
class CBtmpbutton : public CButton
{
// Construction
public:
CBtmpbutton();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBtmpbutton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL// Implementation
public:
static UINT m_testfocusid;
CString m_titlestr;
CRect m_rect;
CDC* m_pDC;
void DrawTestFocusButton();
void DrawPendButton();
void DrawPassButton();
bitset<18> m_bitset;
CBitmap m_bitmap1;
virtual ~CBtmpbutton(); // Generated message map functions
protected:
//{{AFX_MSG(CBtmpbutton)
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};
以下为:Btmpbutton.cpp中的手动增加代码了的函数:
1
UINT CBtmpbutton::m_testfocusid = 1;//手动增加代码的地方1:这里初始化了CBtmpbutton类的静态变量。
CBtmpbutton::CBtmpbutton()
{}
2
void CBtmpbutton::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);//手动增加代码的地方2:这里增加BS_OWNERDRAW风格。
}3
void CBtmpbutton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
m_rect = lpDrawItemStruct->rcItem;
UINT buttonid = lpDrawItemStruct->CtlID;
m_pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
int nSaveDC=m_pDC->SaveDC();
GetWindowText(m_titlestr);
switch(buttonid)
{
case 1:
if(m_bitset.test(0))
DrawPassButton();
else
{
if(1 == (m_testfocusid))
DrawTestFocusButton();
else
DrawPendButton();
}
break;
case 2:
if(m_bitset.test(1))
DrawPassButton();
else
{
if(2 == (m_testfocusid))
DrawTestFocusButton();
else
DrawPendButton();
}
break;
case 3:
......
}
m_pDC->RestoreDC(nSaveDC);
}
{
// TODO: Add your specialized code here and/or call the base class
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);
}void CBtmpbutton::DrawPassButton()
{
m_pDC->SetBkMode(TRANSPARENT);
CBrush greenbr;
greenbr.CreateSolidBrush(RGB(0,255,0));
m_pDC->FillRect(m_rect,&greenbr);
SetWindowText(m_titlestr);
greenbr.DeleteObject();
}void CBtmpbutton::DrawPendButton()
{
m_pDC->SetBkMode(TRANSPARENT);
CBrush yellowbr;
yellowbr.CreateSolidBrush(RGB(255,255,0));
m_pDC->FillRect(m_rect,&yellowbr);
SetWindowText(m_titlestr);
yellowbr.DeleteObject();}void CBtmpbutton::DrawTestFocusButton()
{
m_pDC->SetBkMode(TRANSPARENT);
CBrush bluebr;
bluebr.CreateSolidBrush(RGB(145,120,0));
m_pDC->FillRect(m_rect,&bluebr);
SetWindowText(m_titlestr);
bluebr.DeleteObject();
}
以下为在CAbutnView视类中增加的对WM_CREATE的消息处理int CAbutnView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
::CreateWindowEx(WS_EX_WINDOWEDGE,"button","aaa",WS_CHILD | WS_VISIBLE,120,120,75,35,this->m_hWnd,(HMENU)1,::GetModuleHandle(NULL),NULL); //仅创建这个按钮时,程序显示正常
m_pbmpbtn.Create("aaa",WS_CHILD | WS_VISIBLE,CRect(185,100,255,135),this,1);//创建这个按钮后运行,程序显示按钮的视类中看到了这个按钮,但是程序一闪而过,跟踪确认只要增加重载DrawItem函数这部分功能的代码,程序就会一闪而过,否则视类显示正常。请大家帮指导知道这个DrawItem函数重载是的要领,我这个程序哪里出了问题?
return 0;
}
void CXPButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
//从lpDrawItemStruct获取控件的相关信息
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
int nSaveDC=pDC->SaveDC();
UINT state = lpDrawItemStruct->itemState;
POINT pt ;
TCHAR strText[MAX_PATH + 1];
::GetWindowText(m_hWnd, strText, MAX_PATH);
//画按钮的外边框,它是一个半径为5的圆角矩形
pt.x = 5;
pt.y = 5;
CPen* hOldPen = pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rect, pt);
我上面的也只是把这个pDC指针保存到了成员变量指针m_pDC中了,现在我完全照着XPButtonDemo上的做把成员变量指针m_pDC删除,将之以 CDC *pDC替代,然后编译连接后运行效果一样的一闪而过,事实上这两种形式其实都是一样的,都是保存CDC的指针,你说从CDC::FromHandle(lpDrawItemStruct->hDC);得到的是临时对象的指针,是啊,但是,系统每次调用DrawItem函数时不都是会重新对CDC *pDC赋上当次的正确的DC指针了嘛,我想应该不是这个问题吧
另因为我测试这个自绘按钮类的时候只创建了一个按钮,其按钮的ID标号为1,并且将m_testfocusid 初始化为1了,所以程序调用DrawItem函数时应该只会运行case 1: 中DrawTestFocusButton(); 下了断点后跟踪发现,它运行这一个函数DrawTestFocusButton();根本就不运行pDC->RestoreDC(nSaveDC);这一句,就又循环进了DrawItem函数又从CRect rect = lpDrawItemStruct->rcItem;这句运行到DrawTestFocusButton();函数,如此循环,好象也循环无止尽!
还有其它问题吗?