Push Interop

This commit is contained in:
Blue 2021-01-15 22:53:20 +01:00
parent 0b551e00c7
commit eac81c8c59
5 changed files with 285 additions and 0 deletions

View file

@ -0,0 +1,8 @@
namespace ProjectPSX
{
internal static class ExternDll
{
public const string Gdi32 = "gdi32.dll";
public const string User32 = "user32.dll";
}
}

View file

@ -0,0 +1,111 @@
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace ProjectPSX.Interop.Gdi32
{
internal enum BitmapCompression : uint
{
BI_RGB = 0,
BI_RLE8 = 1,
BI_RLE4 = 2,
BI_BITFIELDS = 3,
BI_JPEG = 4,
BI_PNG = 5,
}
[StructLayout(LayoutKind.Sequential)]
internal struct BitmapInfoHeader
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public BitmapCompression biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RgbQuad
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct BitmapInfo
{
public BitmapInfoHeader bmiHeader;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] bmiColors;
}
internal enum ColorUsage : uint
{
DIB_RGB_COLORS = 0, /* color table in RGBs */
DIB_PAL_COLORS = 1, /* color table in palette indices */
}
internal enum RasterOp : uint
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest )
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
NOMIRRORBITMAP = 0x80000000, // Do not Mirror the bitmap in this call
CAPTUREBLT = 0x40000000, // Include layered windows
}
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
[DllImport(ExternDll.Gdi32)]
internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport(ExternDll.Gdi32)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteDC(IntPtr hdc);
[DllImport(ExternDll.Gdi32)]
internal static extern IntPtr CreateDIBSection(IntPtr hdc, [In] in BitmapInfo pbmi, ColorUsage usage,
out IntPtr ppvBits, IntPtr hSection, uint offset);
[DllImport(ExternDll.Gdi32)]
internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr h);
[DllImport(ExternDll.Gdi32)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr ho);
[DllImport(ExternDll.Gdi32)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool StretchBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest,
IntPtr hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc,
RasterOp rop);
[DllImport(ExternDll.Gdi32)]
internal static extern int StretchDIBits(IntPtr hdc, int xDest, int yDest, int DestWidth, int DestHeight,
int xSrc, int ySrc, int SrcWidth, int SrcHeight, IntPtr lpBits,
[In] ref BitmapInfo lpbmi, ColorUsage iUsage, RasterOp rop);
}
}

View file

@ -0,0 +1,105 @@
using System;
using System.Runtime.InteropServices;
using ProjectPSX.Interop.Gdi32;
using Gdi32 = ProjectPSX.Interop.Gdi32.NativeMethods;
namespace ProjectPSX
{
internal class GdiBitmap : IDisposable
{
public readonly int BytesPerPixel = 4;
public readonly IntPtr DeviceContext;
public readonly IntPtr BitmapHandle;
public readonly int Width;
public readonly int Height;
public readonly IntPtr BitmapData;
private readonly IntPtr _oldObject;
private bool _disposed = false;
public GdiBitmap(int width, int height)
{
Width = width;
Height = height;
DeviceContext = Gdi32.CreateCompatibleDC(IntPtr.Zero);
var bitmapHeader = new BitmapInfoHeader
{
biSize = (uint)Marshal.SizeOf<BitmapInfoHeader>(),
biWidth = width,
biHeight = -height, // negative, top-down bitmap
biPlanes = 1,
biBitCount = (ushort)(8 * BytesPerPixel),
biCompression = BitmapCompression.BI_RGB,
};
var bitmapInfo = new BitmapInfo
{
bmiHeader = bitmapHeader,
};
BitmapHandle = Gdi32.CreateDIBSection(DeviceContext, in bitmapInfo, ColorUsage.DIB_RGB_COLORS,
out BitmapData, IntPtr.Zero, 0);
_oldObject = Gdi32.SelectObject(DeviceContext, BitmapHandle);
}
public unsafe void DrawPixel(int x, int y, int color) {
int* pixel = (int*)BitmapData;
pixel += x + (y * Width);
*pixel = color;
}
public unsafe int GetPixel(int x, int y) {
int* pixel = (int*)BitmapData;
pixel += x + (y * Width);
return *pixel;
}
~GdiBitmap()
{
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
if (_oldObject != IntPtr.Zero)
{
Gdi32.SelectObject(DeviceContext, _oldObject);
}
if (BitmapHandle != IntPtr.Zero)
{
Gdi32.DeleteObject(BitmapHandle);
}
if (DeviceContext != IntPtr.Zero)
{
Gdi32.DeleteDC(DeviceContext);
}
_disposed = true;
}
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using User32 = ProjectPSX.Interop.User32.NativeMethods;
namespace ProjectPSX
{
internal readonly ref struct GdiDeviceContext
{
private readonly IntPtr _handle;
private readonly IntPtr _hdc;
public GdiDeviceContext(IntPtr handle)
{
_handle = handle;
_hdc = User32.GetDC(handle);
}
public void Dispose()
{
User32.ReleaseDC(_handle, _hdc);
}
public static implicit operator IntPtr(GdiDeviceContext dc)
{
return dc._hdc;
}
}
}

View file

@ -0,0 +1,33 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Security;
namespace ProjectPSX.Interop.User32
{
[StructLayout(LayoutKind.Sequential)]
internal struct Message
{
public IntPtr hWnd;
public uint msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public Point p;
}
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
[DllImport(ExternDll.User32)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin,
uint messageFilterMax, uint flags);
[DllImport(ExternDll.User32)]
internal static extern IntPtr GetDC(IntPtr hWnd);
[DllImport(ExternDll.User32)]
internal static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
}
}