www.pudn.com > ScrSnapSrc.zip > ScreenSnapDlg.cpp


////////////////////////////////////////////////////////////////////////////// 
//类名:CScreenSnapDlg 
//功能:轻松抓图实现对话框 
//作者:徐景周(jingzhou_xu@163.net) 
//组织:未来工作室(Future Studio) 
//日期:2001.12.1 
///////////////////////////////////////////////////////////////////////////// 
#include "stdafx.h" 
#include "ScreenSnap.h" 
#include "ScreenSnapDlg.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define WM_SNAPHOTKEY WM_USER + 101  //自定义系统热键消息,用来抓图 
#define WM_TRAYNOTIFY WM_USER + 100  //自定义系统托盘消息 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	CPictureEx	m_Flag;				//GIF动态图像显示 
	CHyperLink	m_Mail;				//超链接形式显示EMAIL 
	CWBButton	m_OK;				//位图按钮 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	virtual BOOL OnInitDialog(); 
	//}}AFX_MSG 
	DECLARE_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) 
	DDX_Control(pDX, IDC_FLAG, m_Flag); 
	DDX_Control(pDX, IDC_STATIC_MAIL, m_Mail); 
	DDX_Control(pDX, IDOK, m_OK); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
////////////////////////////////////////////////////////////////////////////// 
//涵数名:OnInitDialog 
//功能:初始化"关于"对话框 
//作者:徐景周(jingzhou_xu@163.net) 
//组织:未来工作室(Future Studio) 
//日期:2001.12.1 
///////////////////////////////////////////////////////////////////////////// 
BOOL CAboutDlg::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	//设置“关于”对话框的位图按钮显示 
	m_OK.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
 
	//加入EMAIL的超连接 
    m_Mail.SetURL(_T("mailto:jingzhou_xu@163.net")); 
	m_Mail.SetUnderline(FALSE);	 
 
	//显示动态GIF图像logo 
	if(m_Flag.Load(MAKEINTRESOURCE(IDR_FLAG),_T("GIF"))) 
	{ 
		m_Flag.SetBkColor(RGB(160,180,220)); 
		m_Flag.Draw();	 
	}	 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CScreenSnapDlg dialog 
CScreenSnapDlg::CScreenSnapDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CScreenSnapDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CScreenSnapDlg) 
	//在此初始化使用说明文字信息 
	m_Usage = _T("\n使用说明: \n    点击<抓图>按钮后开始抓取图像,用鼠标选中您要抓取的图像范围后(鼠标会自动高亮显示该图像),按键盘上的热键既可完成抓图。程序会自动将此选中图像复制到系统剪切板中,然后到您需要它的文档或画图中,直接粘贴既可,您还可以将已经抓好的图形保存到本地硬盘上。 同时,支持屏幕右下角的系统区图标交互操作。^O^"); 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	//系统区显示的图标文件 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CScreenSnapDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CScreenSnapDlg) 
	DDX_Control(pDX, IDC_SAVEBMP, m_Save); 
	DDX_Control(pDX, IDC_DESCRIPTION, m_Description); 
	DDX_Control(pDX, IDC_HIDEWINDOW, m_Hide); 
	DDX_Control(pDX, IDCANCEL, m_Exit); 
	DDX_Control(pDX, IDC_SCREENSNAP, m_Snap); 
	DDX_Control(pDX, ID_ABOUT, m_About); 
	DDX_Text(pDX, IDC_USAGE, m_Usage); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CScreenSnapDlg, CDialog) 
	//{{AFX_MSG_MAP(CScreenSnapDlg) 
	ON_MESSAGE(WM_TRAYNOTIFY, OnTrayNotification)  //自定义系统托盘消息涵数  
	ON_MESSAGE(WM_HOTKEY,OnHotKey)				   //自定义系统热键消息涵数 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(IDC_SCREENSNAP, OnScreensnap) 
	ON_BN_CLICKED(ID_ABOUT, OnAbout) 
	ON_COMMAND(IDR_SHOWHIDE, OnShowhide) 
	ON_COMMAND(IDR_EXIT, OnExit) 
	ON_WM_LBUTTONDOWN() 
	ON_WM_TIMER() 
	ON_BN_CLICKED(IDC_HIDEWINDOW, OnHideWindow) 
	ON_COMMAND(IDR_SNAPWINDOW, OnSnapWindow) 
	ON_BN_CLICKED(IDC_SAVEBMP, OnSavebmp) 
	ON_COMMAND(IDR_ABOUT, OnAbout) 
	ON_COMMAND(IDR_SAVEBMP, OnSaveBmp) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CScreenSnapDlg message handlers 
