MFC-完成鼠标框选按钮弹出功能

1、工具栏形式的,
注意图片大小要与代码中设置的宽高一致,按钮宽高大于图片宽高。
在这里插入图片描述

核心代码
if (!m_ToolBar)
	{
		if (!m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_SIZE_FIXED | CBRS_LEFT | CBRS_TOOLTIPS))
		{
			TRACE("Failed to create toolbar!\n");
			return;
		}
		CBitmap cBmp[2];

		m_imagelist.Create(30, 30, ILC_COLOR24 | ILC_MASK,3, 1);
		m_imagelist.SetBkColor(::GetSysColor(COLOR_BTNFACE));

		cBmp[0].LoadBitmap(IDB_BITMAP2);
		m_imagelist.Add(&cBmp[0], RGB(255, 255, 255));
		cBmp[1].LoadBitmap(IDB_BITMAP3);
		m_imagelist.Add(&cBmp[1], RGB(255, 255, 255));
		m_ToolBar.GetToolBarCtrl().SetImageList(&m_imagelist);//设置图像

		//m_ToolBar.CreateEx(this);//创建工具栏控件

		//m_ToolBar.SetSizes(CSize(70, 60), CSize(28, 40));
		UINT array[10] = { IDB_BITMAP2,IDB_BITMAP2 + 1 };
		//m_ToolBar.SetSizes(CSize(70, 60), CSize(28, 40));
		//UINT array[10] = { 1000,1001 };
		m_ToolBar.SetButtons(array, 2);
		m_ToolBar.SetSizes(CSize(40, 40), CSize(30, 30));//图片大小要与实际图片大小一致
		m_ToolBar.EnableToolTips(TRUE);
		/*m_ToolBar.SetButtonText(0, _T("选定马赛克"));
		m_ToolBar.SetButtonText(1, _T("取消马赛克"));
		*/
		//m_ToolBar.EnableDocking(CBRS_ALIGN_ANY);
		
		//CReBar m_Rebar;
		//m_Rebar.Create(this);//创建窗口(控件)
		//m_Rebar.AddBar(&m_ToolBar);//添加m_Toolbar为子窗口
		//m_Rebar.RedrawWindow();//重画窗口
		//REBARBANDINFO info;
		//info.cbSize = sizeof(info);
		//info.fMask = RBBIM_BACKGROUND;
		//m_ToolBar.ModifyStyle(0, TBSTYLE_TRANSPARENT);//设置工具栏背景色透明
		//info.hbmBack = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP4));//加载位图
		//m_Rebar.GetReBarCtrl().SetBandInfo(0, &info);
		RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
	}
	
	
	/*EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_ToolBar);*/
	
	
	int i_LDCoordicateX = 0;
	int i_LDCoordicateY = 0;
	if ((80 + x) > m_iWidth)
		i_LDCoordicateX = x - 80;
	else
		i_LDCoordicateX = x + 80;

	if ((40 + y) > m_iHeight)
		i_LDCoordicateY = y - 40;
	else
		i_LDCoordicateY = 40 + y;

	if (x > i_LDCoordicateX)
	{
		int itemp = x;
		x = i_LDCoordicateX;
		i_LDCoordicateX = itemp;
	}
	if (y > i_LDCoordicateY)
	{
		int itemp = y;
		y = i_LDCoordicateY;
		i_LDCoordicateY = itemp;
	}
	CRect rect(x, y, i_LDCoordicateX, i_LDCoordicateY);
	m_ToolBar.MoveWindow(rect);//移动工具栏在父窗口的位置
	m_ToolBar.ShowWindow(TRUE);

2、菜单栏形式的
在这里插入图片描述

核心代码
void CShowMosaicDlg::ShowCMenuBar(int x, int y)
{
	menu1.CreatePopupMenu(); //动态创建弹出式菜单对象
	menu1.AppendMenu(MF_STRING, ID_TEST1, L" 马赛克");
	menu1.AppendMenu(MF_STRING, ID_TEST2, L" 取消马赛克");
	CPoint pt;
	pt.x = m_iStartX;
	pt.y = m_iStartY;
	GetCursorPos(&pt);
	menu1.TrackPopupMenu(TPM_LEFTALIGN | TPM_BOTTOMALIGN, pt.x, pt.y, this);
	menu1.DestroyMenu();
}

3、但是最后的效果图都不是这样的,需要时菜单样式但是每次按钮显示在框选框框的正下方。暂未解决。

其他代码

void CShowMosaicDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	this->GetWindowRect(&rect);//获取MFC图像显示区域
	m_iStartX = point.x;
	m_iStartY = point.y;
	Point p(point.x, point.y);//opencv鼠标坐标(相对界面)
	ScreenToClient(rect);//转化为对话框上的相对位置
	Rect r(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);//OPenCV窗口显示区域
	if (r.contains(p)) //鼠标放在图片窗口上
	{
		m_startRect = TRUE;   //鼠标左键单击,设置可以开始绘制矩形框
		m_endRect = false;
		m_startPoint = point; //记录开始点
		m_OldPoint = point;   //设置老点也为开始点
	}
	Invalidate();
	CDialogEx::OnLButtonDown(nFlags, point);
}


void CShowMosaicDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	this->GetWindowRect(&rect);//获取MFC图像显示区域
	ScreenToClient(rect);//转化为对话框上的相对位置
	Point p(point.x, point.y);//opencv鼠标坐标(相对界面)
	Rect r(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);//opencv窗口显示区域
	if (r.contains(p) && (true == m_startRect)) //鼠标放在图片窗口上
	{
		HCURSOR hCur = LoadCursor(NULL, IDC_CROSS);
		::SetCursor(hCur);

		CClientDC dc(this);   //获取设备句柄
							  //SetRop2 Specifies the new drawing mode.(MSDN)
							  //R2_NOT   Pixel is the inverse of the screen color.(MSDN)
							  //即:该函数用来定义绘制的颜色,而该参数则将颜色设置为原屏幕颜色的反色
							  //这样,如果连续绘制两次的话,就可以恢复原来屏幕的颜色了(如下)
							  //但是,这里的连续两次绘制却不是在一次消息响应中完成的
							  //而是在第一次拖动响应的绘制可以显示(也就是看到的),第二次拖动绘制实现擦出(也就看不到了)
		dc.SetROP2(R2_NOT);   //此为关键!!!
		dc.SelectStockObject(NULL_BRUSH); //不使用画刷
		//if (TRUE == m_startRect)   //根据是否有单击判断是否可以画矩形
		{
			m_endRect = true;
			dc.Rectangle(CRect(m_startPoint, m_OldPoint));
			dc.Rectangle(CRect(m_startPoint, point));
			m_OldPoint = point;
		}
	}

	CDialogEx::OnMouseMove(nFlags, point);
}


void CShowMosaicDlg::OnButtoncancle()
{
	// TODO: 在此添加命令处理程序代码
	MessageBox(TEXT("取消"), TEXT("取消"), MB_YESNO);
	Invalidate();
	//m_ToolBar.ShowWindow(false);
}


void CShowMosaicDlg::OnButtondo()
{
	// TODO: 在此添加命令处理程序代码
	MessageBox(TEXT("操作"), TEXT("操作"), MB_YESNO);
	Invalidate();
	//m_ToolBar.ShowWindow(false);
}

void CShowMosaicDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	this->GetWindowRect(&rect);//获取MFC图像显示区域
	ScreenToClient(rect);//转化为对话框上的相对位置
	Point p(point.x, point.y);//opencv鼠标坐标(相对界面)
	Rect r(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);//opencv窗口显示区域

	if (r.contains(p) && m_endRect) //鼠标放在图片窗口上
	{
		int current_x = point.x;
		int current_y = point.y;

		int tx = (current_x - before_x);
		int ty = (current_y - before_y);
		//CClientDC dc(this);//选定当前画图环境
		//COLORREF colorrrefRGB = RGB(250, 0, 0);
		//CPen pen(PS_SOLID, 1, colorrrefRGB);//做一支红色粗细为1的笔
		//dc.SelectObject(&pen);//将pen放到dc上
		//dc.Rectangle(before_x, before_y, tx, ty);//画一个矩形

		//一个底下出现弹框  选择是否马赛克
		if (current_x < m_startPoint.x)
		{
			current_x = m_startPoint.x;
		}
		if (current_y < m_startPoint.y)
		{
			current_y = m_startPoint.y;
		}
		ShowCMenuBar(current_x, current_y);
		//OnShowToolBar(current_x, current_y);
	}
	m_startRect = false;
	m_endRect = false;
	CDialogEx::OnLButtonUp(nFlags, point);
}

借鉴博客
https://www.cnblogs.com/lujin49/p/4962256.html MFC菜单栏
https://blog.csdn.net/wangshubo1989/article/details/49309547 TrackPopupMenu样式

代码链接地址
代码链接地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值