请教一下,下面的方法,截屏,然后生成缩略图是正确的: IntPtr handle = ImageHelper.GDI32.GetDesktopWindow();//获得屏幕的HWND
IntPtr sourceDC = User32.GetWindowDC(handle);//获得屏幕DC
而换成图片
//Graphics sourceGraphics = Graphics.FromImage(bmp);//使用源图创建画板
//IntPtr sourceDC = sourceGraphics.GetHdc(); //得到画板的DC则会得到全黑的缩略图,实在找不到错在哪里,请指教
---------------------------------------------------------
/// <summary>
/// 生成缩略图
/// </summary>
/// <param name="bmp">源图</param>
/// <param name="widthDest">缩略图宽度</param>
/// <param name="heightDest">缩略图高度</param>
/// <returns></returns>
public static Bitmap MakeThubnail(Bitmap bmp, int widthDest, int heightDest)
{
try
{
//Graphics sourceGraphics = Graphics.FromImage(bmp);//使用源图创建画板
//IntPtr sourceDC = sourceGraphics.GetHdc(); //得到画板的DC IntPtr handle = ImageHelper.GDI32.GetDesktopWindow();//获得屏幕的HWND
IntPtr sourceDC = User32.GetWindowDC(handle);//获得屏幕DC // create a device context we can copy to
IntPtr destCDC = GDI32.CreateCompatibleDC(sourceDC); //建立与sourceDC兼容的DC,用于输出
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(sourceDC, widthDest, heightDest);//再建立一个与hdcSrc兼容的位图(双缓冲?)
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(destCDC, hBitmap); //将DC与位图关联 GDI32.SetStretchBltMode(destCDC, GDI32.STRETCH_HALFTONE);
GDI32.POINTAPI point;
GDI32.SetBrushOrgEx(destCDC, 0, 0, out point); // bitblt over
GDI32.StretchBlt(destCDC, 0, 0, widthDest, heightDest, sourceDC, 0, 0, bmp.Width,bmp.Height, GDI32.SRCCOPY); //复制
// restore selection
GDI32.SelectObject(destCDC, hOld); //取消与位图的关联
// clean up
GDI32.DeleteDC(destCDC);
//User32.ReleaseDC(handle, sourceDC);
//sourceGraphics.ReleaseHdc();
// get a .NET image object for it
Bitmap img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap); return img;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
IntPtr sourceDC = User32.GetWindowDC(handle);//获得屏幕DC
而换成图片
//Graphics sourceGraphics = Graphics.FromImage(bmp);//使用源图创建画板
//IntPtr sourceDC = sourceGraphics.GetHdc(); //得到画板的DC则会得到全黑的缩略图,实在找不到错在哪里,请指教
---------------------------------------------------------
/// <summary>
/// 生成缩略图
/// </summary>
/// <param name="bmp">源图</param>
/// <param name="widthDest">缩略图宽度</param>
/// <param name="heightDest">缩略图高度</param>
/// <returns></returns>
public static Bitmap MakeThubnail(Bitmap bmp, int widthDest, int heightDest)
{
try
{
//Graphics sourceGraphics = Graphics.FromImage(bmp);//使用源图创建画板
//IntPtr sourceDC = sourceGraphics.GetHdc(); //得到画板的DC IntPtr handle = ImageHelper.GDI32.GetDesktopWindow();//获得屏幕的HWND
IntPtr sourceDC = User32.GetWindowDC(handle);//获得屏幕DC // create a device context we can copy to
IntPtr destCDC = GDI32.CreateCompatibleDC(sourceDC); //建立与sourceDC兼容的DC,用于输出
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(sourceDC, widthDest, heightDest);//再建立一个与hdcSrc兼容的位图(双缓冲?)
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(destCDC, hBitmap); //将DC与位图关联 GDI32.SetStretchBltMode(destCDC, GDI32.STRETCH_HALFTONE);
GDI32.POINTAPI point;
GDI32.SetBrushOrgEx(destCDC, 0, 0, out point); // bitblt over
GDI32.StretchBlt(destCDC, 0, 0, widthDest, heightDest, sourceDC, 0, 0, bmp.Width,bmp.Height, GDI32.SRCCOPY); //复制
// restore selection
GDI32.SelectObject(destCDC, hOld); //取消与位图的关联
// clean up
GDI32.DeleteDC(destCDC);
//User32.ReleaseDC(handle, sourceDC);
//sourceGraphics.ReleaseHdc();
// get a .NET image object for it
Bitmap img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap); return img;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
解决方案 »
- 要学习.net网站开发。求引导
- 求一个MDI窗体 简单的传值小程序
- 请教Delphi中如何实现像.NET DatSET一样的离线操作
- 如何将splitContainer中的panel设置为上下放置的(在属性面板中设置,非代码实现)
- TextBox自动显示时间?
- 送分了,贴了一天没人答
- 请教一个关于类的简单问题
- vb调用vs2005生成的dll(急)
- c#新手疑问——什么是事件访问器?下面代码作用是什么?--再线等待
- [★★★]我用 datagridView 或 GridView 绑定了一个, 实现IList接口的类,自动生成的列,排序有问题
- gdi+画图一点问题
- C# winform 触发点动按钮,如何解决先进行滑动然后再按住才能触发?
DWM可以帮助动画窗口,避免不必要的窗口重绘等等。但是,DWM也影响了StretchBlt和BitBlt的作用。
由于多了DWM一层,程序对HDC的操作,不总是反映到屏幕上,对HDC的拷贝,也不一定是拷贝到你眼睛看到的部分。我的建议是避免本地GDI操作,特别是当缩略图在DotNet中很容易做:
public static Bitmap MakeThumbnail(Bitmap bmp, int widthDest, int heightDest)
{
var bmpDest = new Bitmap(widthDest, heightDest);
using (var g = Graphics.FromImage(bmpDest))
{
g.DrawImage(bmp, 0, 0, widthDest, heightDest);
}
return bmpDest;
}
也试过ImageMagick,同样效率低。
因为一次载入数百张图
Bitmap img = Image.FromHbitmap(hBitmap);
GDI32.DeleteObject(hBitmap);
return img;原因是Image.FromHbitmap可能不会进行数据拷贝,一旦GDI32.DeleteObject把img的数据销毁了,返回的img就可能不正常工作。
你可以试试在GDI32.DeleteObject(hBitmap);前保存img,看是否数据存在。Bitmap img = Image.FromHbitmap(hBitmap);
img.Save("调试.bmp"); // 测试这点是否数据存在
img = img.Clone() as Bitmap; // 尝试拷贝到副本,返回副本
GDI32.DeleteObject(hBitmap);
return img;这里讨论全黑的原因,并不是鼓励你用本地GDI调用。
而 g.DrawImage 的效率还算过得去。 真正在处理批量图片的时候, 本身就会非常耗时。
解决办法是尽可能避免,并采用后台线程去做,而不是硬着头皮一张张去处理。