////////////////////////////////////////////////////////////////////////////// 
//涵数名:OnInitDialog 
//功能:初始化对话框 
//作者:徐景周(jingzhou_xu@163.net) 
//组织:未来工作室(Future Studio) 
//日期:2001.12.1 
///////////////////////////////////////////////////////////////////////////// 
BOOL CScreenSnapDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	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); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
     
	//创建系统区图标 
	if (!m_TrayIcon.Create(this,  
				IDR_POPUPMENU,  
				_T("轻松抓图袖珍版 V1.0"),  
				&m_hIcon,  
				1,							//一幅图像 
				1000,						//延时1秒变化 
				WM_TRAYNOTIFY)) 
	{ 
		AfxMessageBox(_T("错误:创建系统图标失败!"), MB_OK | MB_ICONSTOP); 
		return -1; 
	} 
 
	//设置位图按钮显示 
	m_Snap.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
	m_Save.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
	m_Hide.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
	m_About.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
	m_Exit.LoadBitmaps(IDB_BUTTON,5, 5, 5, 5, 4 ); 
 
	//描述信息初始值 
	m_Description.SetWindowText("抓图操作开始后,按F3键完成抓图!"); 
 
	//初始置抓取图像窗口操作为假 
	m_bStartSnapWindow = FALSE; 
 
	//初始置选中图像窗口为空 
	m_hwndFoundWindow = NULL; 
 
	//注册系统热键,用来热键抓图 
	RegisterHotKey(GetSafeHwnd(),WM_SNAPHOTKEY,NULL ,VK_F3); 
 
	//初始置窗体位于最顶层 
	SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 
	 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CScreenSnapDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CScreenSnapDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int 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 icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CScreenSnapDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
//******************************************************************************** 
//* 名称:OnHotKey 
//* 功能:F3键释放抓取操作,并复制选中图像窗口到系统剪切板中 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 组织:未来工作室(Future Studio) 
//* 日期:2001.12.1 
//******************************************************************************** 
LRESULT CScreenSnapDlg::OnHotKey(WPARAM wParam,LPARAM lParam) 
{ 
	if(wParam==WM_SNAPHOTKEY) 
	{ 
	  if(m_bStartSnapWindow)								//当正在抓取操作时 
	  { 
		ReleaseCapture();									//释放全屏捕捉 
		 
		m_bStartSnapWindow = FALSE;							//重置抓取操作为假 
 
		KillTimer(1);										//消除抓取定时器操作 
		 
		if (m_hwndFoundWindow)								//如果已有选中窗口的话,则刷新它 
		{ 
			RefreshWindow (m_hwndFoundWindow); 
		} 
 
	    CaptureWindowToClipboard(m_hwndFoundWindow);		//将选中的图像窗口复制到系统剪切板中 
		Sleep(500);  
		ShowWindow(SW_SHOW);                                //恢复窗口正常显示 
		m_Description.SetWindowText("已成功的将选中图像复制到系统剪切板中!"); 
	  } 
	} 
	 
	return 0; 
} 
 
//******************************************************************************** 
//* 名称:DestroyWindow 
//* 功能:程序关闭时的处理工作 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 组织:未来工作室(Future Studio) 
//* 日期:2001.12.1 
//******************************************************************************** 
BOOL CScreenSnapDlg::DestroyWindow()  
{ 
	if(m_bStartSnapWindow)									//当正在抓取操作时 
	{ 
		ReleaseCapture();									//释放全屏捕捉 
		 
		m_bStartSnapWindow = FALSE;							//重置抓取操作为假 
 
		KillTimer(1);										//消除抓取定时器操作 
		 
		if (m_hwndFoundWindow)								//如果已有选中窗口的话,则刷新它 
		{ 
			RefreshWindow (m_hwndFoundWindow); 
		} 
	} 
 
	//注销已注册的系统热键 
	UnregisterHotKey(GetSafeHwnd(),WM_SNAPHOTKEY);	 
 
	return CDialog::DestroyWindow(); 
} 
 
//******************************************************************************** 
//* 名称:OnTrayNotification() 
//* 功能:系统区创建的图标映射涵数 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 组织:未来工作室(Future Studio) 
//* 日期:2001.12.1 
//******************************************************************************** 
LRESULT CScreenSnapDlg::OnTrayNotification(WPARAM wParam, LPARAM lParam) 
{ 
   
  return m_TrayIcon.OnTrayNotification(wParam, lParam); 
} 
 
//******************************************************************************** 
//* 名称:FindTrayWnd 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:在显示窗体动画效果前,先寻找系统区位置 
//******************************************************************************** 
BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam) 
{ 
    TCHAR szClassName[256]; 
    GetClassName(hwnd, szClassName, 255); 
 
    // 比较窗口类名 
    if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0) 
    { 
        CRect *pRect = (CRect*) lParam; 
        ::GetWindowRect(hwnd, pRect); 
        return TRUE; 
    } 
 
    // 当找到时钟窗口时表示可以结束了 
    if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0) 
    { 
        CRect *pRect = (CRect*) lParam; 
        CRect rectClock; 
        ::GetWindowRect(hwnd, rectClock); 
        pRect->right = rectClock.left; 
        return FALSE; 
    } 
  
    return TRUE; 
} 
 
//******************************************************************************** 
//* 名称:WinAnimation 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:显示窗口动画效果的涵数 
//******************************************************************************** 
void CScreenSnapDlg::WinAnimation(BOOL ShowFlag)  
{ 
    CRect rect(0,0,0,0); 
 
    // 查找托盘窗口  
    CWnd* pWnd = FindWindow("Shell_TrayWnd", NULL); 
    if (pWnd) 
    { 
        pWnd->GetWindowRect(rect); 
		EnumChildWindows(pWnd->m_hWnd, FindTrayWnd, (LPARAM)&rect); 
		//rect 为托盘区矩形 
		CRect rcWnd; 
		GetWindowRect(rcWnd); 
		if(ShowFlag)					//窗体滑向系统区 
		  DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rcWnd,rect); 
		else							//窗体从系统区滑出 
		  DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rect,rcWnd); 
    } 
} 
 
////////////////////////////////////////////////////////////////////////////// 
//涵数名:OnScreensnap 
//功能:开始抓图操作 
//作者:徐景周(jingzhou_xu@163.net) 
//组织:未来工作室(Future Studio) 
//日期:2001.12.1 
///////////////////////////////////////////////////////////////////////////// 
void CScreenSnapDlg::OnScreensnap()  
{ 
	SetCapture();                        //启动全屏捕捉 
 
	if(IsWindowVisible())				 //窗体是否已隐藏 
	{ 
		ShowWindow(SW_HIDE);             //先隐藏窗体 
		WinAnimation(true);			     //窗体动画滑入到系统区中  
	} 
 
	m_bStartSnapWindow = TRUE; 
 
	m_Description.SetWindowText("正在进行抓图..."); 
 
	SetTimer(1,300,NULL);                //启动定时器,开始抓取图像 
} 
 
////////////////////////////////////////////////////////////////////////////// 
//涵数名:OnAbout 
//功能:弹出"关于"对话框 
//作者:徐景周(jingzhou_xu@163.net) 
//组织:未来工作室(Future Studio) 
//日期:2001.12.1 
///////////////////////////////////////////////////////////////////////////// 
void CScreenSnapDlg::OnAbout()  
{ 
	CAboutDlg AboutDlg; 
 
	AboutDlg.DoModal(); 
} 
 
//******************************************************************************** 
//* 名称:OnShowhide() 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:显示或隐藏对话框 
//******************************************************************************** 
void CScreenSnapDlg::OnShowhide()  
{ 
	CWnd * pFrame;					 //得到当前窗体指针 
 
	pFrame=AfxGetApp()->GetMainWnd(); 
	if(!pFrame->IsWindowVisible())	 //是否进行窗体动画,窗体已显示则不进行 
	{ 
		WinAnimation(false);		 //窗体动画从系统区滑出  
		pFrame->ShowWindow(SW_SHOW); 
	} 
    else							 //是否进行窗体动画,窗体已隐藏则不进行 
	{ 
        pFrame->ShowWindow(SW_HIDE); 
	    WinAnimation(true);			 //窗体动画滑入到系统区中  
	}	 
} 
 
//******************************************************************************** 
//* 名称:OnExit() 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:退出程序 
//******************************************************************************** 
void CScreenSnapDlg::OnExit()  
{ 
	m_TrayIcon.RemoveIcon();          //删除系统区图标 
 
	SendMessage(WM_CLOSE); 
} 
 
