用Visual C++设计屏幕抓图程序

来源:本站
导读:目前正在解读《用Visual C++设计屏幕抓图程序》的相关信息,《用Visual C++设计屏幕抓图程序》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《用Visual C++设计屏幕抓图程序》的详细说明。
简介:本实例通过一个钩子DLL实现了屏幕抓图的功能,它有一个缺陷,那就是只能保存整个屏幕图像,不过可以在此基础上,实现屏幕任意区域的抓图功能.

在Windows操作系统中,当用户按下"PrintScreen"按钮后,Windows自动将当前屏幕的图像拷贝到系统剪贴板中,这时可以通过"画笔"这个小程序将剪贴板中的内容保存成图像文件,可以看出,如果需要将当前屏幕保存下来还是比较麻烦的,能否可以自己编写一个应用程序,自动将当前屏幕的内容保存到一个图像文件中去呢?这个答案是肯定的,本实例应用程序就是利用通用的热键管理DLL库实现的热键功能,在收到热键通知后截取屏幕的内容并保存到bmp文件中。例如我们设置图片保存路径为c:,热键为F9 + Control,然后按Change按钮设置好热键,那么当我们按下CTRL+F9后,当前界面将以BMP图像文件的格式被保存在C:目录下。

一、实现方法

热键管理DLL实际上是一个键盘钩子,由它来监视系统的键盘事件。如果有和程序登记符合的按键组合就通知该程序的窗口。为了应用方便,本实例把它做成了一个标准的管理库来为其它的程序通过热键服务,它有两个输出函数:AddHotkey()和DeleteHotkey(),程序只需要调用这两个函数就可以了,如果编译之后不用改变热键,则只需要AddHotkey就可以了。DLL中的所有的全局变量都放在一个共享段中,定义如下:

#pragma data_seg("shareddata")

HHOOK hHook =NULL; //钩子句柄

UINT nHookCount =0; //挂接的程序数目

static UCHAR HotKey[MAX_KEY] = {0}; //热键虚拟键码

static UCHAR HotKeyMask[MAX_KEY] = {0}; //组合掩码, control=4,alt=2,shift=1

static HWND hCallWnd[MAX_KEY] = {0}; //window handle associated with hotkey

static int KeyCount =0;

static UCHAR MaskBits =0; //00000 Ctrl=4 & Alt=2 & Shift=1

#pragma data_seg()

关于共享段,有几点重要的说明:一是必须在链接选项里指定该段为共享:一种方法是在project->settings->link->object/library中加上/section:shareddata,rws;第二种方法是在def文件的sections里加上一句shareddata read write shared;第三种指定共享段的方法在程序里加上一句#pragma comment(linker,"section:shareddata,rws")。二是所有的变量必须初始化,否则链接程序会把它放到普通数据段。三是如果不初始化变量,需要在段外用"__declspec(allocate("shareddata")) 变量类型 变量名"的方式定义。

DLL中的两个输出函数分别用来添加/删除热键,函数代码如下:

BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR

cKey,UCHAR cMask)

{

BOOL bAdded=FALSE;

for(int index=0;index<MAX_KEY;index++){

if(hCallWnd[index]==0){

hCallWnd[index]=hWnd;

HotKey[index]=cKey;

HotKeyMask[index]=cMask;

bAdded=TRUE;

KeyCount++;

break;

}

}

return bAdded;

}

//删除热键

BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,

UCHAR cKey,UCHAR cMask)

{

BOOL bRemoved=FALSE;

for(int index=0;index<MAX_KEY;index++){

if(hCallWnd[index]==hWnd){

if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){

hCallWnd[index]=NULL;

HotKey[index]=0;

HotKeyMask[index]=0;

bRemoved=TRUE;

KeyCount--;

break;

}

}

}

return bRemoved;

}

DLL中的钩子函数如下:

LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)

