标题:抓屏后保存图片失败,我又错在哪里了啊
只看楼主
yaoguai2005
Rank: 1
等 级:新手上路
帖 子:168
专家分:0
注 册:2005-9-11
 问题点数:0 回复次数:9 
抓屏后保存图片失败,我又错在哪里了啊

截取屏幕后,我想保存到C盘下,可到C盘看了一下位图,显示绘图失败,
请大家给指点一下把

#include <windows.h>
#define ID_TIMER 1

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

char szClassName[ ] = "WindowsApp";
void DrawScreen(HDC hdc);
int WINAPI
WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)

{
HWND hwnd;
MSG messages;
WNDCLASSEX wincl;

wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);

wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;

wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

if (!RegisterClassEx (&wincl))
return 0;

hwnd = CreateWindowEx (
0,
szClassName,
"Windows App",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
544,
375,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);

ShowWindow (hwnd, nFunsterStil);

while (GetMessage (&messages, NULL, 0, 0))
{

TranslateMessage(&messages);

DispatchMessage(&messages);
}

return messages.wParam;
}

LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
DrawScreen(hdc);
EndPaint(hwnd, &ps);
break;
}

case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}


void DrawScreen(HDC hdc)
{
BITMAPINFO bi;
void *pBits=NULL;
int nWidth=GetSystemMetrics(SM_CXSCREEN);
int nHeight=GetSystemMetrics(SM_CYSCREEN);
ZeroMemory(&bi,sizeof(bi));
bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
bi.bmiHeader.biHeight=nHeight;
bi.bmiHeader.biWidth=nWidth;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=24;
bi.bmiHeader.biCompression=BI_RGB;
bi.bmiHeader.biSizeImage=3*nWidth*nHeight;

HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hCaptureBitmap =CreateCompatibleBitmap(hDesktopDC,
nWidth, nHeight);
HGDIOBJ oldobj=SelectObject(hCaptureDC,hCaptureBitmap);

BitBlt(hdc,0,0,nWidth,nHeight,hDesktopDC,0,0,SRCCOPY);
HANDLE hFile=CreateFile("c:\\11.bmp",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dwRet=0;
BITMAPFILEHEADER bmfHeader;
ZeroMemory(&bmfHeader,sizeof(bmfHeader));
bmfHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bmfHeader.bfSize=bi.bmiHeader.biSizeImage+bmfHeader.bfOffBits;
bmfHeader.bfType='MB';

WriteFile(hFile,&bmfHeader,sizeof(bmfHeader),&dwRet,NULL);
WriteFile(hFile,&bi.bmiHeader,sizeof(bi.bmiHeader),&dwRet,NULL);
WriteFile(hFile,pBits,bi.bmiHeader.biSizeImage,&dwRet,NULL);
CloseHandle(hFile);
}

SelectObject(hCaptureDC,oldobj);
DeleteDC(hCaptureDC);
}

[此贴子已经被作者于2006-4-19 14:45:28编辑过]

搜索更多相关主题的帖子: windows int 保存 HINSTANCE HWND 
2006-04-19 14:38
踏魔狼
Rank: 6Rank: 6
等 级:贵宾
威 望:24
帖 子:1322
专家分:33
注 册:2005-9-22
得分:0 

我这里有几个函数,是你想要的功能。我没有分析过,不过应该不难。
BOOL WriteWindowToDIB( LPTSTR szFile, CWnd *pWnd )
{
CBitmap bitmap;
CWindowDC dc(pWnd);
CDC memDC;
CRect rect;

memDC.CreateCompatibleDC(&dc);

pWnd->GetWindowRect(rect);

bitmap.CreateCompatibleBitmap(&dc, rect.Width(),rect.Height() );

CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, rect.Width(),rect.Height(), &dc, 0, 0, SRCCOPY);

// Create logical palette if device support a palette
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 =
GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );

// Create the palette
pal.CreatePalette( pLP );

delete[] pLP;
}

memDC.SelectObject(pOldBitmap);

// Convert the bitmap to a DIB
HANDLE hDIB = DDBToDIB( bitmap, BI_RGB, &pal );

if( hDIB == NULL )
return FALSE;

// Write it to file
WriteDIB( szFile, hDIB );

// Free the memory allocated by DDBToDIB for the DIB
GlobalFree( hDIB );
return TRUE;
}

HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression,CPalette &pal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;

CWindowDC dc( this );

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;
}

BOOL WriteDIB( LPTSTR szFile, HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;

if (!hDIB)
return FALSE;

CFile file;
if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
return FALSE;

lpbi = (LPBITMAPINFOHEADER)hDIB;

int nColors = 1 << lpbi->biBitCount;

// Fill in the fields of the file header
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof( hdr ) + lpbi->biSize +
nColors * sizeof(RGBQUAD));

// Write the file header
file.Write( &hdr, sizeof(hdr) );

// Write the DIB header and the bits
file.Write( lpbi, GlobalSize(hDIB) );

return TRUE;
}


=×&D o I p R e E n C g T l X&×=
2006-04-19 17:38
yaoguai2005
Rank: 1
等 级:新手上路
帖 子:168
专家分:0
注 册:2005-9-11
得分:0 
是C++的语句,我暂时只会C哦,
我在看呢,
对我来说,还是很有难度的

2006-04-19 18:08
踏魔狼
Rank: 6Rank: 6
等 级:贵宾
威 望:24
帖 子:1322
专家分:33
注 册:2005-9-22
得分:0 
实在不行我帮你弄。我有的是时间。

