872 lines
20 KiB
C#
872 lines
20 KiB
C#
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
|
|
{
|
|
///<summary>
|
|
/// GridComboBoxExEditControl
|
|
///</summary>
|
|
[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
|
|
|
|
///<summary>
|
|
/// GridComboBoxExEditControl
|
|
///</summary>
|
|
public GridComboBoxExEditControl()
|
|
{
|
|
DrawMode = DrawMode.OwnerDrawFixed;
|
|
DisconnectedPopupDataSource = true;
|
|
|
|
BindingContext = new BindingContext();
|
|
}
|
|
|
|
#region OnDataSourceChanged
|
|
|
|
/// <summary>
|
|
/// OnDataSourceChanged
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// DataManager_ListChanged
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
void DataManagerListChanged(object sender, ListChangedEventArgs e)
|
|
{
|
|
_ValueMembers = null;
|
|
_ValueIndicees = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnTextChanged
|
|
|
|
/// <summary>
|
|
/// OnTextChanged
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// OnSelectedIndexChanged
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// OnInvalidated
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
protected override void OnInvalidated(InvalidateEventArgs e)
|
|
{
|
|
base.OnInvalidated(e);
|
|
|
|
if (_Cell != null && _SuspendUpdate == false)
|
|
_Cell.InvalidateRender();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetValue
|
|
|
|
/// <summary>
|
|
/// GetValue
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Informs the control to cache DataRowView
|
|
/// ValueMember/DisplayMember information (default is true).
|
|
/// </summary>
|
|
public bool CacheDisplayMembers
|
|
{
|
|
get { return (_CacheDisplayMembers); }
|
|
|
|
set
|
|
{
|
|
_CacheDisplayMembers = value;
|
|
|
|
if (value == false)
|
|
{
|
|
_ValueMembers = null;
|
|
_ValueIndicees = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CanInterrupt
|
|
|
|
/// <summary>
|
|
/// CanInterrupt
|
|
/// </summary>
|
|
public virtual bool CanInterrupt
|
|
{
|
|
get { return (true); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CellEditMode
|
|
|
|
CellEditMode _CellEditMode = CellEditMode.Modal;
|
|
|
|
/// <summary>
|
|
/// CellEditMode
|
|
/// </summary>
|
|
public virtual CellEditMode CellEditMode
|
|
{
|
|
get { return (_CellEditMode); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorCell
|
|
|
|
/// <summary>
|
|
/// EditorCell
|
|
/// </summary>
|
|
public GridCell EditorCell
|
|
{
|
|
get { return (_Cell); }
|
|
set { _Cell = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorCellBitmap
|
|
|
|
///<summary>
|
|
/// EditorCellBitmap
|
|
///</summary>
|
|
public Bitmap EditorCellBitmap
|
|
{
|
|
get { return (_EditorCellBitmap); }
|
|
|
|
set
|
|
{
|
|
if (_EditorCellBitmap != null)
|
|
_EditorCellBitmap.Dispose();
|
|
|
|
_EditorCellBitmap = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorFormattedValue
|
|
|
|
///<summary>
|
|
/// EditorFormattedValue
|
|
///</summary>
|
|
public virtual string EditorFormattedValue
|
|
{
|
|
get
|
|
{
|
|
if (_Cell != null && _Cell.IsValueNull == true)
|
|
return (_Cell.NullString);
|
|
|
|
return (_ValueText);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorPanel
|
|
|
|
/// <summary>
|
|
/// EditorPanel
|
|
/// </summary>
|
|
public EditorPanel EditorPanel
|
|
{
|
|
get { return (_EditorPanel); }
|
|
set { _EditorPanel = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorValue
|
|
|
|
/// <summary>
|
|
/// EditorValue
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// EditorValueChanged
|
|
/// </summary>
|
|
public virtual bool EditorValueChanged
|
|
{
|
|
get { return (_ValueChanged); }
|
|
|
|
set
|
|
{
|
|
if (_ValueChanged != value)
|
|
{
|
|
_ValueChanged = value;
|
|
|
|
if (value == true)
|
|
_Cell.SetEditorDirty(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EditorValueType
|
|
|
|
///<summary>
|
|
/// EditorValueType
|
|
///</summary>
|
|
public virtual Type EditorValueType
|
|
{
|
|
get { return (typeof(string)); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region StretchBehavior
|
|
|
|
/// <summary>
|
|
/// StretchBehavior
|
|
/// </summary>
|
|
public virtual StretchBehavior StretchBehavior
|
|
{
|
|
get { return (_StretchBehavior); }
|
|
set { _StretchBehavior = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SuspendUpdate
|
|
|
|
/// <summary>
|
|
/// SuspendUpdate
|
|
/// </summary>
|
|
public bool SuspendUpdate
|
|
{
|
|
get { return (_SuspendUpdate); }
|
|
set { _SuspendUpdate = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ValueChangeBehavior
|
|
|
|
/// <summary>
|
|
/// ValueChangeBehavior
|
|
/// </summary>
|
|
public virtual ValueChangeBehavior ValueChangeBehavior
|
|
{
|
|
get { return (ValueChangeBehavior.InvalidateRender); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region InitializeContext
|
|
|
|
///<summary>
|
|
/// InitializeContext
|
|
///</summary>
|
|
///<param name="cell"></param>
|
|
///<param name="style"></param>
|
|
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
|
|
|
|
///<summary>
|
|
/// GetProposedSize
|
|
///</summary>
|
|
///<param name="g"></param>
|
|
///<param name="cell"></param>
|
|
///<param name="style"></param>
|
|
///<param name="constraintSize"></param>
|
|
///<returns></returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// BeginEdit
|
|
/// </summary>
|
|
/// <param name="selectAll"></param>
|
|
/// <returns></returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// EndEdit
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual bool EndEdit()
|
|
{
|
|
if (IsPopupOpen == true)
|
|
IsPopupOpen = false;
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CancelEdit
|
|
|
|
/// <summary>
|
|
/// CancelEdit
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual bool CancelEdit()
|
|
{
|
|
if (IsPopupOpen == true)
|
|
IsPopupOpen = false;
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region CellRender
|
|
|
|
/// <summary>
|
|
/// CellRender
|
|
/// </summary>
|
|
/// <param name="g"></param>
|
|
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
|
|
|
|
///<summary>
|
|
/// CellKeyDown
|
|
///</summary>
|
|
public virtual void CellKeyDown(KeyEventArgs e)
|
|
{
|
|
Focus();
|
|
|
|
switch (e.KeyData)
|
|
{
|
|
default:
|
|
OnKeyDown(e);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region WantsInputKey
|
|
|
|
/// <summary>
|
|
/// WantsInputKey
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="gridWantsKey"></param>
|
|
/// <returns></returns>
|
|
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
|
|
|
|
///<summary>
|
|
/// OnCellMouseMove
|
|
///</summary>
|
|
///<param name="e"></param>
|
|
public virtual void OnCellMouseMove(MouseEventArgs e)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnCellMouseEnter
|
|
|
|
///<summary>
|
|
/// OnCellMouseEnter
|
|
///</summary>
|
|
///<param name="e"></param>
|
|
public virtual void OnCellMouseEnter(EventArgs e)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnCellMouseLeave
|
|
|
|
///<summary>
|
|
/// OnCellMouseLeave
|
|
///</summary>
|
|
///<param name="e"></param>
|
|
public virtual void OnCellMouseLeave(EventArgs e)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnCellMouseUp
|
|
|
|
///<summary>
|
|
/// OnCellMouseUp
|
|
///</summary>
|
|
///<param name="e"></param>
|
|
public virtual void OnCellMouseUp(MouseEventArgs e)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnCellMouseDown
|
|
|
|
///<summary>
|
|
/// OnCellMouseDown
|
|
///</summary>
|
|
///<param name="e"></param>
|
|
public virtual void OnCellMouseDown(MouseEventArgs e)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Dispose
|
|
|
|
/// <summary>
|
|
/// Dispose
|
|
/// </summary>
|
|
/// <param name="disposing"></param>
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (_CurrentDataManager != null)
|
|
_CurrentDataManager.ListChanged -= DataManagerListChanged;
|
|
|
|
BindingContext = null;
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|