是的 - 我知道这并不令人兴奋 - 但我的同事可以在C程序中使用相同的伪代码,它显示带有一些绿色条带的黑色方块 - 但在C#中它只绘制一个黑色方块 - 见下文:
如果您在Form1的部分类(一个新的默认Windows应用程序)中复制下面的代码 - 您将看到我的问题。 我已经尝试了一百万种不同的东西 - 但我想我是如何规定Win32的电话或其他东西 - 如果有人可以帮助我出错的地方 - 我将非常感激。
下面的代码看起来很长,但我决定把它全部放进去,所以很容易复制/粘贴到标准表格的部分类中 - 所以不要让它吓到你!
public partial class Form1 : Form
{
[DllImport("gdi32.dll", SetLastError = true)]
static extern IntPtr CreateDIBitmap([In] IntPtr hdc, [In] ref BITMAPINFOHEADER lpbmih, uint fdwInit, byte[] lpbInit, [In] ref BITMAPINFO lpbmi, uint fuUsage);
[DllImport("gdi32.dll", SetLastError = true)]
static extern int SetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint
cScanLines, byte[] lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse);
[DllImport("gdi32.dll", SetLastError = true)]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
enum TernaryRasterOperations : uint
{
/// <summary>dest = source</summary>
SRCCOPY = 0x00CC0020,
/// <summary>dest = source OR dest</summary>
SRCPAINT = 0x00EE0086,
/// <summary>dest = source AND dest</summary>
SRCAND = 0x008800C6,
/// <summary>dest = source XOR dest</summary>
SRCINVERT = 0x00660046,
/// <summary>dest = source AND (NOT dest)</summary>
SRCERASE = 0x00440328,
/// <summary>dest = (NOT source)</summary>
NOTSRCCOPY = 0x00330008,
/// <summary>dest = (NOT src) AND (NOT dest)</summary>
NOTSRCERASE = 0x001100A6,
/// <summary>dest = (source AND pattern)</summary>
MERGECOPY = 0x00C000CA,
/// <summary>dest = (NOT source) OR dest</summary>
MERGEPAINT = 0x00BB0226,
/// <summary>dest = pattern</summary>
PATCOPY = 0x00F00021,
/// <summary>dest = DPSnoo</summary>
PATPAINT = 0x00FB0A09,
/// <summary>dest = pattern XOR dest</summary>
PATINVERT = 0x005A0049,
/// <summary>dest = (NOT dest)</summary>
DSTINVERT = 0x00550009,
/// <summary>dest = BLACK</summary>
BLACKNESS = 0x00000042,
/// <summary>dest = WHITE</summary>
WHITENESS = 0x00FF0062,
/// <summary>
/// Capture window as seen on screen. This includes layered windows
/// such as WPF windows with AllowsTransparency="true"
/// </summary>
CAPTUREBLT = 0x40000000
}
[DllImport("gdi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public uint biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (uint)Marshal.SizeOf(this);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RGBQUAD
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
public BITMAPINFOHEADER bmiHeader;
public RGBQUAD bmiColors;
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
private System.IntPtr m_Bitmap;
private BITMAPINFOHEADER m_Bmh;
private BITMAPINFO m_Bmi = new BITMAPINFO();
public Form1()
{
m_Bmh.Init();
m_Bmh.biPlanes = 1;
m_Bmh.biBitCount = 24;
m_Bmh.biCompression = 0;
m_Bmh.biHeight = 100;
m_Bmh.biWidth = 100;
m_Bitmap = (IntPtr)0;
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
int errorNumber = Marshal.GetLastWin32Error();
byte[] testGraphicArray = new byte[300];
for (int i = 0; i < m_Bmh.biWidth; i++)
{
testGraphicArray[i * 3 + 0] = Convert.ToByte(i);
testGraphicArray[i * 3 + 1] = Convert.ToByte(255 - i);
testGraphicArray[i * 3 + 2] = Convert.ToByte(i);
}
IntPtr winPtr = GetDC(this.Handle);
errorNumber = Marshal.GetLastWin32Error();
//Make the bitmap
if (m_Bitmap == (IntPtr)0)
m_Bitmap = CreateDIBitmap(winPtr, ref m_Bmh, (uint)0L, testGraphicArray, ref m_Bmi, (uint)0L);
errorNumber = Marshal.GetLastWin32Error();
int retValue;
//Set data to bitmap
for (int i = 0; i < 100; i++)
{
retValue = SetDIBits((System.IntPtr)winPtr, m_Bitmap, (uint)i, 1, testGraphicArray, ref m_Bmi, (uint)0L);
}
errorNumber = Marshal.GetLastWin32Error();
// Draw the bitmap
if (m_Bitmap != (IntPtr)0)
{
IntPtr hMemDC;
IntPtr Old;
hMemDC = CreateCompatibleDC((System.IntPtr)winPtr);
Old = SelectObject(hMemDC, m_Bitmap);//Select out what was in DC
bool success = BitBlt((System.IntPtr)winPtr, 10, 10, m_Bmh.biWidth, m_Bmh.biHeight, hMemDC, 0, 0, TernaryRasterOperations.SRCCOPY);
errorNumber = Marshal.GetLastWin32Error();
SelectObject(hMemDC, Old);//Put back in the previous stuff back into DC
}
ReleaseDC(this.Handle, winPtr);
}
答案 0 :(得分:1)
是否设置了双缓冲样式?
如果是这样,那么.NET会在e.Graphics
中安排OnPaint
作为内存中的DC,并且在Paint
例程完成后,.NET将覆盖屏幕上的所有内容。那个内存层。
确保您的控件样式设置正确。我想你想要AllPaintingInWmPaint
开启,双缓冲关闭。
您缺少使用本机API正确处理WM_PAINT
所需的其他一些事项,例如使用BeginPaint
返回的设备上下文,然后调用EndPaint
。您可能需要处理来自WM_PAINT
的{{1}},而不是让.NET将其发送给WndProc
和OnPaint
事件处理程序。
我希望您这样做是为了了解Win32 GDI API,而不是因为您计划在完成的应用程序中使用.NET Forms进行绘制。