Option Strict On
Option Explicit On

Imports System
Imports System.Runtime.InteropServices

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Win32 constants that are safe for MAS layered-window hosts to use from Form.CreateParams.
    ''' </summary>
    Friend NotInheritable Class MASLayeredWindowStyles

        Private Sub New()
        End Sub

        Friend Const WS_EX_LAYERED As Integer = &H80000
        Friend Const WS_EX_TOOLWINDOW As Integer = &H80

    End Class

    ''' <summary>
    ''' Internal Win32 bridge used by MAS layered-window presentation.
    ''' Kept inside MAS so external applications do not own layered-window mechanics.
    ''' </summary>
    Friend NotInheritable Class MASLayeredWindowNativeMethods

        Private Sub New()
        End Sub

        Friend Shared ReadOnly InvalidHandleValue As IntPtr = New IntPtr(-1)

        Friend Const ULW_ALPHA As Integer = &H2
        Friend Const AC_SRC_OVER As Byte = &H0
        Friend Const AC_SRC_ALPHA As Byte = &H1
        Friend Const BI_RGB As UInteger = 0UI
        Friend Const DIB_RGB_COLORS As UInteger = 0UI

        <StructLayout(LayoutKind.Sequential)>
        Friend Structure POINT
            Friend X As Integer
            Friend Y As Integer

            Friend Sub New(x As Integer, y As Integer)
                Me.X = x
                Me.Y = y
            End Sub
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Friend Structure SIZE
            Friend cx As Integer
            Friend cy As Integer

            Friend Sub New(width As Integer, height As Integer)
                Me.cx = width
                Me.cy = height
            End Sub
        End Structure

        <StructLayout(LayoutKind.Sequential, Pack:=1)>
        Friend Structure BLENDFUNCTION
            Friend BlendOp As Byte
            Friend BlendFlags As Byte
            Friend SourceConstantAlpha As Byte
            Friend AlphaFormat As Byte

            Friend Shared Function CreatePerPixel(Optional constantAlpha As Byte = 255) As BLENDFUNCTION
                Return New BLENDFUNCTION With {
                    .BlendOp = AC_SRC_OVER,
                    .BlendFlags = 0,
                    .SourceConstantAlpha = constantAlpha,
                    .AlphaFormat = AC_SRC_ALPHA
                }
            End Function
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Friend Structure BITMAPINFOHEADER
            Friend biSize As UInteger
            Friend biWidth As Integer
            Friend biHeight As Integer
            Friend biPlanes As Short
            Friend biBitCount As Short
            Friend biCompression As UInteger
            Friend biSizeImage As UInteger
            Friend biXPelsPerMeter As Integer
            Friend biYPelsPerMeter As Integer
            Friend biClrUsed As UInteger
            Friend biClrImportant As UInteger
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Friend Structure RGBQUAD
            Friend rgbBlue As Byte
            Friend rgbGreen As Byte
            Friend rgbRed As Byte
            Friend rgbReserved As Byte
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Friend Structure BITMAPINFO
            Friend bmiHeader As BITMAPINFOHEADER

            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)>
            Friend bmiColors As RGBQUAD()
        End Structure

        Friend Shared Function CreateTopDown32BitBitmapInfo(width As Integer, height As Integer) As BITMAPINFO
            If width <= 0 Then Throw New ArgumentOutOfRangeException(NameOf(width))
            If height <= 0 Then Throw New ArgumentOutOfRangeException(NameOf(height))

            Return New BITMAPINFO With {
                .bmiHeader = New BITMAPINFOHEADER With {
                    .biSize = CUInt(Marshal.SizeOf(GetType(BITMAPINFOHEADER))),
                    .biWidth = width,
                    .biHeight = -height,
                    .biPlanes = 1S,
                    .biBitCount = 32S,
                    .biCompression = BI_RGB,
                    .biSizeImage = CUInt(width * height * 4)
                },
                .bmiColors = New RGBQUAD(0) {}
            }
        End Function

        Friend Shared Function CreateWindowSize(width As Integer, height As Integer) As SIZE
            If width < 0 Then Throw New ArgumentOutOfRangeException(NameOf(width))
            If height < 0 Then Throw New ArgumentOutOfRangeException(NameOf(height))

            Return New SIZE(width, height)
        End Function

        Friend Shared Function IsNullOrInvalidGdiHandle(handle As IntPtr) As Boolean
            Return handle = IntPtr.Zero OrElse handle = InvalidHandleValue
        End Function

        Friend Shared Function IsValidGdiHandle(handle As IntPtr) As Boolean
            Return Not IsNullOrInvalidGdiHandle(handle)
        End Function

        <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function UpdateLayeredWindow(
            hwnd As IntPtr,
            hdcDst As IntPtr,
            ByRef pptDst As POINT,
            ByRef psize As SIZE,
            hdcSrc As IntPtr,
            ByRef pptSrc As POINT,
            crKey As Integer,
            ByRef pblend As BLENDFUNCTION,
            dwFlags As Integer
        ) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function GetDC(hwnd As IntPtr) As IntPtr
        End Function

        <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function ReleaseDC(hwnd As IntPtr, hdc As IntPtr) As Integer
        End Function

        <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function CreateCompatibleDC(hdc As IntPtr) As IntPtr
        End Function

        <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function DeleteDC(hdc As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function SelectObject(hdc As IntPtr, h As IntPtr) As IntPtr
        End Function

        <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function DeleteObject(hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
        Friend Shared Function CreateDIBSection(
            hdc As IntPtr,
            <[In]> ByRef pbmi As BITMAPINFO,
            iUsage As UInteger,
            ByRef ppvBits As IntPtr,
            hSection As IntPtr,
            dwOffset As UInteger
        ) As IntPtr
        End Function

    End Class

End Namespace
