// CatchDlg.cpp : implementation file // #include "stdafx.h" #include "ScreenShots.h" #include "CatchDlg.h" #include "ScreenShotsDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCatchDlg dialog CCatchDlg::CCatchDlg(CWnd* pParent /*=NULL*/) : CDialog(CCatchDlg::IDD, pParent) { //{{AFX_DATA_INIT(CCatchDlg) //}}AFX_DATA_INIT m_scRect.left = 0; m_scRect.top = 0; m_scRect.right = 0; m_scRect.bottom = 0; m_startPt = 0; m_bDraw = FALSE; m_bFirstDraw = FALSE; m_bShowMsg = FALSE; m_strOld = ""; m_scRect.right = GetSystemMetrics(SM_CXSCREEN); m_scRect.bottom = GetSystemMetrics(SM_CYSCREEN); m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(m_scRect)); m_rectTracker.m_nStyle=CRectTracker::resizeInside|CRectTracker::solidLine; m_rectTracker.m_rect.SetRect(-1,-1,-1,-1); } void CCatchDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCatchDlg) DDX_Control(pDX, IDC_EDIT1, m_eTip); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CCatchDlg, CDialog) //{{AFX_MSG_MAP(CCatchDlg) ON_WM_CANCELMODE() ON_WM_ERASEBKGND() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_PAINT() ON_WM_RBUTTONDOWN() ON_WM_SETCURSOR() ON_WM_RBUTTONDBLCLK() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCatchDlg message handlers BOOL CCatchDlg::OnInitDialog() { CDialog::OnInitDialog(); //把对化框设置成全屏顶层窗口 int m_xScreen = GetSystemMetrics(SM_CXSCREEN); int m_yScreen = GetSystemMetrics(SM_CYSCREEN); ::SetWindowPos(this->m_hWnd,HWND_TOPMOST,0,0,m_xScreen,m_yScreen,SWP_SHOWWINDOW); //移动操作提示窗口 CRect rect; m_eTip.GetWindowRect(&rect); m_eTip.MoveWindow(10,10,rect.Width(),rect.Height()); //显示操作提示窗口文字 SetTip(); //捕获按键消息窗口,将对话框的句柄传递到CCatchScreenApp中 ((CScreenShotsApp *)AfxGetApp())->m_hwndDlg=m_hWnd; return TRUE; // return TRUE unless you set the focus to a control } void CCatchDlg::OnCancelMode() { // TODO: Add extra initialization here CDialog::OnCancelMode(); } void CCatchDlg::mySetWindowPos(const CWnd *pWnd, CRect rect, unsigned int style) { SetWindowPos(&wndTopMost, rect.left,rect.top, rect.Width (),rect.Height(), SWP_SHOWWINDOW); } void CCatchDlg::SetMessage(CRect dRect) { //截取矩形大小信息离鼠标间隔 const int space=3; //设置字体颜色大小 CClientDC dc(this); CPoint pt; CPen pen(PS_SOLID,1,RGB(147,147,147)); dc.SetTextColor(RGB(147,147,147)); CFont font; font.CreatePointFont(90,"宋体"); dc.SelectObject(&font); //得到字体宽度和高度 GetCursorPos(&pt); dc.SetBkMode(TRANSPARENT); TEXTMETRIC tm; int charHeight; CSize size; int lineLength; dc.GetTextMetrics(&tm); charHeight = tm.tmHeight+tm.tmExternalLeading; size=dc.GetTextExtent("顶点位置 ",strlen("顶点位置 ")); lineLength=size.cx; //初始化矩形, 以保证写下六行文字 CRect rect(pt.x+space,pt.y-charHeight*6-space,pt.x+lineLength+space,pt.y-space); int x = GetDeviceCaps(dc, HORZRES); int y = GetDeviceCaps(dc, VERTRES); //创建临时矩形 CRect rectTemp; //当矩形到达桌面边缘时调整方向和大小 if((pt.x+rect.Width())>=x) { //桌面上方显示不下矩形 rectTemp=rect; rectTemp.left=rect.left-rect.Width()-space*2; rectTemp.right=rect.right-rect.Width()-space*2;; rect=rectTemp; } if((pt.y-rect.Height())<=0) { //桌面右方显示不下矩形 rectTemp=rect; rectTemp.top=rect.top+rect.Height()+space*2;; rectTemp.bottom=rect.bottom+rect.Height()+space*2;; rect=rectTemp; } //创建空画刷画矩形 dc.SelectObject((HBRUSH)GetStockObject(NULL_BRUSH)); dc.Rectangle(rect); rect.top+=2; //在矩形中显示文字 CString string(" 顶点位置 "); dc.TextOut(rect.left,rect.top,string); string.Format(" (%d,%d)",dRect.left,dRect.top); dc.TextOut(rect.left,rect.top+charHeight,string); string=" 矩形大小 "; dc.TextOut(rect.left,rect.top+charHeight*2,string); string.Format(" (%d,%d)",dRect.Width(),dRect.Height()); dc.TextOut(rect.left,rect.top+charHeight*3,string); string=" 光标坐标 "; dc.TextOut(rect.left,rect.top+charHeight*4,string); string.Format(" (%d,%d)",pt.x,pt.y); dc.TextOut(rect.left,rect.top+charHeight*5,string); } void CCatchDlg::SetTip() { CPoint pt; GetCursorPos(&pt); //pt.x+=3; //pt.y+=3; //当到当前R,G,B,各像素值 COLORREF color; CClientDC dc(this); color=dc.GetPixel(pt); BYTE rValue,gValue,bValue; rValue=GetRValue(color); gValue=GetGValue(color); bValue=GetGValue(color); //按格式排放字符串 CString string; CString strTemp; string.Format("\r\n\r\n\r\n ·当前像素RGB (%d,%d,%d)\r\n",rValue,gValue,bValue); if(!m_bDraw&&!m_bFirstDraw) { strTemp="\r\n ·按下鼠标左键不放选择截取\r\n 范围\r\n\r\n ·按ESC键或鼠标右键双击退出"; } else if(m_bDraw&&m_bFirstDraw) { strTemp="\r\n ·松开鼠标左键确定截取范围\r\n\r\n ·按ESC键退出"; } else if(m_bFirstDraw) { strTemp="\r\n ·用鼠标左键调整截取范围的\r\n 大小和位置\r\n\r\n·截取范围内双击鼠标左键保存\r\n 图像,结束操作\r\n\r\n·点击鼠标右键重新选择"; } string+=strTemp; //显示到编缉框中,操作提示窗口 m_eTip.SetWindowText(string); } BOOL CCatchDlg::OnEraseBkgnd(CDC* pDC) { //用整个桌面填充全屏对话框背景 CDC dcCompatible; dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect; GetClientRect(&rect); pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); return TRUE; } HBITMAP CCatchDlg::CopyScreenToBitmap(CRect rect, bool bSave) { GetSystemCursor(); HDC hScrDC, hMemDC; // 屏幕和内存设备描述表 HBITMAP hBitmap = NULL; HBITMAP hOldBitmap = NULL; // 位图句柄 int nX, nY, nX2, nY2; // 选定区域坐标 int nWidth, nHeight; //为屏幕创建设备描述表 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); //为屏幕设备描述表创建兼容的内存设备描述表 hMemDC = CreateCompatibleDC(hScrDC); // 确保选定区域不为空矩形 if (IsRectEmpty(rect)) return NULL; // 获得选定区域坐标 nX = rect.left; nY = rect.top; nX2 = rect.right; nY2 = rect.bottom; //确保选定区域是可见的 if (nX < 0) nX = 0; if (nY < 0) nY = 0; if (nX2 > m_scRect.Width()) nX2 = m_scRect.Width(); if (nY2 > m_scRect.Height()) nY2 = m_scRect.Height(); nWidth =abs( nX2 - nX); nHeight =abs( nY2 - nY); // 创建一个与屏幕设备描述表兼容的位图 hBitmap = CreateCompatibleBitmap (hScrDC, nWidth, nHeight); // 把新位图选到内存设备描述表中 hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); // 把屏幕设备描述表拷贝到内存设备描述表中 if(bSave) { CDC dcCompatible; dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC)); dcCompatible.SelectObject(m_pBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, dcCompatible, nX, nY, SRCCOPY); } else { BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); } ICONINFO IconInfo; POINT ptCursor; ::GetCursorPos(&ptCursor); if (GetIconInfo(m_capCursor, &IconInfo)) { ptCursor.x -= ((int) IconInfo.xHotspot); ptCursor.y -= ((int) IconInfo.yHotspot); if (IconInfo.hbmMask != NULL) DeleteObject(IconInfo.hbmMask); if (IconInfo.hbmColor != NULL) DeleteObject(IconInfo.hbmColor); } DrawIconEx( hMemDC, // handle to device context ptCursor.x, ptCursor.y, m_capCursor, // handle to icon to draw 0,0, // width of the icon 0, // index of frame in animated cursor NULL, // handle to background brush DI_NORMAL | DI_COMPAT // icon-drawing flags ); hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); //得到屏幕位图的句柄 //清除 DeleteDC(hScrDC); DeleteDC(hMemDC); // 返回位图句柄 if(bSave) { if (OpenClipboard()) { //清空剪贴板 EmptyClipboard(); //把屏幕内容粘贴到剪贴板上, //hBitmap 为刚才的屏幕位图句柄 SetClipboardData(CF_BITMAP, hBitmap); //关闭剪贴板 CloseClipboard(); } } return hBitmap; } void CCatchDlg::OnLButtonDown(UINT nFlags, CPoint point) { int nHitTest; nHitTest=m_rectTracker.HitTest(point); m_bShowMsg=TRUE; UpdateWindow(); //判断击中位置 if(nHitTest<0) { if(!m_bFirstDraw) { m_startPt=point; m_bDraw=TRUE; m_bFirstDraw=TRUE; SetTip(); UpdateWindow(); } } else { if(m_bFirstDraw) { m_rectTracker.Track(this,point,TRUE); SendMessage(WM_LBUTTONUP,NULL,NULL); UpdateWindow(); } } CDialog::OnLButtonDown(nFlags, point); } void CCatchDlg::OnLButtonUp(UINT nFlags, CPoint point) { m_bShowMsg=FALSE; m_bDraw=FALSE; SetTip(); UpdateWindow(); CDialog::OnLButtonUp(nFlags, point); } void CCatchDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_bDraw) { m_rectTracker.m_rect.SetRect(m_startPt.x+1,m_startPt.y+1,point.x,point.y); m_bFirstDraw=TRUE; UpdateWindow(); } modifyColor(); CDialog::OnMouseMove(nFlags, point); } void CCatchDlg::OnLButtonDblClk(UINT nFlags, CPoint point) { int nHitTest; m_rectTracker.m_rect.NormalizeRect(); nHitTest=m_rectTracker.HitTest(point); if(nHitTest==8) { CopyScreenToBitmap(m_rectTracker.m_rect,TRUE); PostQuitMessage(0); } CDialog::OnLButtonDblClk(nFlags, point); } void CCatchDlg::OnRButtonDown(UINT nFlags, CPoint point) { //如果已经截取矩则清除截取矩形 m_bFirstDraw=FALSE; m_rectTracker.m_rect.SetRect(-1,-1,-1,-1); SetTip(); UpdateWindow(); CDialog::OnRButtonDown(nFlags, point); } void CCatchDlg::OnRButtonDblClk(UINT nFlags, CPoint point) { //关闭程序 PostQuitMessage(0); CDialog::OnRButtonDblClk(nFlags, point); } void CCatchDlg::UpdateWindow() { //获取当全屏对话框窗口大小 CRect rect1; GetWindowRect(rect1); //获取编辑框窗口大小 CRect rect2; m_eTip.GetWindowRect(rect2); CRgn rgn,rgn1,rgn2; rgn.CreateRectRgn(0,0,50,50); rgn1.CreateRectRgnIndirect(rect1); rgn2.CreateRectRgnIndirect(rect2); //获取更新区域,就是除了编辑框窗口不更新 rgn.CombineRgn(&rgn1,&rgn2,RGN_DIFF); InvalidateRgn(&rgn); } void CCatchDlg::OnPaint() { CPaintDC dc(this); //显示截取矩形大小信息 if(m_bShowMsg&&m_bFirstDraw) { CRect rect; m_rectTracker.GetTrueRect(&rect); SetMessage(rect); } //画出像皮筋矩形 if(m_bFirstDraw) { m_rectTracker.Draw(&dc); } // Do not call CDialog::OnPaint() for painting messages } BOOL CCatchDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { //设置改变截取矩形大小时光标 if (pWnd == this && m_rectTracker.SetCursor(this, nHitTest)) { return TRUE; } else { //设置彩色光标 SetCursor(AfxGetApp()->LoadCursor(IDC_COLOR)); return TRUE; } return CDialog::OnSetCursor(pWnd, nHitTest, message); } void CCatchDlg::modifyColor() { //保存旧的RGB值字符串 CPoint pt; GetCursorPos(&pt); //当到当前R,G,B,各像素值 COLORREF color; CClientDC dc(this); color=dc.GetPixel(pt); BYTE rValue,gValue,bValue; rValue=GetRValue(color); gValue=GetGValue(color); bValue=GetBValue(color); //按格式排放字符串 CString string; string.Format("(%d,%d,%d)",rValue,gValue,bValue); //如果当前颜色没变则不刷新RGB值,以免窗口有更多闪烁 if(m_strOld!=string) { //得到RGB文本那一行的文本长度 int LineLength=m_eTip.LineLength(6); //复选RGB值文本,也就是(255,255,255)形式 m_eTip.SetSel(20,LineLength+6); //替换RGB内容 m_eTip.ReplaceSel(string); } m_strOld=string; } void CCatchDlg::GetSystemCursor() { static HWND hTemp=0; DWORD dwProcessID=0; HICON hSavedCursor; POINT ptCursor; ::GetCursorPos(&ptCursor); HWND hwnd=::WindowFromPoint(ptCursor); if(hTemp!=hwnd) { DWORD dwThreadID=::GetWindowThreadProcessId(hwnd,&dwProcessID); DWORD dwCurThreadID=::GetCurrentThreadId(); if(dwCurThreadID != dwThreadID) { ::AttachThreadInput(dwCurThreadID,dwThreadID,true); m_capCursor =::GetCursor(); AttachThreadInput(dwCurThreadID, dwThreadID, FALSE); } else { m_capCursor =GetCursor(); } } }