关于画十字线的难题

hill_qd 2010-01-09 06:12:00
程序目的:
1、窗口限制最小范围,通过响应WM_GETMINMAXINFO事件,已经实现
2、双击窗口的某个区域,开始绘十字
3、光标在区域中移动时,绘十字,如果超出范围,隐藏十字,但是再进来时,又显示十字
4、再次双击绘图区域,退出画十字模式

目前做法:响应鼠标左键双击事件,和鼠标移动事件来实现。发现在进入画十字模式后,基本上正常,但是在拖拽窗口到最小限制时,如果鼠标停在绘图区域上时,当放开鼠标左键,移动后,就会留下一个十字没有被擦出掉,想好多天了,没有解决,请高手帮忙。
以下是我的程序代码:

用到的几个变量:
BOOL m_bNeedEraseCross; //是否需要擦除光标
BOOL m_bDispCross; //是否显示光标
CPoint m_ptCrossOld; //上次光标位置
CPoint m_ptCrossLast; //当前光标位置

void CUserFunctionView::DrawSelectCross(CDC* pDC, CPoint point)
{
pDC->GetBkMode();

COLORREF XorColor = pDC->GetBkColor() ^ RGB(64,64,112);
CPen pen( PS_SOLID, 1, XorColor ), *oldpen;
oldpen = pDC->SelectObject( &pen );
int nOldDrawMode = pDC->SetROP2( R2_XORPEN );
pDC->MoveTo( m_rectCross.left, point.y );
pDC->LineTo( m_rectCross.right, point.y );
pDC->MoveTo( point.x, m_rectCross.top );
pDC->LineTo( point.x, m_rectCross.bottom);
pDC->SetROP2( nOldDrawMode );
pDC->SelectObject(oldpen);
}
void CUserFunctionView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect client;
GetClientRect(&client);

CDC* pDC = GetDC();
if(m_bDispCross)
{
if(m_rectCross.PtInRect(point))
{

if(m_rectCross.PtInRect(m_ptCrossLast) && m_bNeedEraseCross)
DrawSelectCross(pDC, m_ptCrossLast);

DrawSelectCross(pDC, point);
m_bNeedEraseCross = TRUE;
m_ptCrossLast = point;
}
else
{
if(m_rectCross.PtInRect(m_ptCrossLast) && m_bNeedEraseCross)
{
DrawSelectCross(pDC, m_ptCrossLast);
m_bNeedEraseCross = FALSE;
}
}
}
ReleaseDC(pDC);
}
void CUserFunctionView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//CString str;
//str.Format("%d-%d",point.x,point.y);
//AfxMessageBox(str,1,0);


CDC* pDC = GetDC();





if(m_rectCross.PtInRect(point))
{
if(m_bDispCross)
{
if(m_rectCross.PtInRect(m_ptCrossLast) && m_bNeedEraseCross)
DrawSelectCross(pDC, m_ptCrossLast);
m_bNeedEraseCross = FALSE;
m_bDispCross = FALSE;
}
else
{
//DrawSelectCross(pDC, m_ptCrossLast);
DrawSelectCross(pDC, point);
m_bDispCross = TRUE;
m_bNeedEraseCross = TRUE;
m_ptCrossLast = point;
}
}
ReleaseDC(pDC);

CView::OnLButtonDblClk(nFlags, point);
}
没有重载OnDraw,是不是跟这个有关?请高手一定帮忙!
...全文
894 50 打赏 收藏 转发到动态 举报
写回复
用AI写文章
50 条回复
切换为时间正序
请发表友善的回复…
发表回复
hill_qd 2010-01-25
  • 打赏
  • 举报
回复
我其实是在做股票软件的k线画图部分,需要在双击某k线的时候,显示十字形
hahaking119 2010-01-20
  • 打赏
  • 举报
回复
[Quote=引用 47 楼 hill_qd 的回复:]
不好意思,问题就在这里,我拖拽边框到最小的时候,鼠标再拖,就会进入绘图区域,放开鼠标就会发现留下了一个十字,如果鼠标不落在绘图区域,就不会多一个十字,我感觉我现在最大的问题是在全部重绘的时候,没有处理好
[/Quote]

这个是细节问题,主要怎么个思路去实现还是要靠你自己,况且你鼠标放大缩小窗口显示就显示没有显示就没有显示呗,你也不做其它什么操作,因为你鼠标被使用,这又会有什么问题,会影响你程序的运行么?感觉没有必要,非要处理你可以在非客户区左键按下消息里面处理判断是否击中为边,也可以处理。这个是你自己实现的问题,没有必要讨论这么久。
hill_qd 2010-01-19
  • 打赏
  • 举报
回复
自己顶一下,预防帖子沉底
hill_qd 2010-01-17
  • 打赏
  • 举报
回复
不好意思,问题就在这里,我拖拽边框到最小的时候,鼠标再拖,就会进入绘图区域,放开鼠标就会发现留下了一个十字,如果鼠标不落在绘图区域,就不会多一个十字,我感觉我现在最大的问题是在全部重绘的时候,没有处理好
hahaking119 2010-01-15
  • 打赏
  • 举报
回复
写错了

COLORREF clrBk = pDC->GetBkColor();
memDC.FillRect(rcClient, &CBrush(clrBk));

这句话是获取默认的背景颜色,

你用clrBk = RGB(255, 0, 0)看看是否重绘背景了。
hahaking119 2010-01-15
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 hill_qd 的回复:]
为啥要用CBitmap类?
[/Quote]
用CBitmap类是你在画的时候要在dc上画一幅图片也可以理解直接在dc画位图,CBitmap类实际就是HBITMAP,mfc将这个HBITMAP句柄抽象成一个类的形式。