//******************************************************************************** 
//* 名称:toClipboard 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:将指定窗口复制到系统剪切板中 
//******************************************************************************** 
void CScreenSnapDlg::toClipboard(CWnd * wnd, BOOL FullWnd) 
{ 
     CDC dc; 
     if(FullWnd) 
        { /* 抓取整个窗口 */ 
         HDC hdc = ::GetWindowDC(wnd->m_hWnd); 
         dc.Attach(hdc); 
        } /* 抓取整个窗口 */ 
     else 
        { /* 仅抓取客户区时 */ 
         HDC hdc = ::GetDC(wnd->m_hWnd); 
         dc.Attach(hdc); 
        } /* 仅抓取客户区时 */ 
 
     CDC memDC; 
     memDC.CreateCompatibleDC(&dc); 
 
     CBitmap bm; 
     CRect r; 
     if(FullWnd) 
        wnd->GetWindowRect(&r); 
     else 
        wnd->GetClientRect(&r); 
 
     CString s; 
     wnd->GetWindowText(s); 
     CSize sz(r.Width(), r.Height()); 
     bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy); 
     CBitmap * oldbm = memDC.SelectObject(&bm); 
     memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY); 
 
     wnd->GetParent()->OpenClipboard(); 
     ::EmptyClipboard(); 
     ::SetClipboardData(CF_BITMAP, bm.m_hObject); 
     CloseClipboard(); 
 
	 //恢复原始环境 
     memDC.SelectObject(oldbm); 
     bm.Detach();   
} 
 
//******************************************************************************** 
//* 名称:toClipboard_Bio 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:将指定窗口复制到系统剪切板中(扩展) 
//******************************************************************************** 
void CScreenSnapDlg::toClipboard_Bio(CWnd * wnd, BOOL FullWnd) 
{ 
     CDC *dc; 
     if(FullWnd) 
        { /* 抓取整个窗口 */ 
		 dc = new CWindowDC(wnd); 
        } /* 抓取整个窗口 */ 
     else 
        { /* 仅抓取客户区时 */ 
		 dc = new CClientDC(wnd); 
        } /* 仅抓取客户区时 */ 
 
     CDC memDC; 
     memDC.CreateCompatibleDC(dc); 
 
     CBitmap bm; 
     CRect r; 
     if(FullWnd) 
        wnd->GetWindowRect(&r); 
     else 
         wnd->GetClientRect(&r); 
 
     CString s; 
     wnd->GetWindowText(s); 
     CSize sz(r.Width(), r.Height()); 
     bm.CreateCompatibleBitmap(dc, sz.cx, sz.cy); 
     CBitmap * oldbm = memDC.SelectObject(&bm); 
     memDC.BitBlt(0, 0, sz.cx, sz.cy, dc, 0, 0, SRCCOPY); 
 
     //直接调用OpenClipboard(),而不用wnd->GetParent()->OpenClipboard(); 
	 wnd->OpenClipboard(); 
 
     ::EmptyClipboard(); 
     ::SetClipboardData(CF_BITMAP, bm.m_hObject); 
     CloseClipboard(); 
 
	 //恢复原始环境 
     memDC.SelectObject(oldbm); 
     bm.Detach();   
 
	 delete dc; 
} 
 
//******************************************************************************** 
//* 名称:CaptureWindowToClipboard 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:将指定窗口复制到系统剪切板中 
//******************************************************************************** 
BOOL CScreenSnapDlg::CaptureWindowToClipboard (HWND hwndToCapture) 
{ 
  BOOL bRet = FALSE; 
 
  //如果"hwndToCapture"是有效窗口的话,将其复制到系统剪切板中 
  if((hwndToCapture) && (::IsWindow (hwndToCapture))) 
  { 
    bRet = TRUE; 
    toClipboard_Bio((CWnd *)CWnd::FromHandle (hwndToCapture), TRUE); 
  } 
 
  return bRet; 
} 
 
