对于问题一,我们知道,可以利用SetCapture函数能够追踪鼠标指针移动的特点,在移动鼠标的过程中,还可以根据鼠标指针所在的位置来判断当前窗口的句柄。我们可以利用一个平时程序员不经常使用的函数WindowFromPoint,这个函数能够找出鼠标指针当前位置所对应的窗口句柄。
创建基于对话框的工程,同时写入GDI+代码,形成一个GDI+工程,请看网站的GDI+文章,有关于GDI+代码的介绍。主要代码:
void CScreenCaptionDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
///如果用户按住鼠标左键不放,则开始抓取图片
if(nFlags==MK_LBUTTON)
{
//隐藏程序窗口,以免影响在抓取时的"视野"
ShowWindow(SW_HIDE);
//HCURSOR cur=LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));
SetCapture();
///获得鼠标指针所在窗口的句柄
ClientToScreen(&point);
hwndCapture=(HWND)::WindowFromPoint(point);
//取得屏幕的设备环境句柄,以便在屏幕的任何位置绘图
HDC hDC=::GetDC(NULL);
///建立一支红色的画笔
HPEN hPen=CreatePen(PS_INSIDEFRAME,6,RGB(255,0,0));
///将毁图模式设为R2_NOTXORPEN,在绘图时可以不破坏原有的背景
int nMode=SetROP2(hDC,R2_NOTXORPEN);
HPEN hpenOld=(HPEN)SelectObject(hDC,hPen);
//得到鼠标指针所在窗口的区域
::GetWindowRect(hwndCapture,&rectCapture);
//在鼠标指针所在处的窗口四周画一红色矩形,作为选定时的提示
POINT pt[5];
pt[0]=CPoint(rectCapture.left,rectCapture.top);
pt[1]=CPoint(rectCapture.right,rectCapture.top);
pt[2]=CPoint(rectCapture.right,rectCapture.bottom);
pt[3]=CPoint(rectCapture.left,rectCapture.bottom);
pt[4]=CPoint(rectCapture.left,rectCapture.top);
::Polyline(hDC,pt,5);
///延时后再重绘红色矩形,这样就不会破坏原有内容
Sleep(100);
::SelectObject(hDC,hpenOld);
::ReleaseDC(NULL,hDC);
}
CDialogEx::OnMouseMove(nFlags, point);
}
void CScreenCaptionDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//得到鼠标指针所在窗口的区域的宽,高
int nWidth=rectCapture.Width();
int nHeight=rectCapture.Height();
HDC hdcScreen,hMemDC;
HBITMAP hBitmap,hOldBitmap;
///建立一个屏幕设备环境句柄
hdcScreen=CreateDC(L"DISPLAY",NULL,NULL,NULL);
hMemDC=CreateCompatibleDC(hdcScreen);
//建立一个与屏幕设备环境句柄兼容,与鼠标指针所在窗口的区域等大的位图
hBitmap=CreateCompatibleBitmap(hdcScreen,nWidth,nHeight);
//把新位图选到内存设备描述表中
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
///把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,rectCapture.left,rectCapture.top,SRCCOPY);
//区域鼠标指针所在窗口的屏幕位图的句柄
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
DeleteDC(hdcScreen);
DeleteDC(hMemDC);
///返回位图句柄
//打开剪贴板,并将位图拷到剪贴板上
OpenClipboard();
EmptyClipboard();
SetClipboardData(CF_BITMAP,hBitmap);
CloseClipboard();
MessageBox(L"屏幕内容已经拷到剪贴板!");
ReleaseCapture();
ShowWindow(SW_NORMAL);
OPENFILENAME ofn;
TCHAR lpstrFileName[MAX_PATH]=L"屏幕截图文件.bmp";
ZeroMemory(&ofn,sizeof(ofn));
ofn.lStructSize=sizeof(OPENFILENAME);
ofn.hwndOwner=this->m_hWnd;
ofn.lpstrFilter=L"位图文件(.BMP)\0*.bmp";
ofn.nMaxFile=MAX_PATH;
ofn.lpstrFile=lpstrFileName;
ofn.lpstrTitle=L"将屏幕截图文件另存为?";
if(GetSaveFileName(&ofn))
{
CLSID pngClsid;
Bitmap bmp(hBitmap,NULL);
GetEncoderClsid(L"image/bmp",&pngClsid);
CString tmp(ofn.lpstrFile);
CStringW filename(tmp);
bmp.Save(filename,&pngClsid);
}
CDialogEx::OnLButtonUp(nFlags, point);
}
int CScreenCaptionDlg::GetEncoderClsid(WCHAR* format, CLSID* pClsid)
{
UINT num = 0;
UINT size = 0;
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1;
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
在头文件中:
HWND hwndCapture;
CRect rectCapture;
int GetEncoderClsid(WCHAR* format, CLSID* pClsid);
对于GetEncoderClsid,请看之前的文章,搜索作者阿郎找找就行了。由于特殊原因,我这里查不了,就看读者你的好学心了
代码实现: