////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Removes device of the specified ID.
        /// </summary>
        /// <param name="deviceID_I">Touch device identifier</param>
        public void RemoveDevice(Int32 deviceID_I)
        {
            IntPtr devBuf = IntPtr.Zero;

            try
            {
                if (mDeviceCapsMap.ContainsKey(deviceID_I))
                {
                    mDeviceCapsMap.Remove(deviceID_I);

                    // Make sure we're in sync with system's view of #attached devices.
                    devBuf = CMemUtils.AllocUnmanagedBuf(mDeviceIDArray);
                    Marshal.StructureToPtr(mDeviceIDArray, devBuf, false);

                    mNumDevices = CWacomMTInterface.WacomMTGetAttachedDeviceIDs(devBuf, mMaxNumTouchDevices * sizeof(Int32));

                    if (mNumDevices > 0)
                    {
                        mDeviceIDArray = (WacomMTDeviceIDArray)Marshal.PtrToStructure(devBuf, typeof(WacomMTDeviceIDArray));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                CMemUtils.FreeUnmanagedBuf(ref devBuf);
            }
        }
        /// <summary>
        /// Find capabilities for all attached touch devices.
        /// If successful, this will populate mDeviceCapsMap.
        /// </summary>
        /// <returns> true if all device capabilities updated</returns>
        private bool UpdateDeviceCaps()
        {
            IntPtr devBuf = IntPtr.Zero;

            try
            {
                if (mNumDevices > 0)
                {
                    for (int idx = 0; idx < mNumDevices; idx++)
                    {
                        Int32             devID   = mDeviceIDArray.data[idx];
                        WacomMTCapability devCaps = new WacomMTCapability();

                        devBuf = CMemUtils.AllocUnmanagedBuf(devCaps);
                        Marshal.StructureToPtr(devCaps, devBuf, false);

                        if (WacomMTError.WMTErrorSuccess == CWacomMTInterface.WacomMTGetDeviceCapabilities(devID, devBuf))
                        {
                            devCaps = (WacomMTCapability)Marshal.PtrToStructure(devBuf, typeof(WacomMTCapability));
                            mDeviceCapsMap[devID] = devCaps;
                            DumpDeviceCaps(devID);

                            CMemUtils.FreeUnmanagedBuf(ref devBuf);;
                        }
                        else
                        {
                            throw new Exception("Oops - failed WacomMTGetDeviceCapabilities");
                        }
                    }

                    return(true);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (devBuf != IntPtr.Zero)
                {
                    CMemUtils.FreeUnmanagedBuf(ref devBuf);
                }
            }

            return(false);
        }
        ////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Adds touch device with the specified device capability to the current
        /// list of attached devices.
        /// </summary>
        /// <param name="deviceCapability_I"></param>
        public void AddDevice(WacomMTCapability deviceCapability_I)
        {
            IntPtr devBuf = IntPtr.Zero;

            try
            {
                Int32 deviceID = deviceCapability_I.DeviceID;

                // Only add device if not already added.
                if (!mDeviceCapsMap.ContainsKey(deviceID))
                {
                    mDeviceCapsMap[deviceID] = deviceCapability_I;

                    // Make sure we're in sync with system's view of #attached devices.
                    devBuf = CMemUtils.AllocUnmanagedBuf(mDeviceIDArray);
                    Marshal.StructureToPtr(mDeviceIDArray, devBuf, false);

                    if (mNumDevices > WacomMTConstants.MAX_NUMBER_TOUCH_DEVICES)
                    {
                        throw new Exception("Too many touch devices attached");
                    }

                    mNumDevices = CWacomMTInterface.WacomMTGetAttachedDeviceIDs(devBuf, mMaxNumTouchDevices * sizeof(Int32));

                    if (mNumDevices > 0)
                    {
                        mDeviceIDArray = (WacomMTDeviceIDArray)Marshal.PtrToStructure(devBuf, typeof(WacomMTDeviceIDArray));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                CMemUtils.FreeUnmanagedBuf(ref devBuf);
            }
        }
        ////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Initialize MTAPI, find/cache connected devices
        /// and their capabilities.
        /// </summary>
        public void Init()
        {
            IntPtr devBuf = IntPtr.Zero;

            try
            {
                WacomMTError res = WacomMTError.WMTErrorSuccess;

                // ----------------------------------------------------------------
                // Initialize the MTAPI.
                //
                res = CWacomMTInterface.WacomMTInitialize(WacomMTConstants.WACOM_MULTI_TOUCH_API_VERSION);
                if (WacomMTError.WMTErrorSuccess != res)
                {
                    throw new Exception("Oops - failed WacomMTInitialize - is the tablet touch driver running?");
                }
                Trace.WriteLine("WacomMTDN: WacomMTInitialize successful.");

                // ----------------------------------------------------------------
                // Find all attached touch devices.
                // If successful, this will populate mDeviceIDArray.data.
                //
                devBuf = CMemUtils.AllocUnmanagedBuf(mDeviceIDArray);
                Marshal.StructureToPtr(mDeviceIDArray, devBuf, false);

                if (mNumDevices > WacomMTConstants.MAX_NUMBER_TOUCH_DEVICES)
                {
                    throw new Exception("Too many touch devices attached");
                }

                mNumDevices = CWacomMTInterface.WacomMTGetAttachedDeviceIDs(devBuf, mMaxNumTouchDevices * sizeof(Int32));

                if (mNumDevices > 0)
                {
                    mDeviceIDArray = (WacomMTDeviceIDArray)Marshal.PtrToStructure(devBuf, typeof(WacomMTDeviceIDArray));
                    DumpDeviceIDArray();
                }
                else
                {
                    Trace.WriteLine("WacomMTDN: NO TOUCH DEVICES FOUND!");
                }

                CMemUtils.FreeUnmanagedBuf(ref devBuf);

                // ----------------------------------------------------------------
                // Find capabilities for all attached touch devices.
                // If successful, this will populate mDeviceCapsMap.
                //
                if ((mNumDevices > 0) && !UpdateDeviceCaps())
                {
                    throw new Exception("Oops - could not complete query for capabilities");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                if (devBuf != IntPtr.Zero)
                {
                    CMemUtils.FreeUnmanagedBuf(ref devBuf);
                }
            }
        }