- 版本
NX9+VS2012
- 演示
- 开发思路
在UG项目中添加一个MFC对话框资源,然后设置MFC对话框的鼠标消息回调,获得截图区域,最后保存图片(截图这个功能在VC++中网上可以百度到现成的代码)
- 开发步骤
1.新建BlockUI对话框(此处匆匆带过,不做详细步骤)
2.新建VS项目(此处匆匆带过,不做详细步骤)
3.添加资源(dialog对话框)
如下
删除对话框上的确定和取消
在对话框上点右键-属性(更改Border为None)
4.为对话框添加类
5.添加初始化对话框虚函数
6.在ShotDlg.h里加头文件#include "Resource.h"
出现上面这种问题,加头文件#include "Resource.h"就行了
7.更改基类
在ShotDlg.h和ShotDlg.cpp里全部改掉
8.在UG的代码里添加如下的几个头文件
编译成功,如果失败,根据错误提示,自己找问题
9.去ShotDlg.h和ShotDlg.cpp添加截图代码
头文件里定义变量
源文件里加在构造函数里的代码
start=captured=false; LIMITE = 5; CDC *pdc=GetDesktopWindow()->GetDC(); dc.CreateCompatibleDC(pdc); int nx=GetSystemMetrics(SM_CXSCREEN); int ny=GetSystemMetrics(SM_CYSCREEN); bmp.CreateCompatibleBitmap(pdc,nx,ny); pold=dc.SelectObject(&bmp); dc.BitBlt(0,0,nx,ny,pdc,0,0,SRCCOPY);
加在析构函数里的代码
dc.SelectObject(pold);
bmp.DeleteObject();
dc.DeleteDC();
加在初始化里的代码
this->ShowWindow(SW_SHOWMAXIMIZED); int nx=GetSystemMetrics(SM_CXSCREEN); int ny=GetSystemMetrics(SM_CYSCREEN); SetWindowPos(&wndTopMost,0,0,nx,ny,SWP_SHOWWINDOW);
下面开始为对话框添加五个消息回调
步骤如下
开始往每个消息函数里写代码
BOOL CShotDlg::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 int nx=GetSystemMetrics(SM_CXSCREEN); int ny=GetSystemMetrics(SM_CYSCREEN); BITMAP bm; bmp.GetBitmap(&bm); BOOL X=pDC->BitBlt(0,0,nx,ny,&dc,0,0,SRCCOPY); return X; //return CDialog::OnEraseBkgnd(pDC); }
void CShotDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if(!start) { opt=point;lastmove=point;start=true;captured=false; CDC *pDC=GetDC(); CPen pen(PS_SOLID,2,RGB(255,0,0)); CPen *oldp=pDC->SelectObject(&pen); int nmode=pDC->SetROP2(R2_NOTXORPEN); pDC->Rectangle(point.x,point.y,point.x,point.y); nmode=pDC->SetROP2(nmode); pDC->SelectObject(oldp); ReleaseDC(pDC); } CDialog::OnLButtonDown(nFlags, point); }
void CShotDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if(start) { start=false; CDC *pDC=GetDC(); CPen pen(PS_SOLID,2,RGB(255,0,0)); CPen *oldp=pDC->SelectObject(&pen); int nmode=pDC->SetROP2(R2_NOTXORPEN); pDC->Rectangle(opt.x,opt.y,lastmove.x,lastmove.y); nmode=pDC->SetROP2(nmode); pDC->SelectObject(oldp); lastmove=point; int ox,oy,dx,dy; ox=(opt.x<point.x)?opt.x:point.x; oy=(opt.y<point.y)?opt.y:point.y; dx=(opt.x>point.x)?opt.x:point.x; dy=(opt.y>point.y)?opt.y:point.y; if(dx-ox>LIMITE&&dy-oy>LIMITE) { captured=true;ReleaseDC(pDC); OnOK(); } else { captured=false;ReleaseDC(pDC);OnCancel(); } } CDialog::OnLButtonUp(nFlags, point); }
void CShotDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if(start) { CDC *pDC=GetDC(); CPen pen(PS_SOLID,2,RGB(255,0,0)); CPen *oldp=pDC->SelectObject(&pen); int nmode=pDC->SetROP2(R2_NOTXORPEN); pDC->Rectangle(opt.x,opt.y,lastmove.x,lastmove.y); lastmove=point; pDC->Rectangle(opt.x,opt.y,lastmove.x,lastmove.y); nmode=pDC->SetROP2(nmode); pDC->SelectObject(oldp); ReleaseDC(pDC); } CDialog::OnMouseMove(nFlags, point); }
void CShotDlg::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 start=false; captured=false; OnCancel(); CDialog::OnRButtonDown(nFlags, point); }
都加完后,编译下项目。生成成功。
10.去UG的代码里面调用这个MFC类里的方法
先在头文件里定义变量和函数
int limit; bool hasdc; CDC picdc; CBitmap* pold; CBitmap bmp; int pw,ph; int enlarge; void save_picture(CString path,CString num);
在去update_cb里的button0控件那写代码
label0->SetLabel("开始截图"); button0->SetEnable(false); if(hasdc) { picdc.SelectObject(pold); bmp.DeleteObject(); picdc.DeleteDC(); } pw=ph=0; AFX_MANAGE_STATE(AfxGetStaticModuleState()); CShotDlg *g = new CShotDlg(); g->LIMITE=limit; g->DoModal(); if(g->captured) { CPoint lt=g->GetLt();CPoint rb=g->GetRb(); lt.Offset(-enlarge,-enlarge); rb.Offset(enlarge,enlarge); int w=rb.x-lt.x; int h=rb.y-lt.y; pw=w;ph=h; CDC* pDC=g->GetBmpDC(); picdc.CreateCompatibleDC(pDC); bmp.CreateCompatibleBitmap(pDC,rb.x-lt.x,rb.y-lt.y); pold=picdc.SelectObject(&bmp); picdc.BitBlt(0,0,rb.x-lt.x,rb.y-lt.y,g->GetBmpDC(),lt.x,lt.y,SRCCOPY); CString str = "D:\1\2\";//保存路径 CString str1 = "1";//保存名字 hasdc=true; save_picture(str,str1); g->SendMessage(WM_CLOSE); label0->SetLabel("结束截图"); button0->SetEnable(true); }
去构造函数里加代码
hasdc=false;pw=ph=0;limit=5;enlarge=0;
去析构函数里加代码
if(hasdc) { picdc.SelectObject(pold); bmp.DeleteObject(); picdc.DeleteDC(); }
添加一个函数
void ScreenShotTool::save_picture(CString path,CString num) { int nwidth=pw; int nheight=ph; int bpp=24; CImage img; img.Create(nwidth,nheight,bpp); BOOL X=::BitBlt(img.GetDC(),0,0,nwidth,nheight,picdc.m_hDC,0,0,SRCCOPY); CString strFileName=path; CTime t = CTime::GetCurrentTime(); CString tt = t.Format("%Y%m%d%H%M%S"); strFileName = strFileName+num+"_"+tt; strFileName += _T(".png"); HRESULT Y=img.Save(strFileName); img.ReleaseDC(); if(X==TRUE && Y>=0) { uc1601("截取成功", 1); } else { uc1601("截取失败", 1); } }
加上ug的头文件
#include <uf.h>
#include <uf_ui.h>
到这里就全部写完了
去测试执行一下
没问题,可以的。
但是一般我不建议直接在UG项目里这样写,太麻烦的,也没法重用。
比较好一点的方法是先拿MFC开发一个应用程序,然后每次去调那个exe去传参截图。这样很多场合都可以重用。
回头我在写一个MFC截图的一个应用程序
会把文章连接补充在这里的
Caesar卢尚宇
2021年3月13日