MFC截图工具

1.新建MFC应用程序

(1)新建基于对话框的MFC应用程序

在这里插入图片描述
在这里插入图片描述

(2)加入按钮并命名

在这里插入图片描述

2.新建一个模态窗口

(1)在资源视图中,右击资源项目添加资源

在这里插入图片描述

(2)删除控件,更改属性

在这里插入图片描述

(3)更改窗口ID名称

在这里插入图片描述

(4)对此模态窗口添加类

在这里插入图片描述

3.主对话框窗口操作

(1)在主对话框窗口,即之前带按钮的窗口
在主窗口的头文件中加入

#include "Resource.h"
#include "CaptureDlg.h"

在这里插入图片描述
(2)回到主窗口界面双击截图按钮
在这里插入图片描述
(3)在按钮事件函数中加入

CCaptureDlg dlg;
dlg.DoModal();

在这里插入图片描述
(4)点击运行,再点击按钮,可以看到,弹出了一个模态对话框
在这里插入图片描述

4.再次对模态窗口操作

(1)CaptureDlg.h头文件操作

在CaptureDlg.h即模态窗口的头文件中输入以下代码

public:
	virtual BOOL OnInitDialog();
	CBitmap m_ScreenBmp;
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	CRectTracker m_rectTracker;
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnPaint();
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);

在这里插入图片描述

(2)CaptureDlg.cpp文件操作

将下面除了包含头文件之外的所有代码复制到CaptureDlg.cpp文件中,注意CaptureDlg.cpp中包含的头文件不要改变,只将包含头文件意外的代码替换掉即可。
CaptureDlg.cpp

// CaptureDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "screenCapture.h"
#include "CaptureDlg.h"
#include "afxdialogex.h"

BOOL copyScreenToBitmap(CBitmap &tBmp){		//为了修改值使用引用

	//获取屏幕当前分辨率的宽度和高度(以像素为单位,传递参数不同X,Y)
	int screenWidth = GetSystemMetrics(SM_CXSCREEN);
	int screenHeight = GetSystemMetrics(SM_CYSCREEN);

	//获取整个屏幕的DC
	//(DC是windows系统描画各种东西的时候都要用到的东西,可以叫做设备描述表,
	//你想要画的信息都要通过DC的对象去描画,任何窗口都有自己的DC,用自己的设备描述表进行描画,
	//比如画图像、画文字,在画文字的时候指定文字的宽度、高度、字体等,都可以通过DC指定描画,在画
	//任何东西时,都要先获取到当前窗口的设备描述表DC,用它去描画,才能在屏幕上显示出来)
	//获取屏幕的DC,对屏幕截图,屏幕的东西就是屏幕的DC画上去的,要获取屏幕DC ,将内容拷贝到我们的DC中就可以截图了
	CDC *pDC = CDC::FromHandle(::GetDC(NULL));		//::GetDC(NULL)表示或取整个屏幕DC,要获取某一个窗口的DC,它的参数就是某一窗口的窗口句柄
	//::GetDC(NULL)返回的是HDC(win32的对象),而我们使用MFC,需要将HDC对象转换成CDC类型的对象,MFC已经将HDC封装了
	//此时pDC指向的对象就是屏幕的DC

	//屏幕DC有了,要将屏幕DC的内容拿过来拷贝到自己DC上来,然后才能进行内容保存,保存到图片或者剪切板,所以要建立自己的DC,在内存中建立与屏幕相容

	//创建内存DC
	CDC memDc;
	memDc.CreateCompatibleDC(pDC);		//创建一个与屏幕DC兼容的内存DC
	//内存DC创建好后,还要在内存DC上画东西,但内存DC无任何画板,是画不上去的
	//要建立Bitmap,让Bitmap作为内存DC的画板,把屏幕上的一些东西画到bitmap上面来,通过Bitmap将数据保存

	//创建画板
	CBitmap *pOldBmp = NULL;
	tBmp.CreateCompatibleBitmap(pDC, screenWidth, screenHeight);		//创建一个与屏幕DC兼容的一个Bitmap,画板的信息,参数1:DC,参数2、3:宽高
	//画布建好了,要将Bitmap选入到内存DC中,这样在内存DC画东西是就会画到Bitmap上面
	pOldBmp = memDc.SelectObject(&tBmp);	//SelectObject返回原来的旧的画布,定义pOldBmp接收,还会用到

	//将屏幕DC上的内容拷贝到内存DC上面来(BitBlt比较重要的函数)
	memDc.BitBlt(0, 0, screenWidth, screenHeight, pDC, 0, 0, SRCCOPY);
	//参数1,2:左上角坐标,参数3,4:宽高,参数5:源DC,参数6,7:从源DC的那个位置开始拷贝,参数8:直接拷贝源矩形到目标矩形

	//善后操作
	memDc.SelectObject(pOldBmp);		//将pOldBmp选择到内存DC中
	memDc.DeleteDC();					//还要对内存DC在用完了后清除(create与delete成对使用)

	::ReleaseDC(NULL, pDC->m_hDC);		//还要释放屏幕DC(getDC与releaseDC成对使用)

	return TRUE;
}