[Quote=引用 35 楼 hill_qd 的回复:]
memDC.FillRect(rcClient, &CBrush(clrBk));
不能重画背景
[/Quote]
不能重绘,是不是你看到的是白色的内容啊,如果是白色的内容,可能是我的背景画刷设置的是白色,你那m_clrBk的颜色改一下看看,可能是因为这个原因吧。
hahaking119 2010-01-15
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 hill_qd 的回复:]
学到了很多东西,hahaking119,你把下面的代码复制到你的程序中试试
afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);


ON_WM_GETMINMAXINFO()

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
// TODO: Add your message handler code here and/or call default
    lpMMI->ptMinTrackSize.x  = 640 ; 
    lpMMI->ptMinTrackSize.y  = 456 ;
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}
[/Quote]

你限制窗口大小??不知道你怎么考虑的??好像和你问题不搭边。
hahaking119 2010-01-15
  • 打赏
  • 举报
回复
[Quote=引用 43 楼 hill_qd 的回复:]
还有个思路的问题,应该减少重绘量,在移动鼠标的时候,背景图是不重绘的,只有在需要的时候才重绘
[/Quote]

如果不处理背景图重绘,那么你画是十字线就无法用在背景图上实现,因为你十字线在你鼠标移动的时候是会发生变化的,这样毕竟在背景中的位置会发生改变,还有如果你鼠标位置不发生改变,那么就不会产生ON_MOUSEMOVE消息,也就不会重绘。个人觉得重绘不会太影响效率。你减少重绘量好像不容易实现,你可以试试。
  • 打赏
  • 举报
回复
帮顶
hill_qd 2010-01-15
  • 打赏
  • 举报
回复
还有个思路的问题,应该减少重绘量,在移动鼠标的时候,背景图是不重绘的,只有在需要的时候才重绘
hill_qd 2010-01-15
  • 打赏
  • 举报
回复
学到了很多东西,hahaking119,你把下面的代码复制到你的程序中试试
afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);


ON_WM_GETMINMAXINFO()

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
// TODO: Add your message handler code here and/or call default
lpMMI->ptMinTrackSize.x = 640 ;
lpMMI->ptMinTrackSize.y = 456 ;
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}
hahaking119 2010-01-15
  • 打赏
  • 举报
回复

int CXXWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
BITMAP bitinfo;
m_bitmap.LoadBitmap(IDB_XXX); // 加载图片资源
m_bitmap.GetBitmap(&bitinfo);
m_szImage = CSize(bitinfo.bmWidth, bitinfo.bmHeight);
return 0;
}

void CXXWnd::DrawCross(CDC* pDC)
{
ASSERT(pDC);
// 这里用双缓冲
CDC memDC1, memDC2;
CBitmap bitmap, *pOldBitmap1 = NULL, *pOldBitmap2 = NULL;
CPen pen(PS_SOLID, 2, RGB(255, 0, 0)), *pOldPen = NULL;
CRect rcClient;
GetClientRect(rcClient);
if ( memDC1.CreateCompatibleDC(pDC)
&& memDC2.CreateCompatibleDC(pDC)
&& bitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()) )
{
// 选入背景资源的内存DC
pOldBitmap1 = memDC1.SelectObject(&m_bitmap);
// 完整内容的内存DC
pOldBitmap2 = memDC2.SelectObject(&bitmap);
pOldPen = memDC2.SelectObject(&pen);
memDC2.StretchBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC1, 0, 0, m_szImage.cx, m_szImage.cy, SRCCOPY);
if ( m_bOpenDrawCross && m_bMouseIn )
{
CPoint ptMouse;
GetCursorPos(&ptMouse);
ScreenToClient(&ptMouse);
memDC2.MoveTo(rcClient.left, ptMouse.y);
memDC2.LineTo(rcClient.right, ptMouse.y);
memDC2.MoveTo(ptMouse.x, rcClient.top);
memDC2.LineTo(ptMouse.x, rcClient.bottom);
}
pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC2, 0, 0, SRCCOPY);
memDC2.SelectObject(pOldPen);
memDC2.SelectObject(pOldBitmap2);
memDC1.SelectObject(pOldBitmap1);
}
}


hill_qd 2010-01-15
  • 打赏
  • 举报
回复
我的背景其实是别的图
hill_qd 2010-01-15
  • 打赏
  • 举报
回复
拷贝过去以后,连背景应该也能拷贝过去吧?
hill_qd 2010-01-15
  • 打赏
  • 举报
回复
pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
绘图完毕后,这个应该是吧绘制的图拷贝到屏幕上吧?
我感觉我主要是因为没处理好WM_SIZE事件,其实我根本就没处理
hill_qd 2010-01-13
  • 打赏
  • 举报
回复
memDC.FillRect(rcClient, &CBrush(clrBk));
不能重画背景
hill_qd 2010-01-13
  • 打赏
  • 举报
回复
为啥要用CBitmap类?
hill_qd 2010-01-12
  • 打赏
  • 举报
回复
非常感谢,我再试验一下
hill_qd 2010-01-11
  • 打赏
  • 举报
回复
这个是框架窗口,肯定包含绘图区域,真晕,你到底说的是啥意思?
hill_qd 2010-01-11
  • 打赏
  • 举报
回复
鼠标肯定在这个区域里!
加载更多回复(30)

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