如题,请教这个VC程序,曲线图上两条十字线是怎么做的?
下边是这个曲线图的连接
http://www.vckbase.com/document/viewdoc/?id=1077
我用的edit控件制作这样的十字线,可是鼠标移动太快界面就变了,他这个图是怎么做到的?

解决方案 »

  1.   

    作者说他用的是MFC,那么我们就使用MFC看一下怎么实现这个功能:
    首先此程序界面上的光标不是默认的箭头,这意味着我们要手动把它设置成十字:
    SetCursor(LoadCursor(AfxGetInstanceHandle(), IDC_CROSS));
    或者干脆设置为空。接着在View类中添加Paint消息
    在OnPaint函数中添加如下代码:
    POINT pt;
    RECT rect;
    GetCursorPos(&pt);//得到当前光标坐标
    GetClientRect(&rect);//得到当前界面客户区矩形
    dc.MoveTo(pt.x, rect.top);//这个dc用的是OnPaint自带的CPaintDC
    dc.LineTo(pt.x, rect.bottom);//以光标为中心画纵线
    dc.MoveTo(rect.left, pt.y);
    dc.LineTo(rect.right, pt.y);//以光标为中心画横线当然如果只是这样的话程序只有在触发“重画”消息的时候才重新画这个十字,这显然不符合我们的期望。
    我们想要的是程序在触发“鼠标移动”的时候就重画这个十字所以要添加一个MouseMove消息
    并且在OnMouseMove函数中写下一行:Invalidate();//触发重画这样就实现了这个大十字。
      

  2.   

    当然如楼上所说,这个程序需要使用内存dcCDC mdc;
    dc.CreateCompatibleDC(&mdc);//创建兼容dc的内存mdc,这里的dc是CPaintDC,mdc是内存dc
    这样就可以和用普通dc一样向mdc里面画图了,
    比如
    mdc.MoveTO(...);
    mdc.LineTo(...);//画背景图表接着再画十字
    POINT pt;
    RECT rect;
    GetCursorPos(&pt);//得到当前光标坐标
    GetClientRect(&rect);//得到当前界面客户区矩形
    mdc.MoveTo(pt.x, rect.top);//这个mdc用的是内存dc
    mdc.LineTo(pt.x, rect.bottom);//以光标为中心画纵线
    mdc.MoveTo(rect.left, pt.y);
    mdc.LineTo(rect.right, pt.y);//以光标为中心画横线最后把mdc内容显示到屏幕dc上或者CPaintDC:
    BitBlt(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, mdc, 0, 0, SRCCOPY);
      

  3.   

    dc.MoveTo
    dc.LineTo
    想画什么样的都行长的,短的,粗的,细的,红的,绿的,虚线,实线,不知道楼主想问什么?
      

  4.   

    第一次在这上发帖,这么多朋友帮忙,感动啊^_^,先谢谢了!!!我也想到用双缓冲,可是做出来的窗口缩放时闪的更明显,不知道是为什么?我把程序贴出来,大家帮看看
    void CLUBOTestView::OnInitialUpdate()
    {
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
            OnTest();
    }
    void CLUBOTestView::OnTest() 
    {
    //  CDC *m_pDC;
    //  CDC MemDC;
    m_pDC = this->GetDC();                 // 获取设备上下文句柄  
    CRect rect;
    GetWindowRect(&rect);             // 获取显示/画图区域大小(物理范围)
    ScreenToClient(&rect);                 // 转换为客户区坐标

    nWidth = rect.Width();                 // 显示/画图区域x方向物理宽度
    nHeight = rect.Height();               // 显示/画图区域y方向物理高度
        xRange = 1000;
    yRange = 800;
    m_pDC->SetMapMode(MM_ANISOTROPIC);     // 注意MM_ANISOTROPIC和MM_ISOTROPIC的区别

    m_pDC->SetWindowExt(xRange,-yRange);   // 设定窗口尺寸范围,画图使用的逻辑范围,实现放大或是缩小,坐标方向↑和→为正向

    m_pDC->SetViewportExt(nWidth,nHeight); // 设定视口尺寸范围,客户区实际图形显示的区域范围,大小固定

    m_pDC->SetViewportOrg(rect.left,rect.bottom);  //设定画图的逻辑原点坐标(0,0)在物理坐标的(rect.left,rect.bottom)点上
    if(MemDC.m_hDC==0)
    {
    MemDC.CreateCompatibleDC(m_pDC);//m_pDC                          // 创建内存兼容设备上下文
    MemBitmap.CreateCompatibleBitmap(m_pDC,xRange,yRange);    // 创建内存兼容画布,大小由逻辑范围决定
    pOldbitmap = MemDC.SelectObject(&MemBitmap);              // 将画布选入内存设备上下文

    MemDC.FillSolidRect(0,0,xRange,yRange,RGB(123,213,132)); // 对内存中的画布填充背景颜色,否则是默认的黑色
    }

    // 画图操作,如画一条对角直线
    MemDC.MoveTo(0,0);
    MemDC.LineTo(xRange*0.9,yRange*0.9);

    // 将内存中的画图区域拷贝到界面的控件区域上去
    // 第1和第2个参数若是0时,则从物理坐标的(rect.left,rect.bottom)点上开始按上述指定的方向贴图
    m_pDC->BitBlt(0,0,xRange,yRange,&MemDC,0,0,SRCCOPY);  //MemDC.SelectObject(pOldbitmap);
    //MemBitmap.DeleteObject();
    //DeleteDC(MemDC);
    //this->ReleaseDC(&MemDC);
    //this->ReleaseDC(m_pDC);
    }
    void CLUBOTestView::OnSize(UINT nType, int cx, int cy) 
    {
    CFormView::OnSize(nType, cx, cy);
    //OnTest();
    if(MemDC.m_hDC!=0)
    {
    m_pDC = GetDC();
    CRect rect;
    GetWindowRect(&rect);             // 获取显示/画图区域大小(物理范围)
    ScreenToClient(&rect);                 // 转换为客户区坐标

    nWidth = rect.Width();                 // 显示/画图区域x方向物理宽度
    nHeight = rect.Height();               // 显示/画图区域y方向物理高度
    xRange = 1000;
    yRange = 800;


    m_pDC->SetMapMode(MM_ANISOTROPIC);     // 注意MM_ANISOTROPIC和MM_ISOTROPIC的区别

    m_pDC->SetWindowExt(xRange,-yRange);   // 设定窗口尺寸范围,画图使用的逻辑范围,实现放大或是缩小,坐标方向↑和→为正向

    m_pDC->SetViewportExt(nWidth,nHeight); // 设定视口尺寸范围,客户区实际图形显示的区域范围,大小固定

    m_pDC->SetViewportOrg(rect.left,rect.bottom);  //设定画图的逻辑原点坐标(0,0)在物理坐标的(rect.left,rect.bottom)点上
    m_pDC->BitBlt(0,0,xRange,yRange,&MemDC,0,0,SRCCOPY);
    }}void CLUBOTestView::OnDraw(CDC* pDC) 
    {
    // TODO: Add your specialized code here and/or call the base class
    if(MemDC.m_hDC!=0)
    {
    m_pDC = GetDC();
    CRect rect;
    GetWindowRect(&rect);             // 获取显示/画图区域大小(物理范围)
    ScreenToClient(&rect);                 // 转换为客户区坐标

    nWidth = rect.Width();                 // 显示/画图区域x方向物理宽度
    nHeight = rect.Height();               // 显示/画图区域y方向物理高度
    xRange = 1000;
    yRange = 800;


    m_pDC->SetMapMode(MM_ANISOTROPIC);     // 注意MM_ANISOTROPIC和MM_ISOTROPIC的区别

    m_pDC->SetWindowExt(xRange,-yRange);   // 设定窗口尺寸范围,画图使用的逻辑范围,实现放大或是缩小,坐标方向↑和→为正向

    m_pDC->SetViewportExt(nWidth,nHeight); // 设定视口尺寸范围,客户区实际图形显示的区域范围,大小固定

    m_pDC->SetViewportOrg(rect.left,rect.bottom);  //设定画图的逻辑原点坐标(0,0)在物理坐标的(rect.left,rect.bottom)点上


    m_pDC->BitBlt(0,0,xRange,yRange,&MemDC,0,0,SRCCOPY);
    }
    //OnTest();
    }
      

  5.   


    我是想知道那个曲线图里边的十字线怎么做到随光标移动而平滑的移动?且不闪屏
    图里边的十字线是用的画线还是控件模拟的line?
      

  6.   

    那个随着鼠标动的绘图部分是在WM_MOUSEMOVE事件的响应函数OnMouseMove里面,用获得CDC话的,这样就有相当的实时性,