{

BOOL bProcessed=FALSE;

if(HC_ACTION==nCode)

{

if((lParam&0xc0000000)==0xc0000000){// 有键松开

switch(wParam)

{

case VK_MENU:

MaskBits&=~ALTBIT;

break;

case VK_CONTROL:

MaskBits&=~CTRLBIT;

break;

case VK_SHIFT:

MaskBits&=~SHIFTBIT;

break;

default: //judge the key and send message

break;

}

for(int index=0;index<MAX_KEY;index++){

if(hCallWnd[index]==NULL)

continue;

if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))

{

SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);

bProcessed=TRUE;

}

}

}

else if((lParam&0xc000ffff)==1){ //有键按下

switch(wParam)

{

case VK_MENU:

MaskBits|=ALTBIT;

break;

case VK_CONTROL:

MaskBits|=CTRLBIT;

break;

case VK_SHIFT:

MaskBits|=SHIFTBIT;

break;

default: //judge the key and send message

break;

}

for(int index=0;index<MAX_KEY;index++){

if(hCallWnd[index]==NULL)

continue;

if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))

{

SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);

bProcessed=TRUE;

}

}

}

if(!bProcessed){ //一般按键事件,为监视键盘的程序留出余地

for(int index=0;index<MAX_KEY;index++){

if(hCallWnd[index]==NULL)

continue;

if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))

SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);

//lParam的意义可看MSDN中WM_KEYDOWN部分

}

}

}

return CallNextHookEx( hHook, nCode, wParam, lParam );

}

抓图程序是一个基于对话框的程序,它在建立对话框的时候调用前面的DLL,登记热键,因此需要将hook.lib添加到工程里,在程序里给出两个DLL函数的定义,也可以写个头文件,再包含进来以下代码:

BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);

BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);

为了添加应用程序对热键通知事件的响应,程序中用的办法是重载WindowProc()函数,该函数代码如下:

LRESULT CCaptureDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

if(message==WM_HOTKEY&&lParam==WM_KEYDOWN)

{ //lParam表示是按下还是松开,如果有多个热键,由wParam来区分

SaveBmp();

return FALSE;

}

…… //其它处理及默认处理

}

将屏幕图像保存到BMP文件中的任务是由函数SaveBmp()来完成的,具体实现参见代码部分。另外为了顺利实现屏幕抓图,程序中还实现了"托盘"功能,由于这一部分本书在实例中已经专门介绍过了,所以不再赘述,读者朋友可以参考相关实例。

最后需要提醒读者朋友们注意的是,源程序的编译与使用时要先编译hook.dll并将其放在系统目录(win2000/NT是system32,98/ME是system),然后编译对话框程序运行即可。

二、编程步骤

1、 启动Visual C++,生成一个DLL项目和一个基于对话框的应用程序项目,并将两个项目分别命名为"Hook"和"Capture";

2、 在"Hook"项目中导出AddHotkey()、DeleteHotkey()函数;

3、 在"Capture"项目中按照图一所示设置对话框的界面,具体设置参见代码部分;

4、 使用Class Wizard在"Capture"项目中添加按钮的鼠标单击消息响应函数,并重载对话框的WindowProc()函数;

5、 添加代码,编译运行程序。

三、程序码

////////////////////////////////////////////////////////// Hook.h : main header file for the HOOK DLL#if !defined(AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_)#define AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__#error include ''stdafx.h'' before including this file for PCH#endif#include "resource.h" // main symbols class CHookApp : public CWinApp{public:CHookApp();// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CHookApp)public:virtual BOOL InitInstance();virtual int ExitInstance();//}}AFX_VIRTUAL//{{AFX_MSG(CHookApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam);BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);BOOL InitHotkey();BOOL UnInit();#endif ////////// Hook.cpp : Defines the initialization routines for the DLL.#include "stdafx.h"#include "hook.h"#include #ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define MAX_KEY 100#define CTRLBIT 0x04#define ALTBIT 0x02#define SHIFTBIT 0x01 #pragma data_seg("shareddata")HHOOK hHook =NULL;UINT nHookCount =0;static UCHAR HotKey[MAX_KEY] = {0}; //hotkeystatic UCHAR HotKeyMask[MAX_KEY] = {0}; //flag for hotkey, value is VK_CONTRL or VK_NEMU or VK_SHIFTstatic HWND hCallWnd[MAX_KEY] = {0}; //window associated with hotkeystatic int KeyCount =0;static UCHAR MaskBits =0; //00000 Ctrl Alt Shift#pragma data_seg()HINSTANCE hins;void VerifyWindow();BEGIN_MESSAGE_MAP(CHookApp, CWinApp)//{{AFX_MSG_MAP(CHookApp)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSG_MAPEND_MESSAGE_MAP()CHookApp::CHookApp(){// TODO: add construction code here,// Place all significant initialization in InitInstance}CHookApp theApp;LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam){ BOOL bProcessed=FALSE;if(HC_ACTION==nCode){if((lParam&0xc0000000)==0xc0000000){// Key upswitch(wParam){case VK_MENU:MaskBits&=~ALTBIT;break;case VK_CONTROL:MaskBits&=~CTRLBIT;break;case VK_SHIFT:MaskBits&=~SHIFTBIT;break;default: //judge the key and send messagebreak;}for(int index=0;index<MAX_KEY;index++){if(hCallWnd[index]==NULL)continue;if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits)){SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);bProcessed=TRUE;}}}else if((lParam&0xc000ffff)==1){ //Key downswitch(wParam){case VK_MENU:MaskBits|=ALTBIT;break;case VK_CONTROL:MaskBits|=CTRLBIT;break;case VK_SHIFT:MaskBits|=SHIFTBIT;break;default: //judge the key and send messagebreak;}for(int index=0;index<MAX_KEY;index++){if(hCallWnd[index]==NULL)continue;if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits)){SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);bProcessed=TRUE;}}}if(!bProcessed){for(int index=0;index<MAX_KEY;index++){if(hCallWnd[index]==NULL)continue;if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);}}}return CallNextHookEx( hHook, nCode, wParam, lParam ); }BOOL InitHotkey(){if(hHook!=NULL){nHookCount++;return TRUE;}elsehHook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);if(hHook!=NULL)nHookCount++;return (hHook!=NULL);}BOOL UnInit(){ if(nHookCount>1){nHookCount--;return TRUE;}BOOL unhooked = UnhookWindowsHookEx(hHook);if(unhooked==TRUE){nHookCount=0;hHook=NULL;}return unhooked;} BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask){BOOL bAdded=FALSE;for(int index=0;index<MAX_KEY;index++){if(hCallWnd[index]==0){hCallWnd[index]=hWnd;HotKey[index]=cKey;HotKeyMask[index]=cMask;bAdded=TRUE;KeyCount++;break;}}return bAdded;}BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask){BOOL bRemoved=FALSE;for(int index=0;index<MAX_KEY;index++){if(hCallWnd[index]==hWnd){if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){hCallWnd[index]=NULL;HotKey[index]=0;HotKeyMask[index]=0;bRemoved=TRUE;KeyCount--;break;}}}return bRemoved;}void VerifyWindow(){for(int i=0;i<MAX_KEY;i++){if(hCallWnd[i]!=NULL){if(!IsWindow(hCallWnd[i])){hCallWnd[i]=NULL;HotKey[i]=0;HotKeyMask[i]=0;KeyCount--;}}}}BOOL CHookApp::InitInstance() {AFX_MANAGE_STATE(AfxGetStaticModuleState());hins=AfxGetInstanceHandle();InitHotkey();return CWinApp::InitInstance();}int CHookApp::ExitInstance() {VerifyWindow();UnInit();return CWinApp::ExitInstance();}////////////////////////////////////////////////////////////////////// CaptureDlg.h : header file#if !defined(AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_)#define AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class CCaptureDlg : public CDialog{// Constructionpublic:BOOL bTray;BOOL bRegistered;BOOL RegisterHotkey();UCHAR cKey;UCHAR cMask;void DeleteIcon();void AddIcon();UINT nCount;void SaveBmp();CCaptureDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CCaptureDlg)enum { IDD = IDD_CAPTURE_DIALOG };CComboBox m_Key;BOOL m_bControl;BOOL m_bAlt;BOOL m_bShift;CString m_Path;CString m_Number;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CCaptureDlg)public:virtual BOOL PreTranslateMessage(MSG* pMsg);protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV supportvirtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);//}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CCaptureDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();virtual void OnCancel();afx_msg void OnAbout();afx_msg void OnBrowse();afx_msg void OnChange();//}}AFX_MSGDECLARE_MESSAGE_MAP()};#endif ////////////////////// CaptureDlg.cpp : implementation file#include "stdafx.h"#include "Capture.h"#include "CaptureDlg.h"#include #pragma comment(lib,"hook.lib")#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define IDM_SHELL WM_USER+1BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);UCHAR Key_Table[]={0x78,0x79,0x7a,0x7b,0x6a,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};class CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()CCaptureDlg::CCaptureDlg(CWnd* pParent /*=NULL*/): CDialog(CCaptureDlg::IDD, pParent){//{{AFX_DATA_INIT(CCaptureDlg)m_bControl = FALSE;m_bAlt = FALSE;m_bShift = FALSE;m_Path = _T("c:");m_Number = _T("0 picture captured.");nCount=0;bRegistered=FALSE;bTray=FALSE;//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CCaptureDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CCaptureDlg)DDX_Control(pDX, IDC_KEY, m_Key);DDX_Check(pDX, IDC_CONTROL, m_bControl);DDX_Check(pDX, IDC_ALT, m_bAlt);DDX_Check(pDX, IDC_SHIFT, m_bShift);DDX_Text(pDX, IDC_PATH, m_Path);DDX_Text(pDX, IDC_NUMBER, m_Number);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CCaptureDlg, CDialog)//{{AFX_MSG_MAP(CCaptureDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(ID_ABOUT, OnAbout)ON_BN_CLICKED(IDC_BROWSE, OnBrowse)ON_BN_CLICKED(ID_CHANGE, OnChange)//}}AFX_MSG_MAPEND_MESSAGE_MAP()BOOL CCaptureDlg::OnInitDialog(){CDialog::OnInitDialog();ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}SetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small iconm_Key.SetCurSel(0); RegisterHotkey();CMenu* pMenu=GetSystemMenu(FALSE);pMenu->DeleteMenu(SC_MAXIMIZE,MF_BYCOMMAND);pMenu->DeleteMenu(SC_SIZE,MF_BYCOMMAND);pMenu->DeleteMenu(SC_RESTORE,MF_BYCOMMAND);return TRUE; // return TRUE unless you set the focus to a control}void CCaptureDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}void CCaptureDlg::OnPaint() {if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}HCURSOR CCaptureDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CCaptureDlg::OnCancel() {if(bTray)DeleteIcon();CDialog::OnCancel();}void CCaptureDlg::OnAbout() {CAboutDlg dlg;dlg.DoModal();}void CCaptureDlg::OnBrowse() {CString str;BROWSEINFO bi;char name[MAX_PATH];ZeroMemory(&bi,sizeof(BROWSEINFO));bi.hwndOwner=GetSafeHwnd();bi.pszDisplayName=name;bi.lpszTitle="Select folder";bi.ulFlags=BIF_RETURNONLYFSDIRS;LPITEMIDLIST idl=SHBrowseForFolder(&bi);if(idl==NULL)return;SHGetPathFromIDList(idl,str.GetBuffer(MAX_PATH));str.ReleaseBuffer();m_Path=str;if(str.GetAt(str.GetLength()-1)!='''')m_Path+="";UpdateData(FALSE);}void CCaptureDlg::SaveBmp(){CDC dc;dc.CreateDC("DISPLAY",NULL,NULL,NULL);CBitmap bm;int Width=GetSystemMetrics(SM_CXSCREEN);int Height=GetSystemMetrics(SM_CYSCREEN);bm.CreateCompatibleBitmap(&dc,Width,Height);CDC tdc;tdc.CreateCompatibleDC(&dc);CBitmap*pOld=tdc.SelectObject(&bm);tdc.BitBlt(0,0,Width,Height,&dc,0,0,SRCCOPY);tdc.SelectObject(pOld);BITMAP btm;bm.GetBitmap(&btm);DWORD size=btm.bmWidthBytes*btm.bmHeight;LPSTR lpData=(LPSTR)GlobalAllocPtr(GPTR,size);BITMAPINFOHEADER bih;bih.biBitCount=btm.bmBitsPixel;bih.biClrImportant=0;bih.biClrUsed=0;bih.biCompression=0;bih.biHeight=btm.bmHeight;bih.biPlanes=1;bih.biSize=sizeof(BITMAPINFOHEADER);bih.biSizeImage=size;bih.biWidth=btm.bmWidth;bih.biXPelsPerMeter=0;bih.biYPelsPerMeter=0;GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);static int filecount=0;CString name;name.Format("pict%04d.bmp",filecount++);name=m_Path+name;BITMAPFILEHEADER bfh;bfh.bfReserved1=bfh.bfReserved2=0;bfh.bfType=((WORD)(''M''<< 8)|''B'');bfh.bfSize=54+size;bfh.bfOffBits=54;CFile bf;if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)){bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER));bf.WriteHuge(lpData,size);bf.Close();nCount++;}GlobalFreePtr(lpData);if(nCount==1)m_Number.Format("%d picture captured.",nCount);elsem_Number.Format("%d pictures captured.",nCount);UpdateData(FALSE);}BOOL CCaptureDlg::PreTranslateMessage(MSG* pMsg) {if(pMsg -> message == WM_KEYDOWN){if(pMsg -> wParam == VK_ESCAPE)return TRUE;if(pMsg -> wParam == VK_RETURN)return TRUE;} return CDialog::PreTranslateMessage(pMsg);}LRESULT CCaptureDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {if(message==WM_HOTKEY&&lParam==WM_KEYDOWN){SaveBmp();return FALSE;}if(message==IDM_SHELL&&lParam==WM_RBUTTONUP){CMenu pop;pop.LoadMenu(MAKEINTRESOURCE(IDR_MENU1));CMenu*pMenu=pop.GetSubMenu(0);pMenu->SetDefaultItem(ID_EXITICON);CPoint pt;GetCursorPos(&pt);int id=pMenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_NONOTIFY|TPM_RETURNCMD|TPM_LEFTBUTTON,pt.x,pt.y,this);if(id==ID_EXITICON)DeleteIcon();else if(id==ID_EXIT)OnCancel();return FALSE;}LRESULT res= CDialog::WindowProc(message, wParam, lParam);if(message==WM_SYSCOMMAND&&wParam==SC_MINIMIZE)AddIcon();return res;}void CCaptureDlg::AddIcon(){NOTIFYICONDATA data;data.cbSize=sizeof(NOTIFYICONDATA);CString tip;tip.LoadString(IDS_ICONTIP);data.hIcon=GetIcon(0);data.hWnd=GetSafeHwnd();strcpy(data.szTip,tip);data.uCallbackMessage=IDM_SHELL;data.uFlags=NIF_ICON|NIF_MESSAGE |NIF_TIP ;data.uID=98;Shell_NotifyIcon(NIM_ADD,&data);ShowWindow(SW_HIDE);bTray=TRUE;}void CCaptureDlg::DeleteIcon(){NOTIFYICONDATA data;data.cbSize=sizeof(NOTIFYICONDATA);data.hWnd=GetSafeHwnd();data.uID=98;Shell_NotifyIcon(NIM_DELETE,&data);ShowWindow(SW_SHOW);SetForegroundWindow();ShowWindow(SW_SHOWNORMAL);bTray=FALSE;}void CCaptureDlg::OnChange() {RegisterHotkey();}BOOL CCaptureDlg::RegisterHotkey(){UpdateData();UCHAR mask=0;UCHAR key=0;if(m_bControl)mask|=4;if(m_bAlt)mask|=2;if(m_bShift)mask|=1;key=Key_Table[m_Key.GetCurSel()];if(bRegistered){DeleteHotkey(GetSafeHwnd(),cKey,cMask);bRegistered=FALSE;}cMask=mask;cKey=key;bRegistered=AddHotkey(GetSafeHwnd(),cKey,cMask);return bRegistered;} 

提醒:《用Visual C++设计屏幕抓图程序》最后刷新时间 2024-03-14 00:58:39,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《用Visual C++设计屏幕抓图程序》该内容的真实性请自行鉴别。