老爸我爱你
2018-05-17 04:15
采纳率: 50%
浏览 1.9k
已采纳

MFC 自绘按钮划过或点击会出现闪烁问题,求助精通GDI高手解决

鼠标划进按钮再划出再划进,速度快一点或慢一点各种尝试,会发现闪炼现象(即中间会一个白色底短时间内出现),请做过相关开发的大神们帮解决

如下是一个vs2010中建立的测试工程,打包在下面链接。
链接: https://pan.baidu.com/s/1jnL4f6qapbUBP3od4WoQRw 密码: 1jqk

(ps: C币是不是给多了还是不够,C友们不要担心问题难,本人因为没做过贴图这块学习和开发,把重心放在别的地方,奉行拿来主义,这工程中的按钮自绘类我就是从别的C友博客中直接拷贝来的,我想在人家博客下面问,不知道何年马月才可能被回复,人家也不一定愿意去再看这问题,这个按钮闪烁问题解决了,我就谢谢各位了,可惜CSDN没法散币给帮助的大家)

(再PS:这闪烁问题我尝试解决,但是能力不够,我觉得问题最可能在 SelfControlPublic.cpp 这个类中,大楖是没有使用到双缓冲,但是不知道怎么改,我只想问题再点解决,所以提供下我的猜测)

(再再PS:下面的zqbnqsdsmd网友,我不需要这种贴一大段代码,我要修改好的工程或者一段能解决的方法,只采纳能解决我问题的答案,你这样贴,和我百度搜索各种尝试有啥区别)

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

17条回答 默认 最新

  • 白色一大坨 2018-05-25 07:13
    已采纳

    void CPngButton::PaintParent()
    {
    CRect rect;
    GetWindowRect(&rect);
    Invalidate();
    //GetParent()->ScreenToClient(&rect);
    //GetParent()->InvalidateRect(&rect); //这里会导致闪烁,只能用双缓冲
    }
    我把这个函数改了一下,移动进去时候不会闪了,不知老兄是否还有时间看看啊,其实我这里有完整的一个很好用的图片按钮,如果老兄有兴趣,加个联系方式我发给你,你觉得满意也好结贴

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • dabocaiqq 2018-05-17 04:36

    给dialog加上 WS_CLIPCHILDREN .
    这样, 父窗口重画的时候, 子窗口可以不用重画,直接把子窗口的东西clip过来.

    WS_CLIPCHILDREN 属性!!!

    评论
    解决 无用
    打赏 举报
  • dabocaiqq 2018-05-17 04:37

    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;

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:41

    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 }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:41
         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);  
    }  
    
    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:41

    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);

    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:42

    添加 以下代码在 .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);

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:42

    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
    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:42

    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

    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:42
     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
    
    }
    
    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:43

    #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);
    
    }
    
    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:43

    HBRUSH MyButtonEx::CtlColor(CDC* pDC, UINT nCtlColor)
    {
    pDC->SetBkMode(TRANSPARENT);

    pDC->SetTextColor(RGB(255,255,255));

    return (HBRUSH)GetStockObject(NULL_BRUSH);   
    

    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:43

    //添加绘图函数
    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);
    

    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:44

    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);

    }

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:44

    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(); //删除位图

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:45

    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.

    评论
    解决 无用
    打赏 举报
  • zqbnqsdsmd 2018-05-17 04:45

    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);
    }

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题