MFC 实现划线左右滚动(有闪屏问题,双缓冲技术未解决)

#define IDR_MENU_SET                    1115
#define ID_SET_WIDTHCOLOR               1116

 

#define Black RGB(0,0,0)
#define Red RGB(255,0,0)
#define Green RGB(0,255,0)
#define Blue RGB(0,0,255)

定义的成员:

CPoint m_pntStart;//存放直线的起点坐标
CPoint m_pntEnd;  //存放直线的终点坐标
COLORREF m_Color;
int m_PenWidth;
int m_CycleTime;
bool m_bCycle;

 

1. .rc文件中添加菜单:

IDR_MENU_SET MENU
BEGIN
    POPUP "SetDlg"
    BEGIN
        MENUITEM "设置宽度和颜色",                     ID_SET_WIDTHCOLOR
    END
END

2. 在窗口的OnRButtonDown方法中加载菜单:

CDialog::OnRButtonDown(nFlags, point);
 ::GetCursorPos(&point);
 CMenu menu;
 BOOL bIsSucces;
 bIsSucces =menu.LoadMenu(IDR_MENU_SET);
 if(!bIsSucces)
 {
  return;
 }
 CMenu *pSubMenu;
 pSubMenu = menu.GetSubMenu(0);
 pSubMenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);

3. 设置对应处理方法:ON_COMMAND(ID_SET_WIDTHCOLOR, &CDrawtestDlg::OnWidthColorSet)

void CDrawtestDlg::OnWidthColorSet()
{
 CSettingParam SettingParam;
 if (IDOK == SettingParam.DoModal())
 {
  CString sPenWidth = SettingParam.m_WidthValue;
  m_PenWidth = atoi(sPenWidth);
  CString sColor = SettingParam.m_ColorValue;
  if (sColor.Compare("Black") == 0)
  {
   m_Color = Black;
  }
  else if (sColor.Compare("Red") == 0)
  {
   m_Color = Red;
  }
  else if (sColor.Compare("Green") == 0)
  {
   m_Color = Green;
  }
  else if (sColor.Compare("Blue") == 0)
  {
   m_Color = Blue;
  }
  else
  {}

  m_CycleTime = atoi(SettingParam.m_CycleValue);
  HANDLE hHandle = (HANDLE)_beginthreadex(NULL,
                                                                                         0,
                                                                                         CDrawtestDlg::Proc,
                                                                                         (LPVOID)this,
                                                                                         0,
                                                                                         NULL);
 }
 return;
}

 

4. 在窗体的OnInitDialog()方法中:

最大化显示窗口:

ShowWindow(SW_SHOWMAXIMIZED);

 

5. 在线程方法中:

unsigned __stdcall CDrawtestDlg::Proc(LPVOID pParam)
{
 CDrawtestDlg *pThis = (CDrawtestDlg*)pParam;
 int nClock = 0;
 while (1)
 {
  if ((nClock >= 0) && (nClock <= pThis->m_CycleTime-1))
  {
   pThis->m_bCycle = true;
  }
  else if ((nClock >= pThis->m_CycleTime) && (nClock <= (pThis->m_CycleTime*2 - 1)))
  {
   pThis->m_bCycle = false;
  }
  else
  {}

  nClock ++;
  if (nClock == pThis->m_CycleTime*2)
  {
   nClock = 0;
  }
  pThis->SendMessage(WM_PAINT);     //发送WM_PAINT消息,调用窗体的OnPaint方法
  pThis->Invalidate(FALSE);    //手动重绘..默认参数为true,系统自动擦除背景后重绘,参数为false时,不会自动擦除背景,节省时间
  Sleep(1000);
 }
}

6. 在OnPaint方法中:

CPaintDC dc(this);
 CRect rect;
 GetClientRect(&rect);         //获得窗口客户区

 