//******************************************************************************** 
//* 名称:RefreshWindow 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:刷新选中的图像窗口,消除高度显示 
//******************************************************************************** 
long CScreenSnapDlg::RefreshWindow (HWND hwndWindow) 
{ 
  long lRet = 0; 
 
  ::InvalidateRect(hwndWindow, NULL, TRUE); 
  ::UpdateWindow (hwndWindow); 
  ::RedrawWindow (hwndWindow, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 
 
  return lRet; 
} 
 
//******************************************************************************** 
//* 名称:HighlightFoundWindow 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:高度显示选中的图像窗口 
//******************************************************************************** 
long CScreenSnapDlg::HighlightFoundWindow (HWND hwndFoundWindow) 
{ 
  HDC		hWindowDC = NULL;   
  HGDIOBJ	hPrevPen = NULL;    
  HGDIOBJ	hPrevBrush = NULL;  
  RECT		rect;               
  long		lRet = 0; 
  HPEN      hRectanglePen = CreatePen (PS_SOLID, 3, RGB(256, 0, 0)); 
 
  ::GetWindowRect(hwndFoundWindow, &rect); 
 
  //获取选中窗口DC 
  hWindowDC = ::GetWindowDC(hwndFoundWindow); 
 
  if (hWindowDC) 
  { 
    //选取自定义的高亮矩形画笔 
    hPrevPen = SelectObject(hWindowDC, hRectanglePen); 
 
    //选取自定义的高亮画刷 
    hPrevBrush = SelectObject (hWindowDC, GetStockObject(HOLLOW_BRUSH)); 
 
    //在选中的图像窗口四周绘制高亮矩形 
    Rectangle(hWindowDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top); 
 
    //恢复原始画笔、画刷 
    SelectObject (hWindowDC, hPrevPen); 
 
    SelectObject (hWindowDC, hPrevBrush); 
 
    //释放DC 
    ::ReleaseDC (hwndFoundWindow, hWindowDC); 
  } 
 
  //删除创建的矩形画笔 
  if(hRectanglePen) 
	DeleteObject (hRectanglePen); 
 
  return lRet; 
} 
 
//******************************************************************************** 
//* 名称:OnLButtonDown 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:鼠标左键按下时,实现无标题移动 
//******************************************************************************** 
void CScreenSnapDlg::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	//实现窗体无标题移动 
	PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y)); 
	 
	CDialog::OnLButtonDown(nFlags, point); 
} 
 
//******************************************************************************** 
//* 名称:CheckWindowValidity 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:检验选中窗口的有效性 
//******************************************************************************** 
BOOL CScreenSnapDlg::CheckWindowValidity(HWND hwndToCheck) 
{ 
  HWND hwndTemp = NULL; 
  BOOL bRet = TRUE; 
 
  //不能为空 
  if (hwndToCheck == NULL) 
  { 
    bRet = FALSE; 
	return bRet; 
  } 
 
  //必须是一个不效窗口 
  if (IsWindow(hwndToCheck) == FALSE) 
  { 
    bRet = FALSE; 
	return bRet; 
  } 
 
  //确定它不是先前选中的窗口 
  if (hwndToCheck == m_hwndFoundWindow) 
  { 
    bRet = FALSE; 
	return bRet; 
  } 
 
  //不能是程序主窗口 
  if (hwndToCheck == this->m_hWnd) 
  { 
    bRet = FALSE; 
	return bRet; 
  } 
 
  //不能是程序中的子窗口 
  hwndTemp = ::GetParent(hwndToCheck); 
  if ((hwndTemp == this->m_hWnd)) 
  { 
    bRet = FALSE; 
	return bRet; 
  } 
 
  return bRet; 
} 
 
//******************************************************************************** 
//* 名称:OnTimer 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:鼠标移动时,获取并高亮显示选中图像窗口 
//******************************************************************************** 
void CScreenSnapDlg::OnTimer(UINT nIDEvent)  
{ 
	if(m_bStartSnapWindow)					//当正在抓取操作时 
	{ 
		POINT		CursorPoint; 
		HWND		hwndFoundWindow = NULL; 
		 
		GetCursorPos(&CursorPoint);   
		 
		//从当前鼠标所在点位置,获取其窗口句柄 
		hwndFoundWindow = ::WindowFromPoint(CursorPoint); 
		 
		//检验选中窗口的有效性 
		if (CheckWindowValidity(hwndFoundWindow)) 
		{ 
			 
			//如果先前有选中的窗口,则刷新它,以消除它的高亮显示 
			if (m_hwndFoundWindow) 
			{ 
				RefreshWindow(m_hwndFoundWindow); 
			} 
			 
			//得到选中窗口的句柄 
			m_hwndFoundWindow = hwndFoundWindow; 
			 
			//高亮显示选中窗口 
			HighlightFoundWindow(m_hwndFoundWindow); 
		} 
	} 
	 
	CDialog::OnTimer(nIDEvent); 
} 
 
