用什么方法可以截取屏幕上指定区域的位图?

wbcnxa 2005-09-20 11:47:07
用什么方法可以截取屏幕上指定区域的位图?
...全文
298 点赞 收藏 5
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
xhzxlqt 2005-12-05
这是一个保存整个屏幕的,你可以改为保存一部分,代码是BCB下的:
Ddraw.cpp从SDK里找去
先要:

//初始化DirectDraw环境,并实现DirectDraw功能
InitDDraw(lpDD,lpDDSPrimary)


最后要:
FreeDDraw(lpDD,lpDDSPrimary);

保存的CPP
bool Is555=true;
inline unsigned char GetRed(WORD color)
{
if( Is555 )
return (color>>7) & 0xff;
else
return (color>>8) & 0xff;
}

inline unsigned char GetGreen(WORD color)
{
if( Is555 )
return (color>>2) & 0xff;
else
return (color>>3) & 0xff;
}
inline unsigned char GetBlue(WORD color)
{
return (color & 0x1f) << 3;
}


bool SaveToBitmapFile(LPDIRECTDRAWSURFACE lpSurface, char* filename)
{
WORD* lpBuffer; // 表面指针
int nPitch; // 表面跨距
int nWidth, nHeight; // 表面宽高

///////////////
/////////////

HWND hwnd=GetActiveWindow();
// 打开文件s
FILE* fp;
if( (fp=fopen(filename, "wb")) != NULL )
{
// 锁定表面
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
ShowWindow(hwnd,SW_MINIMIZE);
HRESULT ddrval = lpSurface->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
// ddsd.lPitch//每行数据总字节数
// ShowMessage("RM:"+AnsiString(ddsd.ddpfPixelFormat.dwRBitMask)+
// "GM:"+AnsiString(ddsd.ddpfPixelFormat.dwGBitMask)
// +"BM:"+AnsiString(ddsd.ddpfPixelFormat.dwBBitMask)
// +"lPitch:"+AnsiString(ddsd.lPitch));
if( ddrval == DD_OK )
{
lpBuffer = (WORD *)ddsd.lpSurface;
nWidth = ddsd.dwWidth;
nHeight = ddsd.dwHeight;
nPitch = ddsd.lPitch >> 1; //lPitch以Byte为单位,GraphPitch以WORD为单位。所以GraphPitch = lPitch / 2;
if(ddsd.ddpfPixelFormat.dwBBitMask==31)Is555=false;
}

// 保存文件头
fputc(0x42,fp);
fputc(0x4d,fp);
fputc( (nWidth * nHeight * 3 + 0x36)&0xff,fp);
fputc(((nWidth * nHeight * 3 + 0x36)>>8)&0xff,fp);
fputc(((nWidth * nHeight * 3 + 0x36)>>16)&0xff,fp);
fputc(((nWidth * nHeight * 3 + 0x36)>>24)&0xff,fp);
fputc(0,fp);fputc(0,fp);
fputc(0,fp);fputc(0,fp);
fputc(0x36,fp);
fputc(0,fp);fputc(0,fp);fputc(0,fp);

// 保存文件信息
BITMAPINFOHEADER Header;
Header.biSize = sizeof(BITMAPINFOHEADER);// 结构的大小
Header.biWidth = nWidth; // 宽
Header.biHeight = nHeight;// 高
Header.biPlanes = 1; // 固定
Header.biBitCount = 24; // 颜色数
Header.biCompression = BI_RGB; // 是否压缩
Header.biSizeImage = nWidth * nHeight * 3;// 图片的大小
Header.biXPelsPerMeter = 0;
Header.biYPelsPerMeter = 0;
Header.biClrUsed = 0;
Header.biClrImportant = 0;
fwrite(&Header, Header.biSize, 1, fp);
// 写入具体内容(从下向上存放)
fseek(fp, 0x36, SEEK_SET);
switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
{
case 8:
{
BYTE *tem=(BYTE *)ddsd.lpSurface;
PALETTEENTRY entry[256];
HDC hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL);
::GetSystemPaletteEntries(hScrDC,0,256,entry);
for(int y=(int)nHeight-1;y>=0;y--)
{
for(int x=0;x<(int)nWidth;x++)
{
fputc(entry[tem[x+ddsd.lPitch*y]].peBlue,fp);
fputc(entry[tem[x+ddsd.lPitch*y]].peGreen,fp);
fputc(entry[tem[x+ddsd.lPitch*y]].peRed,fp);
}
}
DeleteDC(hScrDC);
break;
}
case 16:
{ WORD word;
lpBuffer += nWidth * (nHeight - 1);
for(int i=0; i<nHeight; i++)
{
for(int j=0; j<nWidth; j++)
{
word = *lpBuffer;
fputc( GetBlue( word ), fp); // 蓝
fputc( GetGreen( word ), fp); // 绿
fputc( GetRed( word ), fp); // 红

lpBuffer++;
}
lpBuffer -= nPitch*2; // 指针转到上一行的开始
}
break;
}
case 24:
// case 32:
{
BYTE *tem=(BYTE *)ddsd.lpSurface;
tem+=nWidth * (nHeight - 1)*3;
// ShowMessage(AnsiString(ddsd.lPitch));
for(int y=(int)nHeight-1;y>=0;y--)
{
for(int x=0;x<(int)nWidth;x++)
{
fputc(*tem++,fp);
fputc(*tem++,fp);
fputc(*tem++,fp);
}
tem-=ddsd.lPitch*2;
}
break;
}
case 32:
{
BYTE *tem=(BYTE *)ddsd.lpSurface;
tem+=nWidth * (nHeight - 1)*4;
// ShowMessage(AnsiString(ddsd.lPitch));
for(int y=(int)nHeight-1;y>=0;y--)
{
for(int x=0;x<(int)nWidth;x++)
{

fputc(*tem++,fp);
fputc(*tem++,fp);
fputc(*tem++,fp);
tem++;
}
tem-=ddsd.lPitch*2;
}
break;
}
}//end switch

fclose(fp);

// 解锁表面
ddrval = lpSurface->Unlock( NULL );
PostMessage(hwnd,WM_QUIT,0,0);
return true;
}