//自定义代码写在else部分
  // 创建内存缓存DC
  CDC memDC; 
  memDC.CreateCompatibleDC(&dc);

  CBitmap bufferMemBitmap;
  bufferMemBitmap.CreateCompatibleBitmap(&dc, rect.Width(),rect.Height()); 
  memDC.SelectObject(&bufferMemBitmap); 
  CBrush whiteBrush;
  whiteBrush.CreateSolidBrush(RGB(255, 255, 255)); 
  memDC.FillRect(CRect(0, 0, rect.Width(), rect.Height()),&whiteBrush);

  CPen my_pen;
  my_pen.CreatePen(PS_SOLID,m_PenWidth,m_Color);
  CPen *oldPen = memDC.SelectObject(&my_pen);

  if (m_bCycle)
  {
   //向右移动
   int nLineWidth = m_PenWidth;                 //线型宽度
   int nWhite = 30 + nLineWidth;                           //空白区域宽度
   int nLineCount = (rect.right-rect.left) / (nLineWidth + nWhite);       //画整数个线+空白
   int nExceptLineNum =  (rect.right-rect.left) %(nLineWidth + nWhite);    //除去整数个“线+空白”后,剩余空间大小
   static int sStep = 0;             //步长
   long nTempValue = 0;
   bool bNeedIncrease = false;
   //画出整数个线条+空白
   for (int i=0; i<nLineCount; ++i)
   {
    m_pntStart.x = i*(nLineWidth + nWhite) + sStep;
    m_pntStart.y = rect.top ;
    m_pntEnd.x =  i*(nLineWidth + nWhite) + sStep;
    m_pntEnd.y = rect.bottom;
    memDC.MoveTo(m_pntStart);          //画直线
    memDC.LineTo(m_pntEnd);
    if ((0 == i) && ((m_pntStart.x-rect.left) >= (nLineWidth + nWhite)))
    {
     bNeedIncrease = true;
     nTempValue = m_pntStart.x - nLineWidth - nWhite;
     m_pntStart.x = nTempValue;
     m_pntStart.y = rect.top ;
     m_pntEnd.x =  nTempValue;
     m_pntEnd.y = rect.bottom;
     memDC.MoveTo(m_pntStart);          //画直线
     memDC.LineTo(m_pntEnd);
    }
   }

   if (bNeedIncrease)
   {
    sStep = nTempValue;
    bNeedIncrease = false;
   }
   sStep += (28 + nLineWidth);
  }
  //memDC.Rectangle(m_pntStart.x,m_pntStart.y,m_pntEnd.x,m_pntEnd.y);

  if (!m_bCycle)
  {
   //向左移动
   int nLineWidth = m_PenWidth;                 //线型宽度
   int nWhite = 30 + nLineWidth;                           //空白区域宽度
   int nLineCount = (rect.right-rect.left) / (nLineWidth + nWhite);       //画整数个线+空白
   //int nExceptLineNum =  (rect.right-rect.left) %(nLineWidth + nWhite);    //除去整数个“线+空白”后,剩余空间大小
   static int sStep = 0;             //步长
   long nTempValue = 0;
   bool bNeedIncrease = false;
   //画出整数个线条+空白
   for (int i=0; i<nLineCount; ++i)
   {
    m_pntStart.x = rect.right - i*(nLineWidth + nWhite) - sStep;
    m_pntStart.y = rect.top ;
    m_pntEnd.x =   rect.right - i*(nLineWidth + nWhite) - sStep; //i*(nLineWidth + nWhite) + sStep;
    m_pntEnd.y = rect.bottom;
    memDC.MoveTo(m_pntStart);          //画直线
    memDC.LineTo(m_pntEnd);
    if ((0== i) && ((rect.right - m_pntStart.x) >= (nLineWidth + nWhite)))
    {
     bNeedIncrease = true;
     nTempValue = m_pntStart.x + nLineWidth + nWhite;
     m_pntStart.x = nTempValue;
     m_pntStart.y = rect.top ;
     m_pntEnd.x =  nTempValue;
     m_pntEnd.y = rect.bottom;
     memDC.MoveTo(m_pntStart);          //画直线
     memDC.LineTo(m_pntEnd);
    }
   }

   if (bNeedIncrease)
   {
    sStep = rect.right - nTempValue;
    bNeedIncrease = false;
   }
   sStep += (28 + nLineWidth);
  }

  // 将内存缓冲DC拷贝至当前DC  
  dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),&memDC, 0, 0, SRCCOPY); 
  bufferMemBitmap.DeleteObject(); 
  memDC.DeleteDC(); 

  //返还之前画笔
  dc.SelectObject(oldPen);
 }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值