我想写个截图程序
来源:互联网 发布:linux的shell 编辑:程序博客网 时间:2024/05/03 17:13
手把手VC截图小工具,附源码
一直都想写个截图程序,觉得蛮有意思的。看到网上这位兄弟的思路蛮清晰的,就自己跟着做下,并记录了流程,做个备份。
1.首先是构建个基于对话框的程序。在OnInitDialog中
注册热键,并隐藏当前对话框。在资源里把对话框设为无边框。
BOOL CCutterDlg::OnInitDialog(){ RegisterHotKey(m_hWnd,1001,MOD_CONTROL|MOD_ALT,VK_F7); RegisterHotKey(m_hWnd,1002,MOD_CONTROL|MOD_ALT,VK_F8); ShowWindow(SW_HIDE); CDialog::OnInitDialog(); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE}在OnDestroy()对热键注销。
void CCutterDlg::OnDestroy(){CDialog::OnDestroy();// TODO: 在此处添加消息处理程序代码UnregisterHotKey(m_hWnd,1001); UnregisterHotKey(m_hWnd,1002); }
在OnPaint要对对话框再做一次隐藏。
ShowWindow(SW_HIDE);
2.对热键进行声明、关联及响应
afx_msg LRESULT OnHotKey(WPARAM wp,LPARAM lp);
BEGIN_MESSAGE_MAP(CCutterDlg, CDialog)...ON_MESSAGE(WM_HOTKEY,OnHotKey)END_MESSAGE_MAP()
LRESULT CCutterDlg::OnHotKey(WPARAM wp,LPARAM lp)//快捷键{if(wp==1001){int x=GetSystemMetrics(SM_CXSCREEN); int y=GetSystemMetrics(SM_CYSCREEN);CRect cr(CPoint(0,0),CPoint(x,y));HBITMAP hb=myGetScreenBmp(cr);ShowDlgS shows(hb);shows.DoModal();}if (wp==1002){exit(1);}return 0;}
3.热键响应部分,用到了ShowDlgS ,这是一个无边框的对话框。
ShowDlgS.h
#pragma once// ShowDlgS 对话框class ShowDlgS : public CDialog{DECLARE_DYNAMIC(ShowDlgS)public:ShowDlgS(CWnd* pParent = NULL); // 标准构造函数ShowDlgS(HBITMAP hb,CWnd* pParent=NULL);virtual ~ShowDlgS();// 对话框数据enum { IDD = IDD_DIALOG1 };protected:CBitmap m_bmp;HBITMAP m_hBmp;CPoint m_ptBegin;CPoint m_ptMid;CPoint m_ptEnd;bool m_bBegin;bool m_bEnd;virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持DECLARE_MESSAGE_MAP()public:afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnPaint();virtual BOOL OnInitDialog();afx_msg void OnMouseMove(UINT nFlags, CPoint point);};
ShowDlgS.cpp
// ShowDlgS.cpp : 实现文件//#include "stdafx.h"#include "Cutter.h"#include "ShowDlgS.h"#include "screen.h"IMPLEMENT_DYNAMIC(ShowDlgS, CDialog)ShowDlgS::ShowDlgS(CWnd* pParent /*=NULL*/) : CDialog(ShowDlgS::IDD, pParent){}ShowDlgS::ShowDlgS(HBITMAP hb,CWnd* pParent):CDialog(ShowDlgS::IDD, pParent){ m_hBmp=hb; m_bBegin=false; m_bEnd=false;}ShowDlgS::~ShowDlgS(){}void ShowDlgS::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(ShowDlgS, CDialog) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_PAINT() ON_WM_MOUSEMOVE()END_MESSAGE_MAP()void ShowDlgS::OnLButtonDown(UINT nFlags, CPoint point){ // TODO: 在此添加消息处理程序代码和/或调用默认值 if (m_bEnd) { return; } m_ptBegin=point; m_ptMid=point; m_bBegin=true; CDialog::OnLButtonDown(nFlags, point);}void ShowDlgS::OnLButtonUp(UINT nFlags, CPoint point){ // TODO: 在此添加消息处理程序代码和/或调用默认值 if (!m_bBegin||m_bEnd) { return; } m_bEnd=true; m_ptEnd=point; if (m_ptBegin==m_ptEnd) { return; } CBrush * pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//set touming CClientDC dc(this); CBrush *pOldBrush=dc.SelectObject(pBrush);//select brush dc.Rectangle(CRect(m_ptBegin,m_ptEnd)); dc.SelectObject(pOldBrush);//save old brush HBITMAP hbm=myGetScreenBmp(CRect(m_ptBegin,m_ptEnd)); CFileDialog dlg(FALSE,NULL,_T("cut.bmp"),OFN_OVERWRITEPROMPT,_T("(*.bmp)")); if ( dlg.DoModal()!=IDOK ) SendMessage(WM_CLOSE); //get path CString sFileName=dlg.GetPathName(); mySaveBitmapToFile(hbm,sFileName); SendMessage(WM_CLOSE); //CDialog::OnLButtonUp(nFlags, point);}void ShowDlgS::OnPaint(){ CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CDialog::OnPaint() m_bmp.Attach(m_hBmp); // TODO: Add your message handler code here BITMAP bmInfo; ::GetObject( m_bmp.m_hObject, sizeof(BITMAP), &bmInfo ); INT nWidth, nHeigh; nWidth = bmInfo.bmWidth; nHeigh = bmInfo.bmHeight; CDC pDC; pDC.CreateCompatibleDC(&dc); pDC.SelectObject(&m_bmp); dc.BitBlt(0, 0, nWidth, nHeigh, &pDC, 0, 0, SRCCOPY); m_bmp.Detach(); CBrush * pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//set touming CBrush *pOldBrush=dc.SelectObject(pBrush);//select brush dc.Rectangle(CRect(m_ptBegin,m_ptEnd)); dc.SelectObject(pOldBrush);//save old brush}BOOL ShowDlgS::OnInitDialog(){ CDialog::OnInitDialog(); /*bo add begin*/ int x=GetSystemMetrics(SM_CXSCREEN); //获取屏幕分辨率的x int y=GetSystemMetrics(SM_CYSCREEN); //获取屏幕的分辨率的y CDialog::ModifyStyle(WS_BORDER,0,0); //清除VC的对话框 this->SetWindowPos(&wndTopMost,0,0,x,y, SWP_SHOWWINDOW); /*bo add end*/ return TRUE; // return TRUE unless you set the focus to a control}void ShowDlgS::OnMouseMove(UINT nFlags, CPoint point){ // TODO: 在此添加消息处理程序代码和/或调用默认值 if (!m_bBegin||m_bEnd) { return; } m_ptEnd=point; //while move mouse clean reprint the window Invalidate(true); //darw rec CDC *pDC=GetDC(); BLENDFUNCTION bf; bf.BlendOp =0; bf.BlendFlags =0; bf.SourceConstantAlpha=50; bf.AlphaFormat = 0; int bmWidth; int bmHeight; bmWidth=bmHeight=600; CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC,bmWidth,bmHeight); CBitmap *pold=MemDC.SelectObject(&bitmap); CBrush brush(RGB(255,0,0)); CBrush *pL=MemDC.SelectObject(&brush); CRgn rgn; MemDC.Rectangle(m_ptBegin.x,m_ptMid.y,m_ptEnd.x,m_ptEnd.y); rgn.CreateRectRgn(m_ptBegin.x,m_ptMid.y,m_ptEnd.x,m_ptEnd.y); pDC->SelectClipRgn(&rgn); AlphaBlend(pDC->m_hDC, 0,0,point.x+bmWidth,point.y+bmHeight, MemDC.GetSafeHdc(),0,0,bmWidth,bmHeight,bf); rgn.DeleteObject(); MemDC.Rectangle(m_ptMid.x,m_ptBegin.y,m_ptEnd.x,m_ptMid.y); rgn.CreateRectRgn(m_ptMid.x,m_ptBegin.y,m_ptEnd.x,m_ptMid.y); pDC->SelectClipRgn(&rgn); AlphaBlend(pDC->m_hDC, 0,0,point.x+bmWidth,point.y+bmHeight, MemDC.GetSafeHdc(),0,0,bmWidth,bmHeight,bf); rgn.DeleteObject(); //last point m_ptMid=point;}
4.用来保存位图的文件
screen.h
#pragma onceHBITMAP myGetScreenBmp(CRect &rc);//截屏函数,rc为截屏区域,用屏幕坐标bool mySaveBitmapToFile(HBITMAP hBitmap , CString lpFileName);//保存位图函数
screen.cpp
#include "stdafx.h"#include "screen.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endifbool mySaveBitmapToFile(HBITMAP hBitmap, CString lpFileName){//设备描述表 HDC hDC;//当前显示分辨率下每个像素所占字节数int iBits;//位图中每个像素所占字节数WORD wBitCount;//定义调色板大小 DWORD dwPaletteSize=0;// 位图中像素字节大小DWORDdwBmBitsSize = 0;// 位图文件大小DWORD dwDIBSize = 0;// 写入文件字节数DWORD dwWritten = 0;BITMAP Bitmap; BITMAPFILEHEADER bmfHdr;//位图文件头结构 BITMAPINFOHEADER bi;//位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构,定义文件,分配内存句柄,调色板句柄//计算位图文件每个像素所占字节数HANDLE fh, hDib, hPal,hOldPal=NULL; hDC = CreateDC(_T("DISPLAY"),NULL,NULL,NULL);iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);DeleteDC(hDC);if (iBits <= 1)wBitCount = 1;else if (iBits <= 4)wBitCount = 4;else if (iBits <= 8)wBitCount = 8;else {if (iBits <= 24)wBitCount = 24;elsewBitCount = 32;//原来没有,应有}//计算调色板大小if (wBitCount <= 8)dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);//设置位图信息头结构GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);bi.biSize = sizeof(BITMAPINFOHEADER);bi.biWidth = Bitmap.bmWidth;bi.biHeight = Bitmap.bmHeight;bi.biPlanes = 1;bi.biBitCount = wBitCount;bi.biCompression = BI_RGB;bi.biSizeImage = 0;bi.biXPelsPerMeter = 0;bi.biYPelsPerMeter = 0;bi.biClrUsed = 0;bi.biClrImportant = 0;dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;//为位图内容分配内存hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));if(hDib==NULL)AfxMessageBox(_T("null"));lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);*lpbi = bi;// 处理调色板 hPal = GetStockObject(DEFAULT_PALETTE);if (hPal){hDC = ::GetDC(NULL);hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);RealizePalette(hDC);}// 获取该调色板下新的像素值GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);//恢复调色板 if (hOldPal){SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);RealizePalette(hDC);::ReleaseDC(NULL, hDC);}//创建位图文件 fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);if (fh == INVALID_HANDLE_VALUE)return FALSE;// 设置位图文件头bmfHdr.bfType = 0x4D42; // "BM"dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; bmfHdr.bfSize = dwDIBSize;bmfHdr.bfReserved1 = 0;bmfHdr.bfReserved2 = 0;bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;// 写入位图文件头WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);// 写入位图文件其余内容WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);//消除内存分配 GlobalUnlock(hDib);GlobalFree(hDib);CloseHandle(fh);return TRUE;}HBITMAP myGetScreenBmp(CRect &rc)//rc为屏幕坐标,非客户区坐标{HWND hwnd = ::GetDesktopWindow();HDC hsrc = ::GetDC(hwnd);HDC hmemdc = ::CreateCompatibleDC(hsrc);rc.NormalizeRect();SIZE sz;sz.cx=rc.right-rc.left;sz.cy=rc.bottom-rc.top;HBITMAP hbmp = ::CreateCompatibleBitmap(hsrc,sz.cx,sz.cy);HGDIOBJ holdbmp = ::SelectObject(hmemdc,hbmp);::BitBlt(hmemdc,0,0,sz.cx,sz.cx,hsrc,rc.left,rc.top,SRCCOPY);::SelectObject(hmemdc,holdbmp);::DeleteObject(hmemdc);::ReleaseDC(hwnd,hsrc);return hbmp;}
5.还没结束。
a.对截图的过程中,还没充分理解。
b. 希望能简化到一个对话框中。
- 我想写个截图程序
- 我想写个程序
- 我想写程序
- 我想写一个小程序
- 我想利用时钟写个无限弹窗的小程序 ,但是程序会自动停止
- 用C#写屏幕截图小程序
- GUI 剖析之 3)我想写画图程序
- GUI 剖析之 4)我想写动画程序
- GUI 剖析之5) 我想写音乐贺卡程序
- GUI 剖析之 7)我想写不规则窗口程序
- 写了个程序
- 拜托写个程序,
- 写个atoi程序
- 我想写研发笔记...
- 我想写点东西
- 我想写博客了
- 我想写一个代码
- 我想写博客
- IPSec configuration procedure
- 粤语忌讳
- 关于#pragma comment(lib,"ws2_32.lib")(
- spark中聊天记录的存储
- 过滤条件,下拉条的形式!!的插件
- 我想写个截图程序
- Jsp学习——servlet详解
- gcc命令之 objdump
- 价格面议插件1!!!!!!
- Android编译全过程
- Chapter 1. Introduction
- android sdk 源码下载
- 客户填写发货方式的内容备注
- 修改spark install4j配置文件使得安装程序语言为中文