=×&D o I p R e E n C g T l X&×=
2006-04-19 18:37
yaoguai2005
Rank: 1
等 级:新手上路
帖 子:168
专家分:0
注 册:2005-9-11
得分:0 
天呀,大好人啊,
我就是想抓屏,然后保存到C盘就可以了,
下面这个程序好象比较简单点
我在看呢,你要是能帮我做出来
我简直要感动死了
为了这个题,我研究20天了,
从抓屏幕开始,还是你指点下,我才明白的。
书上和网上也没有什么例题,
VB的倒是有,可是我喜欢C啊

hbitmap copyscreentobitmap(lprect lprect)
//lprect 代表选定区域
{
hdc hscrdc, hmemdc;
// 屏幕和内存设备描述表
hbitmap hbitmap, holdbitmap;
// 位图句柄
int nx, ny, nx2, ny2;
// 选定区域坐标
int nwidth, nheight;
// 位图宽度和高度
int xscrn, yscrn;
// 屏幕分辨率

// 确保选定区域不为空矩形
if (isrectempty(lprect))
return null;
//为屏幕创建设备描述表
hscrdc = createdc("display", null, null, null);
//为屏幕设备描述表创建兼容的内存设备描述表
hmemdc = createcompatibledc(hscrdc);
// 获得选定区域坐标
nx = lprect- >left;
ny = lprect- >top;
nx2 = lprect- >right;
ny2 = lprect- >bottom;
// 获得屏幕分辨率
xscrn = getdevicecaps(hscrdc, horzres);
yscrn = getdevicecaps(hscrdc, vertres);
//确保选定区域是可见的
if (nx 〈0)
nx = 0;
if (ny 〈 0)
ny = 0;
if (nx2 > xscrn)
nx2 = xscrn;
if (ny2 > yscrn)
ny2 = yscrn;
nwidth = nx2 - nx;
nheight = ny2 - ny;
// 创建一个与屏幕设备描述表兼容的位图
hbitmap = createcompatiblebitmap
(hscrdc, nwidth, nheight);
// 把新位图选到内存设备描述表中
holdbitmap = selectobject(hmemdc, hbitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
bitblt(hmemdc, 0, 0, nwidth, nheight,
hscrdc, nx, ny, srccopy);
//得到屏幕位图的句柄
hbitmap = selectobject(hmemdc, holdbitmap);
//清除
deletedc(hscrdc);
deletedc(hmemdc);
// 返回位图句柄
return hbitmap;
}

得到屏幕位图句柄以后,我们
可以把屏幕内容粘贴到剪贴板上.
if (openclipboard(hwnd))
//hwnd为程序窗口句柄
{
//清空剪贴板
emptyclipboard();
//把屏幕内容粘贴到剪贴板上,
hbitmap 为刚才的屏幕位图句柄
setclipboarddata(cf_bitmap, hbitmap);
//关闭剪贴板
closeclipboard();
}
我们也可以把屏幕内容以位图格式存到磁盘文件上.

int savebitmaptofile(hbitmap hbitmap ,
lpstr lpfilename) //hbitmap 为刚才的屏幕位图句柄
{ //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, hpal, false);
realizepalette(hdc);
}
// 获取该调色板下新的像素值
getdibits(hdc, hbitmap, 0, (uint) bitmap.bmheight,
(lpstr)lpbi + sizeof(bitmapinfoheader)
+dwpalettesize,
(bitmapinfoheader *)
lpbi, dib_rgb_colors);
//恢复调色板
if (holdpal)
{
selectpalette(hdc, 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);
}


2006-04-19 19:07
踏魔狼
Rank: 6Rank: 6
等 级:贵宾
威 望:24
帖 子:1322
专家分:33
注 册:2005-9-22
得分:0 
终于完成了,用了3个小时呀!。
打开程序的菜单file,有一个抓图项,选中它,程序就会最小化,这时你就可以抓图了。
按左键保存图片,图片保存在C盘。
iWGEVRwl.rar (741.91 KB) 抓屏后保存图片失败,我又错在哪里了啊



=×&D o I p R e E n C g T l X&×=
2006-04-19 23:28
yaoguai2005
Rank: 1
等 级:新手上路
帖 子:168
专家分:0
注 册:2005-9-11
得分:0 
老大好厉害,
程序我已经下载了,现在正在看呢,
用谢字已经不能表达了
有 事给我发消息好了
来西安的话我请你吃饭
这2天我要好好的好你的程序
又能学到不少知识了


2006-04-20 08:08
wfpb
Rank: 6Rank: 6
等 级:贵宾
威 望:29
帖 子:2188
专家分:0
注 册:2006-4-2
得分:0 

好强,我现在都还没搞过桌面这种东西,因为还是菜鸟,不过我有信心有一天我也能会这些,多学学基础,花3个月把基础学扎实点再看别的吧


[glow=255,red,2]wfpb的部落格[/glow] 学习成为生活的重要组成部分!
2006-04-24 21:57
rayc
Rank: 1
等 级:新手上路
帖 子:40
专家分:0
注 册:2006-4-24
得分:0 
强人.
我都看不懂

2006-04-25 14:18
xjc
Rank: 1
等 级:新手上路
帖 子:95
专家分:0
注 册:2004-12-2
得分:0 

  一下子就把所有的原码给出来,还是让别人学不到东西啊,最好的是写思路,具体的过程让自己去实现不是更好吗?我认为这样子才能让人进步得更快。


时间是最宝贵的
2006-04-25 15:10



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-58562-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.385764 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved