using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SensorTechnology;
using System.Runtime.InteropServices;

namespace SampleCallback
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            m_GDICallbackDelegate = new StCam.fStCamPreviewGDICallbackFunc(OnGDICallbackFunc);

        }
        private System.IntPtr m_hCamera;
        private bool m_bStatusTransfer = false;
        private bool m_bStatusAVIFile = false;
        private bool m_bStatusPreviewWnd = false;
        private FormSnapShot m_FormSnapShot;
        private uint m_dwPreviewGDICallbackNo = 0;
        private StCam.fStCamPreviewGDICallbackFunc m_GDICallbackDelegate;
        private CFPS m_FPS = new CFPS(100);

        private void Form1_Load(object sender, EventArgs e)
        {
            m_hCamera = StCam.Open(0);
            if (m_hCamera == IntPtr.Zero)
                ShowErrorMsg(StCam.GetLastError(m_hCamera));
            if (!StCam.SetReceiveMsgWindow(m_hCamera, this.Handle))
                ShowErrorMsg(StCam.GetLastError(m_hCamera));
            StatusChanged();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (m_hCamera != System.IntPtr.Zero)
                StCam.Close(m_hCamera);
        }

        private void btnPreview_Click(object sender, EventArgs e)
        {
            if (m_bStatusPreviewWnd && m_bStatusTransfer)
            {
                //Stop
                if (!StCam.StopTransfer(m_hCamera))
                    ShowErrorMsg(StCam.GetLastError(m_hCamera));
            }
            else
            {
                //Start
                if (!StCam.CreatePreviewWindow(
                    m_hCamera, "Preview",
                    StCam.WS_OVERLAPPEDWINDOW | StCam.WS_VISIBLE,
                    0, 0, 0, 0, System.IntPtr.Zero, System.IntPtr.Zero, true))
                    ShowErrorMsg(StCam.GetLastError(m_hCamera));
                if (!StCam.StartTransfer(m_hCamera))
                    ShowErrorMsg(StCam.GetLastError(m_hCamera));
            }
        }
        private void StatusChanged()
        {
            if (m_bStatusPreviewWnd && m_bStatusTransfer)
                btnPreview.Text = "STOP";
            else
                btnPreview.Text = "START";
            btnMovie.Enabled = !m_bStatusAVIFile;
            if (m_dwPreviewGDICallbackNo == 0)
            {
                btnFPS.Text = "Show FPS";
            }
            else
            {
                btnFPS.Text = "Erase FPS";
            }

        }
        [System.Security.Permissions.PermissionSet(
            System.Security.Permissions.SecurityAction.Demand,
            Name = "FullTrust")]
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case StCam.WM_STCAM_TRANSFER_START:
                    m_bStatusTransfer = true;
                    StatusChanged();
                    break;
                case StCam.WM_STCAM_TRANSFER_FINISH:
                    m_bStatusTransfer = false;
                    StatusChanged();
                    if ((uint)m.LParam != 0)
                        ShowErrorMsg((uint)m.LParam);
                    break;
                case StCam.WM_STCAM_AVI_FILE_START:
                    m_bStatusAVIFile = true;
                    StatusChanged();
                    break;
                case StCam.WM_STCAM_AVI_FILE_FINISH:
                    m_bStatusAVIFile = false;
                    StatusChanged();
                    if ((uint)m.LParam != 0)
                        ShowErrorMsg((uint)m.LParam);
                    break;
                case StCam.WM_STCAM_PREVIEW_WINDOW_CREATE:
                    m_bStatusPreviewWnd = true;
                    StatusChanged();
                    break;
                case StCam.WM_STCAM_PREVIEW_WINDOW_CLOSE:
                    m_bStatusPreviewWnd = false;
                    StatusChanged();
                    if ((uint)m.LParam != 0)
                        ShowErrorMsg((uint)m.LParam);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern int FormatMessage(int dwFlags, IntPtr lpSource,
            int dwMessageId, int dwLanguageId, System.Text.StringBuilder lpBuffer, int nSize, IntPtr Arguments);
        [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern IntPtr LoadLibraryEx(String lpszLibFile, IntPtr hFile, int dwFlags);
        [DllImport("kernel32.dll")]
        private static extern int FreeLibrary(IntPtr hModule);

        private void ShowErrorMsg(uint dwErrorCode)
        {
            int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
            int FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;

            int DONT_RESOLVE_DLL_REFERENCES = 0x00000001;

            System.Text.StringBuilder strErrorMsg = new System.Text.StringBuilder(255);
            int dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
            IntPtr ptrlpSource = IntPtr.Zero;

            int iFoundErrMsg = FormatMessage(dwFlags, ptrlpSource, (int)dwErrorCode, 0, strErrorMsg, strErrorMsg.Capacity, IntPtr.Zero);
            if (iFoundErrMsg == 0)
            {
                ptrlpSource = LoadLibraryEx("StCamMsg.dll", IntPtr.Zero, DONT_RESOLVE_DLL_REFERENCES);
                dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;

                if (!ptrlpSource.Equals(IntPtr.Zero))
                {
                    iFoundErrMsg = FormatMessage(dwFlags, ptrlpSource, (int)dwErrorCode, 0, strErrorMsg, strErrorMsg.Capacity, IntPtr.Zero);
                    FreeLibrary(ptrlpSource);
                }
            }

            System.Windows.Forms.MessageBox.Show(strErrorMsg.ToString(), "Error Message", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);

        }

        private void btnSnap_Click(object sender, EventArgs e)
        {
            bool bReval = true;
            uint nLastErrorNo = 0;

            do
            {
                //Get Image Size
                uint dwSize;
                uint dwWidth;
                uint dwHeight;
                uint dwLinePitch;
                bReval = StCam.GetPreviewDataSize(m_hCamera, out dwSize,out dwWidth, out dwHeight, out dwLinePitch);
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                    break;
                }

                //Get Preview Pixel Format
                uint dwPreviewPixelFormat;
                bReval = StCam.GetPreviewPixelFormat(m_hCamera, out dwPreviewPixelFormat);
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                    break;
                }

                //Allocate Memory
                System.Drawing.Imaging.PixelFormat pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
                switch (dwPreviewPixelFormat)
                {
                    case (StCam.STCAM_PIXEL_FORMAT_24_BGR):
                        pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
                        break;
                    case (StCam.STCAM_PIXEL_FORMAT_32_BGR):
                        pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppRgb;
                        break;
                }

                byte[] pbyteImageBuffer = new byte[dwSize];

                //Take Snap Shot
                uint dwNumberOfByteTrans;
                uint[] pdwFrameNo = new uint[1];
                uint dwMilliseconds = 100;
                System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.Alloc(pbyteImageBuffer, System.Runtime.InteropServices.GCHandleType.Pinned);
                System.IntPtr ptr = gch.AddrOfPinnedObject();

                bReval = StCam.TakePreviewSnapShot(m_hCamera, ptr, dwSize, out dwNumberOfByteTrans, pdwFrameNo, dwMilliseconds);

                gch.Free();
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                    break;
                }

                if (m_FormSnapShot == null)
                {
                    m_FormSnapShot = new FormSnapShot();
                    m_FormSnapShot.FormClosed += new System.Windows.Forms.FormClosedEventHandler(FormSnapShot_FormClosed);
                }
                m_FormSnapShot.bUpdateSnapShot((int)dwWidth, (int)dwHeight, pbyteImageBuffer, dwSize, pixelFormat);
                m_FormSnapShot.Show();
            } while (false);

            //Show Error Message
            if (!bReval)
            {
                ShowErrorMsg(nLastErrorNo);
            }
        }
        private void FormSnapShot_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
        {
            m_FormSnapShot = null;
        }

        private void btnMovie_Click(object sender, EventArgs e)
        {
            bool bReval = true;
            uint nLastErrorNo = 0;

            if (DialogResult.OK == saveFileDialog1.ShowDialog(this))
            {
                bReval = StCam.SaveAVI(m_hCamera, saveFileDialog1.FileName, StCam.STCAM_AVI_COMPRESSOR_MJPG, 300, IntPtr.Zero);
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                }
            }

            //Show Error Message
            if (!bReval)
            {
                ShowErrorMsg(nLastErrorNo);
            }

        }
        public void OnGDICallbackFunc(IntPtr hDC, uint dwWidth, uint dwHeight, uint dwFrameNo, IntPtr lpContext, IntPtr lpReserved)
        {
            Graphics grfx = System.Drawing.Graphics.FromHdcInternal(hDC);
            Font fontString = new Font(FontFamily.GenericSerif, 12);
            SolidBrush brushString = new SolidBrush(Color.Black);

            m_FPS.Check();

            double dblFPS = m_FPS.GetFPS();
            grfx.DrawString(dblFPS.ToString("0.0") + "FPS", fontString, brushString, 0, 0);

            brushString.Dispose();
            fontString.Dispose();
            grfx.Dispose();
        }

        private void btnFPS_Click(object sender, EventArgs e)
        {
            bool bReval = true;
            uint nLastErrorNo = 0;

            if (m_dwPreviewGDICallbackNo == 0)
            {
                m_FPS.Reset();
                bReval = StCam.AddPreviewGDICallback(m_hCamera, m_GDICallbackDelegate, IntPtr.Zero, out m_dwPreviewGDICallbackNo);
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                }
            }
            else
            {
                bReval = StCam.RemovePreviewGDICallback(m_hCamera, m_dwPreviewGDICallbackNo);
                if (!bReval)
                {
                    nLastErrorNo = StCam.GetLastError(m_hCamera);
                }
                m_dwPreviewGDICallbackNo = 0;
            }
            //Show Error Message
            if (!bReval)
            {
                ShowErrorMsg(nLastErrorNo);
            }

        }
    }
}