鼠标划进按钮再划出再划进,速度快一点或慢一点各种尝试,会发现闪炼现象(即中间会一个白色底短时间内出现),请做过相关开发的大神们帮解决
如下是一个vs2010中建立的测试工程,打包在下面链接。
链接: https://pan.baidu.com/s/1jnL4f6qapbUBP3od4WoQRw 密码: 1jqk
(ps: C币是不是给多了还是不够,C友们不要担心问题难,本人因为没做过贴图这块学习和开发,把重心放在别的地方,奉行拿来主义,这工程中的按钮自绘类我就是从别的C友博客中直接拷贝来的,我想在人家博客下面问,不知道何年马月才可能被回复,人家也不一定愿意去再看这问题,这个按钮闪烁问题解决了,我就谢谢各位了,可惜CSDN没法散币给帮助的大家)
(再PS:这闪烁问题我尝试解决,但是能力不够,我觉得问题最可能在 SelfControlPublic.cpp 这个类中,大楖是没有使用到双缓冲,但是不知道怎么改,我只想问题再点解决,所以提供下我的猜测)
(再再PS:下面的zqbnqsdsmd网友,我不需要这种贴一大段代码,我要修改好的工程或者一段能解决的方法,只采纳能解决我问题的答案,你这样贴,和我百度搜索各种尝试有啥区别)
void CPngButton::PaintParent()
{
CRect rect;
GetWindowRect(&rect);
Invalidate();
//GetParent()->ScreenToClient(&rect);
//GetParent()->InvalidateRect(&rect); //这里会导致闪烁,只能用双缓冲
}
我把这个函数改了一下,移动进去时候不会闪了,不知老兄是否还有时间看看啊,其实我这里有完整的一个很好用的图片按钮,如果老兄有兴趣,加个联系方式我发给你,你觉得满意也好结贴
给dialog加上 WS_CLIPCHILDREN .
这样, 父窗口重画的时候, 子窗口可以不用重画,直接把子窗口的东西clip过来.
WS_CLIPCHILDREN 属性!!!
1 CDC buttonDC;
2 CBitmap bitmapTrans;
3 BITMAP bmp;
4 CDC mem;
5 CRect rc;
6 buttonDC.Attach(lpDrawItemStruct->hDC);//得到用于绘制按钮的DC
7 mem.CreateCompatibleDC(&buttonDC);//准备向按钮区域传输图形
8
9 if (lpDrawItemStruct->CtlID == IDC_BUTTON1)
10 {
11 rc = lpDrawItemStruct->rcItem;//获取按钮所占的矩形大小
12 UINT state = lpDrawItemStruct->itemState;//获取按钮当前的状态,不同状态绘制不同的按钮
13 if (state & ODS_FOCUS)//如果按钮已经取得焦点,绘制选中状态下的按钮
14 {
15 bitmapTrans.LoadBitmap(IDB_BITMAP2);
16 bitmapTrans.GetBitmap(&bmp);
17 CBitmap * old = mem.SelectObject(&bitmapTrans);
18 //向按钮传输位图,使用stretcnblt可以使图片随按钮大小而改变
19 buttonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
20 mem.SelectObject(old);
21 bitmapTrans.DeleteObject();
22 }
23 else //如果按钮已经取得焦点,绘制选中状态下的按钮
24 {
25 bitmapTrans.LoadBitmap(IDB_BITMAP3);
26 CBitmap *old2 = mem.SelectObject(&bitmapTrans);
27 bitmapTrans.GetBitmap(&bmp);
28 CBitmap *old=mem.SelectObject(&bitmapTrans);
29 buttonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
30 mem.SelectObject(old2);
31 bitmapTrans.DeleteObject();
32 }
33 }
void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
// 1,查询当前系统“拖动显示窗口内容”设置
SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bDragFullWindow, NULL);
// 2,如果需要修改设置,则在每次进入CDialog::OnNcLButtonDown默认处理之前修改
if(m_bDragFullWindow)
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, NULL);
// 3,默认处理,系统会自动绘制虚框
CDialog::OnNcLButtonDown(nHitTest, point);
// 4,默认处理完毕后,还原系统设置
if(m_bDragFullWindow)
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, NULL);
}
void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
// 1,查询当前系统“拖动显示窗口内容”设置
SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bDragFullWindow, NULL);
// 2,如果需要修改设置,则在每次进入CDialog::OnNcLButtonDown默认处理之前修改
if(m_bDragFullWindow)
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, NULL);
// 3,默认处理,系统会自动绘制虚框
CDialog::OnNcLButtonDown(nHitTest, point);
// 4,默认处理完毕后,还原系统设置
if(m_bDragFullWindow)
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, NULL);
}
添加 以下代码在 .h中:
//member variable
CPoint m_oldPt;
CPoint m_offsetPt;
CRect m_wndRc;
CRect m_newRc;
CRect m_newSizeRect;
CRect m_oldSizeRect;
BOOL m_bDrawFrame;
BOOL m_needFinish;
BOOL m_bDrawSize;
BOOL m_needSize;
LRESULT OnMoving(WPARAM,LPARAM);
LRESULT OnExitSizeMove(WPARAM,LPARAM);
LRESULT OnEnterSizeMove(WPARAM, LPARAM);
LRESULT OnSizing(WPARAM,LPARAM);
DECLARE_MESSAGE_MAP()
添加 以下代码在 .CPP中:
ON_MESSAGE(WM_MOVING,OnMoving)
ON_MESSAGE(WM_EXITSIZEMOVE,OnExitSizeMove)
ON_MESSAGE(WM_ENTERSIZEMOVE,OnEnterSizeMove)
ON_MESSAGE(WM_SIZING,OnSizing)
END_MESSAGE_MAP()
下面是简单的处理函数,你可以扩展
LRESULT CPrimeNumDlg::OnEnterSizeMove(WPARAM, LPARAM){
GetWindowRect(&m_wndRc);
m_oldSizeRect = m_wndRc;
m_oldPt = CPoint(m_wndRc.left,m_wndRc.top);
m_offsetPt = CPoint(0,0);
m_bDrawFrame = FALSE;
return TRUE; //we don't process this message
}
LRESULT CPrimeNumDlg::OnExitSizeMove(WPARAM,LPARAM){
if(m_needFinish){
CRect rect;
rect.left = m_oldPt.x - m_offsetPt.x;
rect.top = m_oldPt.y - m_offsetPt.y;
rect.right = rect.left + m_wndRc.Width();
rect.bottom = rect.top + m_wndRc.Height();
DrawDashFrame(rect);
m_needFinish = FALSE;
SetWindowPos(NULL,m_oldPt.x,m_oldPt.y,m_wndRc.Width(),m_wndRc.Height(),\
SWP_NOSENDCHANGING ); //prevent receiving more moving message
GetWindowRect(&m_wndRc);
m_oldPt = CPoint(m_wndRc.left,m_wndRc.top);
m_offsetPt = CPoint(0,0);
m_bDrawFrame = FALSE;
}
if(m_needSize){
m_bDrawSize = FALSE;
m_needSize = FALSE;
DrawDashFrame(m_oldSizeRect);
SetWindowPos(NULL,m_newSizeRect.left,m_newSizeRect.top,m_newSizeRect.Width(),m_newSizeRect.Height(),\
SWP_NOSENDCHANGING ); //prevent receiving more moving message
}
return TRUE; //we don't process this message
}
void CPrimeNumDlg::DrawDashFrame(CRect& rect){
CPen pen;
pen.CreatePen(PS_DASH,1,RGB(0,0,0));
CWnd* p_desktop = GetDesktopWindow();
CDC* p_dc_desktop = p_desktop->GetWindowDC();
p_dc_desktop->SetROP2(R2_XORPEN );
CPen* p_old_pen = p_dc_desktop->SelectObject(&pen);
p_dc_desktop->MoveTo(rect.left,rect.top);
p_dc_desktop->LineTo(rect.left,rect.bottom);
p_dc_desktop->MoveTo(rect.left,rect.bottom);
p_dc_desktop->LineTo(rect.right,rect.bottom);
p_dc_desktop->MoveTo(rect.right,rect.bottom);
p_dc_desktop->LineTo(rect.right,rect.top);
p_dc_desktop->MoveTo(rect.right,rect.top);
p_dc_desktop->LineTo(rect.left,rect.top);
p_dc_desktop->SelectObject(p_old_pen);
p_desktop->ReleaseDC(p_dc_desktop);
}
LRESULT CPrimeNumDlg::OnMoving(WPARAM wp,LPARAM lp){
RECT* p_rc = (RECT*)lp;
m_newRc = CRect(p_rc);
CPoint pt;
GetCursorPos(&pt);
if(!m_bDrawFrame){
m_bDrawFrame = TRUE;
m_offsetPt = CPoint(pt.x - m_wndRc.left,pt.y - m_wndRc.top);
m_oldPt = pt;
CRect rect;
rect.left = m_oldPt.x - m_offsetPt.x;
rect.top = m_oldPt.y - m_offsetPt.y;
rect.right = rect.left + m_wndRc.Width();
rect.bottom = rect.top + m_wndRc.Height();
DrawDashFrame(rect);
m_needFinish = TRUE;
}
else{
CRect rect;
rect.left = m_oldPt.x - m_offsetPt.x;
rect.top = m_oldPt.y - m_offsetPt.y;
rect.right = rect.left + m_wndRc.Width();
rect.bottom = rect.top + m_wndRc.Height();
DrawDashFrame(rect);
rect.left = pt.x - m_offsetPt.x;
rect.top = pt.y - m_offsetPt.y;
rect.right = rect.left + m_wndRc.Width();
rect.bottom = rect.top + m_wndRc.Height();
DrawDashFrame(rect);
m_oldPt = pt;
}
int width = p_rc->right - p_rc->left;
int height = p_rc->bottom - p_rc->top;
p_rc->left = m_wndRc.left;
p_rc->right = p_rc->left + width;
p_rc->top = m_wndRc.top;
p_rc->bottom = p_rc->top + height;
return FALSE; //we process this message
}
LRESULT CPrimeNumDlg::OnSizing(WPARAM wp,LPARAM lp){
m_needSize = TRUE;
if(!m_bDrawSize){
DrawDashFrame(m_wndRc);
m_oldSizeRect = m_wndRc;
m_bDrawSize = TRUE;
}
else{
RECT* p_rc = (RECT*)lp;
m_newSizeRect = CRect(p_rc);
DrawDashFrame(m_oldSizeRect);
DrawDashFrame(m_newSizeRect);
p_rc->left = m_wndRc.left;
p_rc->right = m_wndRc.right;
p_rc->top = m_wndRc.top;
p_rc->bottom = m_wndRc.bottom;
m_oldSizeRect = m_newSizeRect;
}
return FALSE; //we don't process this message
}
LRESULT CPrimeNumDlg::OnEnterSizeMove(WPARAM, LPARAM){
GetWindowRect(&m_wndRc);
m_oldSizeRect = m_wndRc;
m_oldPt = CPoint(m_wndRc.left,m_wndRc.top);
m_offsetPt = CPoint(0,0);
m_bDrawFrame = FALSE;
return TRUE; //we don't process this message
}
LRESULT CPrimeNumDlg::OnEnterSizeMove(WPARAM, LPARAM){
GetWindowRect(&m_wndRc);
m_oldSizeRect = m_wndRc;
m_oldPt = CPoint(m_wndRc.left,m_wndRc.top);
m_offsetPt = CPoint(0,0);
m_bDrawFrame = FALSE;
return TRUE; //we don't process this message
}
#if(WINVER >= 0x0500)
#define WM_NCMOUSEHOVER 0x02A0
#define WM_NCMOUSELEAVE 0x02A2
#endif /* WINVER >= 0x0500 */
据此手动添加如下代码:
#ifndef WM_MOUSELEAVE
#define WM_MOUSELEAVE 0x02A3
#endif
对于WM_MOUSEHOVER消息也是一样:
#ifndef WM_MOUSEHOVER
#define WM_MOUSEHOVER 0x02A1
#endif
重新编译即可。
另外上篇文章中说道TrackMouseEvent函数用来投递WM_MOUSELEAVE和WM_MOUSEHOVER消息。貌似这个函数在Windows CE操作系统下也找不到。找不到就不用它了,自己直接调用PostMessage投递出去算了。
比如:
::PostMessage(m_hWnd, WM_MOUSELEAVE, 0, 0);
那么当光标滑过按钮时,会触发WM_MOUSEMOVE消息,在这个函数中如何判断光标是在按钮上停留着还是离开了,从而是发送WM_MOUSELEAVE消息还是WM_MOUSEHOVER消息呢?这个不难吧,至少PtInRect函数可以搞定。
自己测试了一下,完全可以。
MFC下按钮自绘的实现(三)
按钮的绘制主要在DrawItem函数中来完成,下面来简单的绘制一下。
第一步先绘制按钮的外边框。定义了一个成员变量:
CPen m_OutBorderPen;
这是一个用来绘制按钮外边框的画笔,在类的构造函数中创建它,在类的析构函数中销毁之。然后在DrawItem函数中开始绘制按钮的外边框:
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
int nSavedDC = pDC->SaveDC();
// 绘制按钮的外边框
POINT pt;
pt.x = 5;
pt.y = 5;
CPen *pOldPen = pDC->SelectObject(&m_OutBorderPen);
pDC->RoundRect(&rect, pt);
pDC->SelectObject(pOldPen);
编译之后执行一下程序,看下效果:
按钮的轮廓出来了。
第二步绘制按钮的底色。
// 绘制按钮的底色
rect.DeflateRect(3, 3, 3, 3);
CBrush *pOldBrush = pDC->SelectObject(&m_BackgroundBrush);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
这里只是简单的示范一下而已,画出来的按钮不一定好看。这里将按钮的底色设置为纯白色。程序的执行效果如下:
第三步绘制按钮的文本。
// 绘制按钮文本
TCHAR strButtonText[MAX_PATH + 1];
::GetWindowText(m_hWnd, strButtonText, MAX_PATH); // 获取按钮文本
if (strButtonText != NULL)
{
CFont *pFont = GetFont();
CFont *pOldFont = pDC->SelectObject(pFont);
CSize szExtent = pDC->GetTextExtent(strButtonText, _tcslen(strButtonText));
CRect rectText = lpDrawItemStruct->rcItem;
rectText.DeflateRect(rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2, rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2);
int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
pDC->DrawText(strButtonText, -1, rectText, DT_WORDBREAK | DT_CENTER);
pDC->SelectObject(pOldFont);
pDC->SetBkMode(nOldBkMode);
}
重新编译,执行效果如下:
按钮的基本外观已经绘制出来了。接下来还要绘制按钮按下时,光标滑过时,光标离开时等等状态下按钮的外观。当然还要探索一下圆形按钮,三角形按钮,以及不规则图形按钮的绘制。累了,先写到这里。
MFC下按钮自绘的实现(四)
接下来为自绘的按钮绘制不同状态下的外观,首先绘制按钮按下时的状态。一般在按钮按下时,按钮的文本会向右下方移动一个微小的距离,使其看起来有被“压下”的视觉。
通过如下代码获取按钮的状态:
UINT state = lpDrawItemStruct->itemState;
然后在DrawItem函数中绘制按钮文本之前(DrawText)添加如下代码:
if (state & ODS_SELECTED)
{
rectText.OffsetRect(1, 1);
}
编译运行程序,看下效果。
按钮正常状态:
按钮被按下时:
对比一下,可以看出按钮按下时,按钮上文本向右下方移动一小段距离。测试了一下,效果还不错。
接下来绘制当光标位于按钮之上但按钮并没有被按下时的状态。这里仅仅大致的介绍一下我的方法。
首先在OnMouseMove函数中,添加如下代码:
if (!m_bOver)
{
m_nTimerId = SetTimer(1, 50, TimerProc);
m_bOver = TRUE;
}
其中m_bOver是用来标记光标此时是否在按钮之上的BOOL类型的变量。当光标经过按钮时,触发OnMouseMove函数,在此函数中设置一个定时器,定时时间为50ms,定时时间到了之后将触发TimerProc回调函数。在TimerProc函数中不断的判断此时光标停留在按钮之上,还是已经离开了按钮。
POINT CursorPos;
RECT ButtonRect;
::GetCursorPos(&CursorPos);
::ScreenToClient(hwnd, &CursorPos);
::GetClientRect(hwnd, &ButtonRect);
if (!::PtInRect(&ButtonRect, CursorPos))
{
::PostMessage(hwnd, WM_MOUSELEAVE, 0, 0);
}
else
{
::PostMessage(hwnd, WM_MOUSEHOVER, 0, 0);
}
HBRUSH MyButtonEx::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,255));
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
//添加绘图函数
void CMy40_mybuttonDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your message handler code here and/or call default
CDC ButtonDC;
CBitmap bitmapTrans;
BITMAP bmp;
CDC mem;
CRect rc;
//得到用于绘制按钮的DC
ButtonDC.Attach(lpDrawItemStruct->hDC);
//准备用于向按钮区域传输位图
mem.CreateCompatibleDC(&ButtonDC);
//获取按钮所占的矩形大小
rc=lpDrawItemStruct->rcItem;
//获取按钮目前所处的状态,根据不同的状态绘制不同的按钮
UINT state = lpDrawItemStruct->itemState;
//如果按钮已经得到焦点,绘制选中状态下的按钮
if(state&ODS_FOCUS)
{
bitmapTrans.LoadBitmap(IDB_BITMAP1);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
//向按钮所在位置传输位图
//使用StretcnBlt的目的是为了让位图随按钮的大小而改变
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
mem.SelectObject(old);
bitmapTrans.DeleteObject();
//设置文字背景为透明
ButtonDC.SetBkMode(TRANSPARENT);
ButtonDC.DrawText("已选中",&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
else
{
bitmapTrans.LoadBitmap(IDB_BITMAP2);
CBitmap *old2 = mem.SelectObject(&bitmapTrans);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
ButtonDC.SetBkMode(TRANSPARENT);
ButtonDC.DrawText("未选中",&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
mem.SelectObject(old2);
bitmapTrans.DeleteObject();
}
CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
CBCDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CPoint ptCenter;
CRect rect,ellipseRect;
GetClientRect(&rect);
ptCenter = rect.CenterPoint();
for(int i=20;i>0;i--)
{
ellipseRect.SetRect(ptCenter,ptCenter);
ellipseRect.InflateRect(i*10,i*10);
pDC->Ellipse(ellipseRect);
}
CBitmap bit;
bit.LoadBitmapA(IDB_BITMAP1);
BITMAP bm;
bit.GetBitmap(&bm);
CDC memDc;
memDc.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = memDc.SelectObject(&bit);
CRect rect;
GetClientRect(&rect);
pDC->SetStretchBltMode(COLORONCOLOR);//这个模式不设置的话会导致图片严重失真
pDC->StretchBlt(0,0,rect.Width() ,rect.Height(),
&memDc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
memDc.SelectObject(pOldBitmap);
memDc.DeleteDC(); //删除DC
bm.DeleteObject(); //删除位图
Q: OnEraseBkgnd函数中返回TRUE或FALSE有什么区别?
A:
WM_ERASEBKGND
Return Values
An application should return nonzero if it erases the background; otherwise, it should return zero.
A:true表示已处理背景刷新,false表示需要在OnPaint里处理
Q:在OnEraseBkgnd中绘制对话框的背景图片和在OnPaint中绘制对话框的背景图片由什么区别,另外OnEraseBkgnd和CtlColor有什么区别?
A:
OnEraseBkgnd是在窗口大小发生改变等情况下发生的,它将绘制窗口背景;而OnCtlColor是当窗口的控件需要绘制时发生的,它将绘制窗口的
控件。
A:
OnEraseBkgnd :在窗口背景需要重绘时调用.
OnPaint : 此时OnEraseBkgnd已经调用过了,所以在此响应函数体内对背景进行的操作将覆盖OnEraseBkgnd中所做的操作.
OnCtlColor : 有于在窗口将要被(第一次)绘制时响应,子窗口可以通过发关WM_CTLCOLOR请求父窗口传来一个HBRUSH.
void CWinceSendDlg::DrawCZButton(int number,int color,CString name)
{
CRect rct;
CBrush m_FillActive;
CBrush* pOldBrush;
CDC pDC=GetDC();
int num_row=(number-1)/column+1;
int num_column=(number-1)%column+1;
rct.left=start_x+(num_column-1)(btn_width+space_x);
rct.top=start_y+(num_row-1)*(btn_height+space_y);
rct.right=btn_width+start_x+(num_column-1)*(btn_width+space_x);
rct.bottom=btn_height+start_y+(num_row-1)*(btn_height+space_y);
//////////////////////////////////////////////////////////////////画边框
CPen m_BoundryPen;
CPen* hOldPen;
m_BoundryPen.CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
POINT pt ;
pt.x = 5;
pt.y = 5;
hOldPen = pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rct, pt);
pDC->SelectObject(hOldPen);
rct.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)));
m_BoundryPen.DeleteObject();
////////////////////////////////////////////////////////////填充矩形
pOldBrush = pDC->SelectObject(&m_FillActive);
if(color==1)//还原
{
CBrush br;
//CRect rect;
//int nWidth = rct.Width();
//int nHeight = rct.Height();
br.CreateSolidBrush(RGB(95, 115, 150));
//rect.SetRect(rct.left, rct.top, nWidth + 2, nHeight + 1);
pDC->FillRect(&rct, &br);
br.DeleteObject();
}
else
{
CBrush brBk[128];
int nWidth = rct.right-rct.left;
int nHeight = rct.bottom-rct.top;
int i;
CRect rect;
if(color==2)
{
for (i = 0; i < 128; i ++)
{
brBk[i].CreateSolidBrush(RGB(95 - (i / 2), 115 - (i / 3), 150 - (i / 4)));
}
}
else
{
for (i = 0; i < 128; i ++)
{
brBk[i].CreateSolidBrush(RGB(254 - (i / 3), 85 - (i / 3), 105 - (i / 4)));
}
}
for (i = rct.top; i < rct.bottom; i ++)
{
rect.SetRect(rct.left, i, rct.right, i+1);
pDC->FillRect(&rect, &brBk[(i-rct.top)*127/nHeight]);
}
for ( i = 0; i < 128; i ++)
brBk[i].DeleteObject();
}
pDC->SelectObject(pOldBrush);
m_FillActive.DeleteObject();
////////////////////////////////////////////////////////////显示按钮的文本
CFont* hFont = GetFont();
CFont* hOldFont = pDC->SelectObject(hFont);
rct.OffsetRect((rct.Width() - rct.Width())/2, rct.Height() - rct.Height()/2);
int nMode = pDC->SetBkMode(TRANSPARENT);
rct.OffsetRect(1, -5);
pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
pDC->DrawText(name, -1, rct, DT_WORDBREAK | DT_CENTER);
rct.OffsetRect(-1, -1);
pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
pDC->DrawText(name, -1, rct, DT_WORDBREAK | DT_CENTER);
pDC->SelectObject(hOldFont);
pDC->SetBkMode(nMode);
ReleaseDC(pDC);
//UpdateWindow();
}
void CWinceSendDlg::ClearArea(int x, int y)
{
CBrush cBrush(RGB(225,232,243));
RECT rect;
CDC* pDC = GetDC();
rect.left=x;
rect.top=y;
rect.right=x+460;
rect.bottom=y+300;
pDC->FillRect(&rect,&cBrush);
ReleaseDC(pDC);
}
void CWinceSendDlg::OnLButtonDown(UINT nFlags, CPoint point) //识别点击按钮
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(nFlags == MK_LBUTTON)
{
if(button_status == true)
{
for(int i=0;i {
for(int j=0;j {
if((point.x>=start_x+j*(space_x+btn_width))&&(point.x<=start_x+j*(space_x+btn_width)+btn_width)&&(point.y>=start_y+i*(btn_height+space_y))&&(point.y<=start_y+i*(btn_height+space_y)+btn_height))
{
//printf("%d %d\n",row,column);
station_number = i*column+j+1;
DrawCZButton(station_number,0,m_strZH[station_number]);
OnButton(station_number);
button_status = false;
}
}
}
}
}
__super::OnLButtonDown(nFlags, point);
}
oid CXPButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTracking = _TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
}
接着添加WM_MOUSELEAVE和WM_MOUSEHOVER消息消息函数。在CXPButton类的声明中(即在XPButton.h文件中)找到afx_msg void OnMouseMove(UINT nFlags, CPoint point);的函数声明,紧接其下输入
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
然后在XPButton.cpp文件中找到ON_WM_MOUSEMOVE(),紧接其后输入
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
当然最后还有函数的实现了,详细代码可见本篇提供的源程序,这里就不再重复了。
DRAWITEMSTRUCT结构的定义如下:
typedef struct tagDRAWITEMSTRUCT {
UINT CtlType; //控件类型
UINT CtlID; //控件ID
UINT itemID; //菜单项、列表框或组合框中某一项的索引值
UINT itemAction; //控件行为
UINT itemState; //控件状态
HWND hwndItem; //父窗口句柄或菜单句柄
HDC hDC; //控件对应的绘图设备句柄
RECT rcItem; //控件所占据的矩形区域
DWORD itemData; //列表框或组合框中某一项的值
} DRAWITEMSTRUCT, *PDRAWITEMSTRUCT, *LPDRAWITEMSTRUCT;