using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Drawing;


namespace TwoMbit {
    class ControlHost : HwndHost {

        [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
        internal static extern IntPtr CreateWindowEx(int dwExStyle,
                                                      string lpszClassName,
                                                      string lpszWindowName,
                                                      int style,
                                                      int x, int y,
                                                      int width, int height,
                                                      IntPtr hwndParent,
                                                      IntPtr hMenu,
                                                      IntPtr hInst,
                                                      [MarshalAs(UnmanagedType.AsAny)] object pvParam);

        [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
        internal static extern int SendMessage(IntPtr hwnd,
                                               int msg,
                                               IntPtr wParam,
                                               IntPtr lParam);

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
        internal static extern int SendMessage(IntPtr hwnd,
                                               int msg,
                                               int wParam,
                                               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lParam);

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
        internal static extern IntPtr SendMessage(IntPtr hwnd,
                                                  int msg,
                                                  IntPtr wParam,
                                                  String lParam);

        [DllImport("user32.dll", EntryPoint = "GetDC")]
        static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("gdi32.dll")]
        static extern bool FillRgn(IntPtr hdc, IntPtr hrgn, IntPtr hbr);

        [DllImport("gdi32.dll")]
        static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect,
            int nBottomRect);

        [DllImport("gdi32.dll")]
        static extern IntPtr CreateSolidBrush(uint crColor);

        [DllImport("gdi32.dll")]
        static extern bool DeleteObject(IntPtr hObject);

        [DllImport("user32.dll")]
        static extern IntPtr BeginPaint(IntPtr hwnd, out PAINTSTRUCT lpPaint);

        [DllImport("user32.dll")]
        static extern bool EndPaint(IntPtr hWnd, [In] ref PAINTSTRUCT lpPaint);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT {
            private int _Left;
            private int _Top;
            private int _Right;
            private int _Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct PAINTSTRUCT {
            public IntPtr hdc;
            public bool fErase;
            public RECT rcPaint;
            public bool fRestore;
            public bool fIncUpdate;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] rgbReserved;
        }

        internal const int
            WS_CHILD = 0x40000000,
            WS_VISIBLE = 0x10000000,
            LBS_NOTIFY = 0x00000001,
            HOST_ID = 0x00000002,
            LISTBOX_ID = 0x00000001,
            WS_VSCROLL = 0x00200000,
            WS_BORDER = 0x00800000,
            WS_EX_TRANSPARENT = 0x020;

        internal const int
            LBN_SELCHANGE = 0x00000001,
            WM_COMMAND = 0x00000111,
            WM_CREATE = 0x0001,
            WM_SHOWWINDOW = 0x0018,
            WM_PAINT = 0xf,
            LB_GETCURSEL = 0x00000188,
            LB_GETTEXTLEN = 0x0000018A,
            LB_ADDSTRING = 0x00000180,
            LB_GETTEXT = 0x00000189,
            LB_DELETESTRING = 0x00000182,
            LB_GETCOUNT = 0x0000018B;

        IntPtr hwndHost;
        int hostHeight, hostWidth;

        public ControlHost(double height, double width) {
            hostHeight = (int)height;
            hostWidth = (int)width;
            hwndHost = IntPtr.Zero;
        }

        public IntPtr hwndHostBox {
            get { return hwndHost; }
        }

        protected override HandleRef BuildWindowCore(HandleRef hwndParent) {
            if (hwndHost != IntPtr.Zero) {
                DestroyWindow(hwndHost);
                hwndHost = IntPtr.Zero;
            }

            hwndHost = CreateWindowEx(0, "static", "",
                                      WS_CHILD | WS_VISIBLE,
                                      0, 0,
                                      hostWidth, hostHeight,
                                      hwndParent.Handle,
                                      (IntPtr)HOST_ID,
                                     IntPtr.Zero,
                                      0);

            return new HandleRef(this, hwndHost);
        }

        public void setBlack() {
            IntPtr wDc = GetDC(hwndHost);
            IntPtr brush = CreateSolidBrush((uint)ColorTranslator.ToWin32(Color.Black));
            FillRgn(wDc, CreateRectRgn(0, 0, hostWidth, hostHeight), brush);
            DeleteObject(brush);
        }

        protected override void DestroyWindowCore(HandleRef hwnd) {
            DestroyWindow(hwnd.Handle);
        }

        protected override IntPtr WndProc(
            IntPtr hwnd,
            int msg,
            IntPtr wParam,
            IntPtr lParam,
            ref bool handled) {
                handled = false;
                switch (msg) {
                    case WM_PAINT:
                        PAINTSTRUCT pStruct; 
                        BeginPaint(hwnd, out pStruct);
                        setBlack();
                        EndPaint(hwnd, ref pStruct); 
                        handled = true;
                        break;
                }
                return IntPtr.Zero; 
        }

    }
}
