获取指定窗口图像API
我们本科宿舍里几个人一直觉得大学学了这么久好像也没能作出些什么好玩的来,当年还曾经豪言约要改造宿舍,弄成学电子的人才会住的宿舍,比如在床边弄个控制器,有人敲门不想走过去开门时按个键就可以了,然而,这么久过去了,一直属于无所为的状态。
因为不想搞什么太专业的,但是又要好玩儿的。。。然后,大四开学两个多月后,我们宿舍所有人保研的保研,工作的工作,全部都找到归属了,人生一时间没什么可以奋斗的理由了,所以。。。沉迷到。。。。水果忍者。。。里面去了,整天切水果,一人一局决胜负,哈,那是真狂热哈。。之后某次吃饭的时候我突然想到,要不我们一起弄一个自动玩切水果游戏的机器吧,构想很简单,一个摄像头对着电脑屏幕(某骚闷男当年搞智能车时弄过摄像头模块),然后获取到数据之后用图像处理的方法(我搞DIP弄了比较长的时间了)得到要怎么切,最后用一个步进机什么的机械控制鼠标(5cm同学比较熟悉这个)来玩。。。这个只是个设想而已。。
后来我发现,额。。我只要获取了指定窗口的图像,干嘛还要用摄像头那种那么不清晰的方式,我纯软件就可以解决了。后来上网研究了一下,终于弄出了一个获取指定窗口图像的API了。存图像的变量是OPENCV里面的Iplimage。除了可以获取指定窗口外还可以获得整个屏幕的图像,这样就可以做截屏软件了!
/* 项目点击右键,依次选择:属性、配置属性、常规, 然后右边有个“项目默认值”,下面有个MFC的使用,选择“在共享 DLL 中使用 MFC” */ #ifdef _DEBUG #pragma comment ( lib, "cxcore200d.lib" ) #pragma comment ( lib, "cv200d.lib" ) #pragma comment ( lib, "highgui200d.lib" ) #else #pragma comment ( lib, "cxcore200.lib" ) #pragma comment ( lib, "cv200.lib" ) #pragma comment ( lib, "highgui200.lib" ) #endif #include <afxwin .h> #include "cv.h" #include "highgui.h" #include <time .h> #include <iostream> #include <stdlib .h> #include <conio .h> #include <afxwin .h> #include <winuser .h> using namespace std; #define WINDOW_NAME "window" #define OBJECT_WINDOW_NAME _T("Fruit Ninja") #define USE_FULL_SCREEN 1 #define SHOW_WINDOW 1 #define ABS(x) (x>0?x:(x*-1)) #define M_MAX(x,y) (x>y ? x : y) #define M_MIN(x,y) (x<y ? x : y) static void GetScreenShot(IplImage* &frame) { CDC *pDC;//屏幕DC #if USE_FULL_SCREEN == 0 pDC = CDC::FromHandle(::GetDC(::FindWindow( NULL,OBJECT_WINDOW_NAME))); #else pDC = CDC::FromHandle(::GetDC(NULL));//获取当前整个屏幕DC #endif static int Flag = 0; static int BitPerPixel; static int Width; static int Height; static CDC memDC;//内存DC static CBitmap memBitmap; CBitmap *oldmemBitmap;//建立和屏幕兼容的bitmap if(!Flag) { BitPerPixel = pDC->GetDeviceCaps(BITSPIXEL);//获得颜色模式 Width = pDC->GetDeviceCaps(HORZRES); Height = pDC->GetDeviceCaps(VERTRES); memDC.CreateCompatibleDC(pDC); memBitmap.CreateCompatibleBitmap(pDC, Width, Height); } oldmemBitmap = memDC.SelectObject(&memBitmap);//将memBitmap选入内存DC memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC BITMAP bmp; memBitmap.GetBitmap(&bmp);//获得位图信息 static BITMAPINFOHEADER bih = {0};//位图信息头 static byte* p; if(!Flag) { bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小 bih.biCompression = BI_RGB; bih.biHeight = bmp.bmHeight;//高度 bih.biPlanes = 1; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小 bih.biWidth = bmp.bmWidth;//宽度 p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据 Flag = 1; } GetDIBits(memDC.m_hDC, (HBITMAP) memBitmap.m_hObject, 0, Height, p, (LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据 if(!frame) { #if USE_FULL_SCREEN == 0 CRect rect; GetClientRect(::FindWindow( NULL,OBJECT_WINDOW_NAME),&rect); frame = cvCreateImage(cvSize(rect.Width(),rect.Height()),IPL_DEPTH_8U,3); #else frame = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight),IPL_DEPTH_8U,3); #endif } for(int i = 0;i < frame->height;i++) { for(int j = 0;j < frame->width;j++) { CV_IMAGE_ELEM(frame,uchar,i,3*j+2) = p[(bmp.bmHeight-i-1)*bmp.bmWidth*4+4*j+2]; CV_IMAGE_ELEM(frame,uchar,i,3*j+1) = p[(bmp.bmHeight-i-1)*bmp.bmWidth*4+4*j+1]; CV_IMAGE_ELEM(frame,uchar,i,3*j) = p[(bmp.bmHeight-i-1)*bmp.bmWidth*4+4*j]; } } } static CPoint GetCurPos() { CPoint point; CRect rect; GetClientRect(::FindWindow( NULL,OBJECT_WINDOW_NAME),&rect); GetCursorPos(&point); point.x -= rect.TopLeft().x; point.y -= rect.TopLeft().y; //cout< <point.x<<" "<<point.y<<endl; return point; } mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); GetCursorPos(&point); mouse_event(MOUSEEVENTF_MOVE,3*dire,0,0,0); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
【完】
本文内容遵从CC版权协议,转载请注明出自http://www.kylen314.com