//******************************************************************************** 
//* 名称:OnHideWindow 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:隐藏窗体 
//******************************************************************************** 
void CScreenSnapDlg::OnHideWindow()  
{ 
	OnShowhide(); 
} 
 
//******************************************************************************** 
//* 名称:OnSnapWindow 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:系统区菜单抓图操作 
//******************************************************************************** 
void CScreenSnapDlg::OnSnapWindow()  
{ 
	OnScreensnap();	 
} 
 
//******************************************************************************** 
//* 名称:DDBToDIB 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:设备相关转换为设备无关位图 
//******************************************************************************** 
HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_RGB */)  
{ 
    BITMAP				bm; 
    BITMAPINFOHEADER    bi; 
    LPBITMAPINFOHEADER  lpbi; 
    DWORD				dwLen; 
    HANDLE				hDIB; 
    HANDLE				handle; 
    HDC					hDC; 
    HPALETTE			hPal; 
 
    CWindowDC			dc( this ); 
    CPalette			pal; 
    //如果支持调色板的话,则建立它 
    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE ) 
    { 
        UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 ); 
        LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize]; 
        pLP->palVersion     = 0x300; 
        pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255,  
        pLP->palPalEntry ); 
 
        pal.CreatePalette( pLP ); 
 
        //释放 
        delete[] pLP; 
    } 
 
    ASSERT( bitmap.GetSafeHandle() ); 
 
    //不支持BI_BITFIELDS类型 
    if( dwCompression == BI_BITFIELDS ) 
        return NULL; 
 
    //如果调色板为空,则用默认调色板 
    hPal = (HPALETTE) pal.GetSafeHandle(); 
    if (hPal==NULL) 
        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); 
 
    //获取位图信息 
    bitmap.GetObject(sizeof(bm),(LPSTR)&bm); 
 
    //初始化位图信息头 
    bi.biSize        = sizeof(BITMAPINFOHEADER); 
    bi.biWidth        = bm.bmWidth; 
    bi.biHeight         = bm.bmHeight; 
    bi.biPlanes         = 1; 
    bi.biBitCount        = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ; 
    bi.biCompression    = dwCompression; 
    bi.biSizeImage        = 0; 
    bi.biXPelsPerMeter    = 0; 
    bi.biYPelsPerMeter    = 0; 
    bi.biClrUsed        = 0; 
    bi.biClrImportant    = 0; 
 
    //计算信息头及颜色表大小 
    int nColors = 0; 
    if(bi.biBitCount <= 8) 
        { 
        nColors = (1 << bi.biBitCount); 
        } 
    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD); 
 
    hDC = ::GetDC(NULL); 
    hPal = SelectPalette(hDC,hPal,FALSE); 
    RealizePalette(hDC); 
 
    //为信息头及颜色表分配内存 
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen); 
 
    if (!hDIB){ 
        SelectPalette(hDC,hPal,FALSE); 
        ::ReleaseDC(NULL,hDC); 
        return NULL; 
    } 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    *lpbi = bi; 
 
    //调用 GetDIBits 计算图像大小 
    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight, 
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); 
 
    bi = *lpbi; 
 
    //图像的每一行都对齐(32bit)边界 
    if (bi.biSizeImage == 0){ 
        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)  
                        * bi.biHeight; 
 
        if (dwCompression != BI_RGB) 
            bi.biSizeImage = (bi.biSizeImage * 3) / 2; 
    } 
 
    //重新分配内存大小,以便放下所有数据 
    dwLen += bi.biSizeImage; 
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ; 
    if (handle != NULL) 
        hDIB = handle; 
    else 
        { 
        GlobalFree(hDIB); 
 
        //重选原始调色板 
        SelectPalette(hDC,hPal,FALSE); 
        ::ReleaseDC(NULL,hDC); 
        return NULL; 
        } 
 
    //获取位图数据 
    lpbi = (LPBITMAPINFOHEADER)hDIB; 
 
    //最终获得的DIB 
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(), 
                0L,                      //扫描行起始处 
                (DWORD)bi.biHeight,      //扫描行数 
                (LPBYTE)lpbi             //位图数据地址 
                + (bi.biSize + nColors * sizeof(RGBQUAD)), 
                (LPBITMAPINFO)lpbi,      //位图信息地址 
                (DWORD)DIB_RGB_COLORS);  //颜色板使用RGB 
 
    if( !bGotBits ) 
    { 
        GlobalFree(hDIB); 
         
        SelectPalette(hDC,hPal,FALSE); 
        ::ReleaseDC(NULL,hDC); 
        return NULL; 
    } 
 
    SelectPalette(hDC,hPal,FALSE); 
    ::ReleaseDC(NULL,hDC); 
    return hDIB; 
} 
 
