请教一下,下面的方法,截屏,然后生成缩略图是正确的:                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;
        }

解决方案 »

  1.   

    Windows Vista后,界面效果提高明显,其中就有Descktop Windows Manager(DWM)的作用。
    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;
    }
      

  2.   

    谢谢,原来用的这个,效率太低了。
    也试过ImageMagick,同样效率低。
    因为一次载入数百张图
      

  3.   

    另外,如下代码可能有问题:
    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调用。
      

  4.   

    谢谢两位其实后来我明白了,对图片处理时 StretchBlt 根本就无法得到结果,因为它只支持对“显示在屏幕上”的东西进行处理。
    而 g.DrawImage 的效率还算过得去。 真正在处理批量图片的时候, 本身就会非常耗时。
    解决办法是尽可能避免,并采用后台线程去做,而不是硬着头皮一张张去处理。