C#使用StretchBlt在两个Bitmap间拷贝无绘制结果问题
问题:StretchBlt调用返回成功但内存位图无绘制内容
概述
尝试使用以下代码,通过StretchBlt将srcBmp位图的部分区域缩放拷贝到destBmp中——该方法返回1表示成功,但目标位图上没有任何绘制内容:
public static void StretchBltImage() { // create the source bitmap var srcBmp = new Bitmap(500, 500, PixelFormat.Format32bppArgb); var srcGfx = Graphics.FromImage(srcBmp); srcGfx.Clear(Color.Green); var srcHdc = srcGfx.GetHdc(); // create the target image var destBmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb); using var destGfx = Graphics.FromImage(destBmp); destGfx.Clear(Color.Gray); var destHdc = destGfx.GetHdc(); var res1 = SetStretchBltMode(destHdc, STRETCH_HALFTONE); var res2 = StretchBlt(destHdc, 75, 75, 50, 50, srcHdc, 0, 0, 100, 100, SRCCOPY); srcGfx.ReleaseHdc(srcHdc); destGfx.ReleaseHdc(destHdc); destBmp.Save(".\\image.png"); }
详细说明
正在编写一个C#应用程序,该程序已成功使用StretchBlt将桌面的一部分区域捕获(并缩小)到位图中,简化代码如下:
ConsoleApp1.csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0-windows</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> <ItemGroup> <PackageReference Include="System.Drawing.Common" Version="8.0.0-preview.5.23280.5" /> </ItemGroup> </Project>
Capture.cs
public static partial class Capture { [LibraryImport("user32")] internal static partial nint GetDesktopWindow(); [LibraryImport("user32")] internal static partial nint GetWindowDC(nint hWnd); [LibraryImport("gdi32")] internal static partial int SetStretchBltMode( nint hdc, int mode); [LibraryImport("gdi32")] internal static partial int StretchBlt(nint hdcDest, int xDest, int yDest, int wDest, int hDest, nint hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, int rop); private const int BLACKNESS = 0x00000042; private const int SRCCOPY = 0x00CC0020; private const int STRETCH_HALFTONE = 4; public static void StretchBltScreen() { // open the desktop handles var srcHwnd = GetDesktopWindow(); var srcHdc = GetWindowDC(srcHwnd); // create the target image var destBmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb); using var destGfx = Graphics.FromImage(destBmp); destGfx.Clear(Color.Gray); var destHdc = destGfx.GetHdc(); var res1 = SetStretchBltMode(destHdc, STRETCH_HALFTONE); var res2 = StretchBlt(destHdc, 75, 75, 50, 50, srcHdc, 0, 0, 100, 100, SRCCOPY); destGfx.ReleaseHdc(destHdc); destBmp.Save(".\\screen.png"); } }
补充说明:使用StretchBlt的原因是需要将超宽显示器(5120 x 1440)的大部分区域拷贝为小缩略图,因此不想先通过Graphics.CopyFromScreen拷贝完整图像再缩放——根据测试,StretchBlt一步完成的速度快得多。
调用StretchBltScreen时可以正常工作并生成截图,但编写单元测试时,尝试使用内存中的静态Bitmap作为源,StretchBlt返回1表示成功,却没有任何内容绘制到目标缩略图中。
怀疑这与设备上下文、兼容位图、DIB等相关,尝试了多种GDI调用组合仍未解决,希望得到相关技术见解。
内容的提问来源于stack exchange,提问作者mclayton
相关产品推荐
相关产品推荐