//******************************************************************************** 
//* 名称:SaveBitmapToFile 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:保存为位图文件 
//******************************************************************************** 
BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName)  
{    	  
	HDC				hDC;							//设备描述表   
    int				iBits;							//当前显示分辨率下每个像素所占字节数 
	WORD            wBitCount;						//位图中每个像素所占字节数 
	DWORD           dwPaletteSize=0,				//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 
					dwBmBitsSize, 
					dwDIBSize, dwWritten; 
	BITMAP          Bitmap;         
	BITMAPFILEHEADER   bmfHdr;						//位图属性结构     
    BITMAPINFOHEADER   bi;							//位图文件头结构        
	LPBITMAPINFOHEADER lpbi;						//位图信息头结构      
    HANDLE          fh, hDib, hPal,hOldPal=NULL;	//指向位图信息头结构,定义文件,分配内存句柄,调色板句柄 
   
   //计算位图文件每个像素所占字节数 
   hDC = CreateDC("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; 
   //计算调色板大小 
   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)); 
   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; 
} 
 
//******************************************************************************** 
//* 名称:OnSavebmp 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:保存为位图 
//******************************************************************************** 
void CScreenSnapDlg::OnSavebmp()  
{ 
	if (m_hwndFoundWindow)								//如果已有选中窗口的话,则刷新它 
	{ 
		//打开保存对话框,获取保存文件名 
		CString	strFileName;	 
		CFileDialog dlg( FALSE,"bmp", "*.bmp", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "*.bmp||" ); 
		dlg.m_ofn.Flags|=OFN_FILEMUSTEXIST; 
		dlg.m_ofn.lpstrTitle="保存为位图"; 
		if( dlg.DoModal() == IDCANCEL ) 
			return ; 
		strFileName = dlg.GetPathName(); 
 
		//先隐藏窗体 
		if(IsWindowVisible())				 //窗体是否已隐藏 
		{ 
			ShowWindow(SW_HIDE);             //先隐藏窗体 
			WinAnimation(true);			     //窗体动画滑入到系统区中  
		} 
 
		//获取选中图像窗口的位图句柄 
		CDC dc; 
        HDC hdc = ::GetWindowDC(m_hwndFoundWindow); 
        dc.Attach(hdc); 
 
		CDC memDC; 
		memDC.CreateCompatibleDC(&dc); 
		 
		CBitmap bm; 
		CRect r; 
		 
		((CWnd *)CWnd::FromHandle(m_hwndFoundWindow))->GetWindowRect(&r); 
	 
		CSize sz(r.Width(), r.Height()); 
		bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy); 
		CBitmap * oldbm = memDC.SelectObject(&bm); 
		memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY); 
		 
		//保存为指定位图文件 
		if(SaveBitmapToFile((HBITMAP)bm.m_hObject,strFileName)) 
			m_Description.SetWindowText("位图保存成功!"); 
		else 
			m_Description.SetWindowText("位图保存失败!"); 
		 
		//恢复原始环境 
		memDC.SelectObject(oldbm); 
		bm.Detach();   
 
		//恢复窗体正常显示 
		if(!IsWindowVisible())				 //窗体是否已隐藏 
		{ 
			ShowWindow(SW_SHOW);              
			WinAnimation(false);			 //窗体动画从系统区中滑出  
		} 
 
	} 
	else 
	{ 
		MessageBox("没有找到选中图像,请在抓图后,按F3键完成抓图!"); 
		m_Description.SetWindowText("没有找到选中图像,请在抓图后,按F3键完成抓图!"); 
	} 
} 
 
//******************************************************************************** 
//* 名称:OnSaveBmp 
//* 作者:徐景周(jingzhou_xu@163.net) 
//* 功能:系统区菜单中保存位图操作 
//******************************************************************************** 
void CScreenSnapDlg::OnSaveBmp()  
{ 
	OnSavebmp();	 
}