return false;
}
回复
wbcnxa 2005-09-21
这些方法都是copy特定窗口位图。我想要拷贝屏幕上任意指定区域的位图,其实就是屏幕抓图。
回复
pomelowu 2005-09-20
获得屏幕DC,然后BitBlt。仔细看BitBlt的参数就知道了。
回复
bobob 2005-09-20
HBITMAP CopyDCToBitmap(HDC hScrDC, LPRECT lpRect)
{
HDC hMemDC; // 屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap; // 位图句柄
int nX, nY, nX2, nY2; // 选定区域坐标
int nWidth, nHeight; // 位图宽度和高度

if (IsRectEmpty(lpRect)) // 确保选定区域不为空矩形
return NULL;

// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
nWidth = nX2 - nX;
nHeight = nY2 - nY;

hMemDC = CreateCompatibleDC(hScrDC);//为屏幕设备描述表创建兼容的内存设备描述表

// 创建一个与屏幕设备描述表兼容的位图
float factor = 1.0f;
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
while(!hBitmap)
{
factor -= 0.05f;
hBitmap = CreateCompatibleBitmap(hScrDC, (int)(nWidth*factor), (int)(nHeight*factor));
}
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
StretchBlt(hMemDC,0,0,nWidth,nHeight,hScrDC,nX,nY,nWidth,nHeight,SRCCOPY);
//BitBlt(hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY);
//得到屏幕位图的句柄

hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//清除

// DeleteDC(hScrDC);
DeleteDC(hMemDC);
DeleteObject(hOldBitmap);
// 返回位图句柄
return hBitmap;
}
回复
xhzxlqt 2005-09-20
Direct也可
回复
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2005-09-20 11:47
社区公告
暂无公告