using System; using System.ComponentModel; using System.Data; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using DevComponents.DotNetBar.Controls; using DevComponents.DotNetBar.SuperGrid.Style; namespace DevComponents.DotNetBar.SuperGrid { /// /// GridComboBoxExEditControl /// [ToolboxItem(false)] public class GridComboBoxExEditControl : ComboBoxEx, IGridCellEditControl { #region DllImports [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] private static extern void GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam); private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam); #endregion #region Static data static bool _StaticIsOpen; #endregion #region Private variables private GridCell _Cell; private EditorPanel _EditorPanel; private Bitmap _EditorCellBitmap; private bool _ValueChanged; private bool _SuspendUpdate; private bool _PanelShown; private bool _CacheDisplayMembers = true; private int _ValueIndex; private string _ValueText; private int[] _ValueIndicees; private object[] _ValueMembers; private CurrencyManager _CurrentDataManager; private StretchBehavior _StretchBehavior = StretchBehavior.None; #endregion /// /// GridComboBoxExEditControl /// public GridComboBoxExEditControl() { DrawMode = DrawMode.OwnerDrawFixed; DisconnectedPopupDataSource = true; BindingContext = new BindingContext(); } #region OnDataSourceChanged /// /// OnDataSourceChanged /// /// protected override void OnDataSourceChanged(EventArgs e) { if (_CurrentDataManager != null) _CurrentDataManager.ListChanged -= DataManagerListChanged; base.OnDataSourceChanged(e); _ValueMembers = null; _ValueIndicees = null; _CurrentDataManager = DataManager; if (_CurrentDataManager != null) _CurrentDataManager.ListChanged += DataManagerListChanged; if (IsDisposed == false) { if (_Cell != null && _Cell.GridPanel != null) InitializeContext(_Cell, null); } } #endregion #region DataManagerListChanged /// /// DataManager_ListChanged /// /// /// void DataManagerListChanged(object sender, ListChangedEventArgs e) { _ValueMembers = null; _ValueIndicees = null; } #endregion #region OnTextChanged /// /// OnTextChanged /// /// protected override void OnTextChanged(EventArgs e) { if (IsDisposed == false) { if (_Cell != null && _SuspendUpdate == false) { _Cell.EditorValueChanged(this); _ValueIndex = -1; } } base.OnTextChanged(e); } #endregion #region OnSelectedIndexChanged /// /// OnSelectedIndexChanged /// /// protected override void OnSelectedIndexChanged(EventArgs e) { if (IsDisposed == false) { if (_Cell != null && _SuspendUpdate == false) { _ValueIndex = SelectedIndex; _Cell.EditorValueChanged(this); EditorValueChanged = true; } } base.OnSelectedIndexChanged(e); } #endregion #region OnInvalidated /// /// OnInvalidated /// /// protected override void OnInvalidated(InvalidateEventArgs e) { base.OnInvalidated(e); if (_Cell != null && _SuspendUpdate == false) _Cell.InvalidateRender(); } #endregion #region GetValue /// /// GetValue /// /// /// public virtual object GetValue(object value) { GridPanel panel = _Cell.GridPanel; if (value == null || (panel.NullValue == NullValue.DBNull && value == DBNull.Value)) { return (""); } if (_Cell.IsValueExpression == true) value = _Cell.GetExpValue((string)value); return (value); } #endregion #region SetValue private void SetValue(object o, bool initEdit) { _ValueText = ""; _ValueIndex = -1; bool oldSuspend = SuspendUpdate; SuspendUpdate = true; SelectedIndex = -1; SuspendUpdate = oldSuspend; if (o != null) { _ValueText = o.ToString(); if (string.IsNullOrEmpty(_ValueText) == false && string.IsNullOrEmpty(ValueMember) == false && string.IsNullOrEmpty(DisplayMember) == false) { if (Items.Count > 0) { if (Items[0] is DataRowView && initEdit == false && _CacheDisplayMembers == true) { SetSelectedDrvValue(o); } else { SetSelectedValue(o); } } } else { Text = _ValueText; _ValueIndex = SelectedIndex; } } } #region SetSelectedDrvValue private void SetSelectedDrvValue(object o) { if (_ValueMembers == null) { SuspendUpdate = true; _ValueMembers = new object[Items.Count]; _ValueIndicees = new int[Items.Count]; for (int i = 0; i < Items.Count; i++) { DataRowView drv = (DataRowView)Items[i]; _ValueMembers[i] = drv.Row[ValueMember]; _ValueIndicees[i] = i; } Array.Sort(_ValueMembers, _ValueIndicees); SuspendUpdate = false; } int n = -1; try { n = Array.BinarySearch(_ValueMembers, o); } catch { } if (n >= 0) { _ValueIndex = _ValueIndicees[n]; _ValueText = GetItemText(Items[_ValueIndex]); } else { Text = _ValueText; } } #endregion #region SetSelectedValue private void SetSelectedValue(object o) { try { SelectedValue = o; _ValueIndex = SelectedIndex; if (SelectedValue != null) _ValueText = Text; } catch { Text = _ValueText; } } #endregion #endregion #region IGridCellEditControl Members #region Public properties #region CacheDisplayMembers /// /// Informs the control to cache DataRowView /// ValueMember/DisplayMember information (default is true). /// public bool CacheDisplayMembers { get { return (_CacheDisplayMembers); } set { _CacheDisplayMembers = value; if (value == false) { _ValueMembers = null; _ValueIndicees = null; } } } #endregion #region CanInterrupt /// /// CanInterrupt /// public virtual bool CanInterrupt { get { return (true); } } #endregion #region CellEditMode CellEditMode _CellEditMode = CellEditMode.Modal; /// /// CellEditMode /// public virtual CellEditMode CellEditMode { get { return (_CellEditMode); } } #endregion #region EditorCell /// /// EditorCell /// public GridCell EditorCell { get { return (_Cell); } set { _Cell = value; } } #endregion #region EditorCellBitmap /// /// EditorCellBitmap /// public Bitmap EditorCellBitmap { get { return (_EditorCellBitmap); } set { if (_EditorCellBitmap != null) _EditorCellBitmap.Dispose(); _EditorCellBitmap = value; } } #endregion #region EditorFormattedValue /// /// EditorFormattedValue /// public virtual string EditorFormattedValue { get { if (_Cell != null && _Cell.IsValueNull == true) return (_Cell.NullString); return (_ValueText); } } #endregion #region EditorPanel /// /// EditorPanel /// public EditorPanel EditorPanel { get { return (_EditorPanel); } set { _EditorPanel = value; } } #endregion #region EditorValue /// /// EditorValue /// public virtual object EditorValue { get { if (_ValueIndex >= 0) SelectedIndex = _ValueIndex; if (string.IsNullOrEmpty(ValueMember) == false) return (SelectedValue ?? Text); if (string.IsNullOrEmpty(DisplayMember) == false) return (Text); return (this.SelectedValue ?? this.SelectedItem ?? Text); } set { SetValue(GetValue(value), true); } } #endregion #region EditorValueChanged /// /// EditorValueChanged /// public virtual bool EditorValueChanged { get { return (_ValueChanged); } set { if (_ValueChanged != value) { _ValueChanged = value; if (value == true) _Cell.SetEditorDirty(this); } } } #endregion #region EditorValueType /// /// EditorValueType /// public virtual Type EditorValueType { get { return (typeof(string)); } } #endregion #region StretchBehavior /// /// StretchBehavior /// public virtual StretchBehavior StretchBehavior { get { return (_StretchBehavior); } set { _StretchBehavior = value; } } #endregion #region SuspendUpdate /// /// SuspendUpdate /// public bool SuspendUpdate { get { return (_SuspendUpdate); } set { _SuspendUpdate = value; } } #endregion #region ValueChangeBehavior /// /// ValueChangeBehavior /// public virtual ValueChangeBehavior ValueChangeBehavior { get { return (ValueChangeBehavior.InvalidateRender); } } #endregion #endregion #region InitializeContext /// /// InitializeContext /// /// /// public virtual void InitializeContext(GridCell cell, CellVisualStyle style) { _Cell = cell; if (style != null) { Enabled = (_Cell.ReadOnly == false); Font = style.Font; ForeColor = style.TextColor; } SetValue(GetValue(_Cell.Value), false); _ValueChanged = false; } #endregion #region GetProposedSize /// /// GetProposedSize /// /// /// /// /// /// public virtual Size GetProposedSize(Graphics g, GridCell cell, CellVisualStyle style, Size constraintSize) { eTextFormat tf = eTextFormat.NoClipping | eTextFormat.WordEllipsis | eTextFormat.NoPrefix; if (style.AllowWrap == Tbool.True) tf |= eTextFormat.WordBreak; string s = EditorFormattedValue; if (String.IsNullOrEmpty(s) == true) s = " "; Size size = (constraintSize.IsEmpty == true) ? TextHelper.MeasureText(g, s, style.Font) : TextHelper.MeasureText(g, s, style.Font, constraintSize, tf); if (ItemHeight > size.Height) size.Height = ItemHeight; size.Height += Dpi.Height(DefaultMargin.Vertical); return (size); } #endregion #region Edit support #region BeginEdit /// /// BeginEdit /// /// /// public virtual bool BeginEdit(bool selectAll) { // If we are caching Display/Value member info, then // force the ComboBox to now set the correct SelectedValue. if (CacheDisplayMembers == true) { object o = EditorValue; } return (false); } #endregion #region EndEdit /// /// EndEdit /// /// public virtual bool EndEdit() { if (IsPopupOpen == true) IsPopupOpen = false; return (false); } #endregion #region CancelEdit /// /// CancelEdit /// /// public virtual bool CancelEdit() { if (IsPopupOpen == true) IsPopupOpen = false; return (false); } #endregion #endregion #region CellRender /// /// CellRender /// /// public virtual void CellRender(Graphics g) { if (_PanelShown == false) { _EditorPanel.Show(); _EditorPanel.Hide(); _PanelShown = true; } _Cell.CellRender(this, g); } #endregion #region Keyboard support #region CellKeyDown /// /// CellKeyDown /// public virtual void CellKeyDown(KeyEventArgs e) { Focus(); switch (e.KeyData) { default: OnKeyDown(e); break; } } #endregion #region WantsInputKey /// /// WantsInputKey /// /// /// /// public virtual bool WantsInputKey(Keys key, bool gridWantsKey) { switch (key & Keys.KeyCode) { case Keys.Space: case Keys.Up: case Keys.Down: return (true); case Keys.Enter: if (DroppedDown == true || IsPopupOpen == true) return (true); if (AutoCompleteMode != AutoCompleteMode.None) { if (string.IsNullOrEmpty(DropDownColumns) == true) { if (IsAutoSuggestOpen() == true) return (true); } } break; } return (gridWantsKey == false); } #region IsAutoSuggestOpen private bool IsAutoSuggestOpen() { _StaticIsOpen = false; EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowCallback, IntPtr.Zero); return (_StaticIsOpen); } #region EnumThreadWindowCallback private static bool EnumThreadWindowCallback(IntPtr hWnd, IntPtr lParam) { if (IsWindowVisible(hWnd) == true) { if ((GetClassName(hWnd) == "Auto-Suggest Dropdown")) { _StaticIsOpen = true; return (false); } } return true; } #region GetClassName private static string GetClassName(IntPtr hRef) { StringBuilder lpClassName = new StringBuilder(256); GetClassName(hRef, lpClassName, 256); return (lpClassName.ToString()); } #endregion #endregion #endregion #endregion #endregion #region Mouse support #region OnCellMouseMove /// /// OnCellMouseMove /// /// public virtual void OnCellMouseMove(MouseEventArgs e) { } #endregion #region OnCellMouseEnter /// /// OnCellMouseEnter /// /// public virtual void OnCellMouseEnter(EventArgs e) { } #endregion #region OnCellMouseLeave /// /// OnCellMouseLeave /// /// public virtual void OnCellMouseLeave(EventArgs e) { } #endregion #region OnCellMouseUp /// /// OnCellMouseUp /// /// public virtual void OnCellMouseUp(MouseEventArgs e) { } #endregion #region OnCellMouseDown /// /// OnCellMouseDown /// /// public virtual void OnCellMouseDown(MouseEventArgs e) { } #endregion #endregion #endregion #region Dispose /// /// Dispose /// /// protected override void Dispose(bool disposing) { if (_CurrentDataManager != null) _CurrentDataManager.ListChanged -= DataManagerListChanged; BindingContext = null; base.Dispose(disposing); } #endregion } }