// CCaptureDlg 对话框

IMPLEMENT_DYNAMIC(CCaptureDlg, CDialog)

CCaptureDlg::CCaptureDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCaptureDlg::IDD, pParent)
{
	copyScreenToBitmap(m_ScreenBmp);	//将屏幕内容拷贝到Bitmap类型的对象中
}

CCaptureDlg::~CCaptureDlg()
{
}

void CCaptureDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CCaptureDlg, CDialog)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_PAINT()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDBLCLK()
END_MESSAGE_MAP()


// CCaptureDlg 消息处理程序


BOOL CCaptureDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化

	//获取屏幕当前分辨率的宽度和高度(以像素为单位,传递参数不同X,Y)
	int screenWidth = GetSystemMetrics(SM_CXSCREEN);
	int screenHeight = GetSystemMetrics(SM_CYSCREEN);
	//调用MoveWindow或者SetWindowPos将当前的窗口设置成与屏幕大小相同
	//使用两个,软件写好后要使用SetWindowPos,但使用SetWindowPos设置成顶层窗口就不能调试了,使用MoveWindow进行调试
	MoveWindow(-3, -3, screenWidth + 6, screenHeight + 6);	//比屏幕膜大3个像素不然白边出现,好看一些
	//SetWindowPos(&wndTopMost, -3, -3, screenWidth + 6, screenHeight + 6, SWP_SHOWWINDOW);

	//橡皮筋类的操作
	m_rectTracker.m_nStyle = CRectTracker::resizeOutside | CRectTracker::dottedLine;	//矩形框虚线
	m_rectTracker.m_rect.SetRect(0, 0, 0, 0);			//初始化矩形大小

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常:  OCX 属性页应返回 FALSE
}


BOOL CCaptureDlg::OnEraseBkgnd(CDC* pDC)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	//将bitmap对象作为背景画到对话框上
	//创建内存DC
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);		//使内存DC与pDC兼容
	memDC.SelectObject(&m_ScreenBmp);	//选入设备环境

	//将内容从内存DC拷贝到pDC中(本模态对话框窗口的DC)
	CRect rect;
	GetClientRect(&rect);		//获取对话框大小,在初始化时设置了
	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);  //将内容从内存DC拷贝到pDC中

	memDC.DeleteDC();		//释放
	return TRUE;			//直接在此返回,不进行下一步操作,否则就画不上了

	return CDialog::OnEraseBkgnd(pDC);
}


void CCaptureDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	//如果点击绘制橡皮筋区域的外部,重新构建一个可拖拽的区域
	if (m_rectTracker.HitTest(point)==CRectTracker::hitNothing)
	{
		m_rectTracker.TrackRubberBand(this, point, TRUE);
	}
	else{
		//点击在了区域内部,允许用户大小调整进行区域描画
		m_rectTracker.Track(this, point, TRUE);
		m_rectTracker.m_rect.NormalizeRect();		//NormalizeRect可以进行左右上下值调整,从右下向左上框柱
	}
	Invalidate(TRUE);		//更新,使WM_PAINT描画消息触发

	CDialog::OnLButtonDown(nFlags, point);
}


void CCaptureDlg::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO:  在此处添加消息处理程序代码
	// 不为绘图消息调用 CDialog::OnPaint()

	//CPaintDC只适合OnPaint里面,所以使用GetDC来获取DC,进行描绘

	CDC *pDC = GetDC();
	m_rectTracker.Draw(pDC);
	ReleaseDC(pDC);		//get与release成对使用
}


BOOL CCaptureDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值

	//如果传递的是本窗口,SetCursor成功了
	if (pWnd == this && m_rectTracker.SetCursor(this, nHitTest)){
		return TRUE;
	}
	else{		//如果失败了
		return CDialog::OnSetCursor(pWnd, nHitTest, message);
	}
}


void CCaptureDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	//如果双击在了矩形区域的内部就进行保存工作
	if (m_rectTracker.HitTest(point) != CRectTracker::hitMiddle)
	{
		return;
	}

	CDC *pDC = GetDC();

	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	memDC.SelectObject(&m_ScreenBmp);

	CRect rect;
	rect = m_rectTracker.m_rect;

	CBitmap mBmp, *pOldBmp = NULL;
	mBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());

	CDC dstDC;
	dstDC.CreateCompatibleDC(pDC);
	pOldBmp = dstDC.SelectObject(&mBmp);

	//内容拷贝到目标,目标肯定比屏幕小,所以坐标0,0,宽高用户选择的,rect.left, rect.top是源缓冲区的坐标
	dstDC.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, rect.left, rect.top, SRCCOPY);

	CImage Img;
	Img.Attach(mBmp);					//关联
	Img.Save(_T("./capture.jpg"));		//保存地址

	mBmp.DeleteObject();
	memDC.DeleteDC();
	dstDC.DeleteDC();

	ReleaseDC(pDC);

	//保存完了后,说明本次截图操作完成了,要把当前显示的模态对话框,全屏的对话框关闭了
	CDialog::OnCancel();
	//CDialog::OnLButtonDblClk(nFlags, point);
}

5.父窗口指针传递子窗口

参考链接:https://blog.csdn.net/yeqingbo2010/article/details/11724937

  • 最近要将截取的图片显示到主窗口上,需要窗口间的数据传递。
  • 数据在各个窗口之间的流动。如子窗口修改的数据,要保存到父窗口中进行保存。这就涉及到父窗口的指针传到子窗口的问题,在子窗口中,声明一个void * 型指针,然后再父窗口创建子窗口对象时,将父窗口的this传递给这个成员变量。当在子窗口中要使用父窗口指针时,可以用父窗口的类型强制转换为父窗口对象指针。非常好用。
  • 为什么不能在子窗口中声明父窗口的指针变量呢?
    那是因为子窗口时父类的一部分,如果父窗口指针又声明为子窗口的一部分,这样必然导致一个鸡生蛋,蛋生鸡的问题,编译不通过。

6.使用操作

最后,运行此程序,点击截图按钮即可进行截图操作

点击截图按钮后,左键按住鼠标拖拽,会出现一个由虚线构成的矩形窗口,此窗口可以进行拖拽、移动、更改边界大小,选择好区域后,在选择的区域内进行双击操作就可以保存截图了,默认保存在此项目的main函数所在文件夹下,名称为capture.jpg

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
MFC(Microsoft Foundation Class)是微软提供的一套用于windows平台开发的C++类库。在MFC中,可以通过自定义工具栏来实现单选按钮的功能。 步骤如下: 1. 首先,需要在MFC对话框资源中添加工具栏控件。可以使用资源编辑器打开对话框的资源文件,并在工具栏控件区域拖拽一个工具栏控件。 2. 在对话框类的头文件中添加成员变量来引用工具栏控件。可以使用ClassWizard工具来自动生成对话框类的成员变量。 3. 在对话框类的初始化函数OnInitDialog()中,添加以下代码来将工具栏控件与对话框关联起来,并设置单选按钮的样式。 ```cpp m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // 添加单选按钮 UINT nIDButton = m_ToolBar.GetDlgCtrlID(); // 获取工具栏控件的ID m_ToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS); m_ToolBar.GetToolBarCtrl().AddButton(nIDButton, TBBS_BUTTON, MFCS_HILITE, NULL, "按钮1"); m_ToolBar.GetToolBarCtrl().AddButton(nIDButton + 1, TBBS_BUTTON, MFCS_HILITE, NULL, "按钮2"); m_ToolBar.GetToolBarCtrl().CheckButton(nIDButton); // 默认选中按钮1 // 调整工具栏尺寸和位置 CRect rect; GetClientRect(&rect); m_ToolBar.SetWindowPos(NULL, rect.left, rect.top, rect.Width(), 30, SWP_SHOWWINDOW); ``` 4. 在对话框类的消息映射函数中添加以下代码来处理单选按钮的切换事件。 ```cpp ON_COMMAND_RANGE(ID_BUTTON1, ID_BUTTON2, OnButtonClicked) void CMyDialog::OnButtonClicked(UINT nID) { // 判断单选按钮的ID,并进行相应的处理 switch (nID) { case ID_BUTTON1: // 按钮1被选中 break; case ID_BUTTON2: // 按钮2被选中 break; } } ``` 通过以上步骤,我们就可以在MFC自定义工具栏中实现单选按钮的功能。根据实际需求,可以添加更多的单选按钮,并在按钮事件中编写相应的处理逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾名招财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值