using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Design;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using C1.Win.C1FlexGrid;
using System.Collections;
namespace AngleEditor1
{
class ImageCombo : UITypeEditor
{
C1FlexGrid _flex ;
private IWindowsFormsEditorService _edSvc;
public ImageCombo(C1FlexGrid flex)
{
this._flex = flex;
_flex.Click += new EventHandler(_flex_Click);
}
public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
Console.WriteLine("editvalue");
_flex.ClientSize = new Size(
Math.Min(600, _flex.Cols[_flex.Cols.Count - 1].Right),
Math.Min(200, _flex.Rows[_flex.Rows.Count - 1].Bottom));
_edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if (_edSvc != null)
{
_edSvc.DropDownControl(_flex);
}
return value;
}
override public void PaintValue(System.Drawing.Design.PaintValueEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.Black), e.Bounds.X, e.Bounds.Y, e.Bounds.Width * 3, e.Bounds.Height);
Console.WriteLine("x={0},y={1},width={2},height={3}", e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
}
override public bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
{
return true;
}
private void _flex_Click(object sender, EventArgs e)
{
_edSvc.CloseDropDown();
}
}
class ImageComboControl :
ComboBox,
IWindowsFormsEditorService,
IServiceProvider
{
//===========================================================================
#region ** fields
private UITypeEditor _editor; // UITypeEditor responsible for editing the values
private Form _form; // form used to show the drop down
private Rectangle _bounds; // cell bounds (used to position control and form)
private object _value; // current editor value
private bool _dropped; // whether the drop down was displayed
private bool _allowTyping; // whether to allow user to edit the string representation of the value
#endregion
//===========================================================================
#region ** ctor
public ImageComboControl(UITypeEditor editor, bool allowTyping)
{
// save ctor parameters
_editor = editor;
_allowTyping = allowTyping;
// initialize combo
DropDownStyle = ComboBoxStyle.DropDown;
DrawMode = DrawMode.OwnerDrawFixed;
// initialize drop down editor
_form = new Form();
_form.StartPosition = FormStartPosition.Manual;
_form.FormBorderStyle = FormBorderStyle.None;
_form.ShowInTaskbar = false;
_form.TopLevel = true;
_form.Deactivate += new EventHandler(_form_Deactivate);
}
#endregion
//===========================================================================
#region ** IC1EmbeddedEditor
public void C1EditorInitialize(object value, IDictionary attributes)
{
// initialize editor value
_value = value;
if (value != null)
{
TypeConverter tc = TypeDescriptor.GetConverter(value.GetType());
try
{
Text = (string)tc.ConvertToString(value);
}
catch
{
Text = string.Empty;
}
}
// initialize editor style
Font = (Font) attributes["Font"];
BackColor = (Color)attributes["BackColor"];
ForeColor = (Color)attributes["ForeColor"];
// we haven't dropped the editor yet
_dropped = false;
}
public object C1EditorGetValue()
{
// return value from drop down or from edit area
return (_dropped)? _value: Text;
}
public UITypeEditorEditStyle C1EditorGetStyle()
{
return _editor.GetEditStyle();
}
public void C1EditorUpdateBounds(Rectangle rc)
{
// store bounds, will apply when showing the form
_bounds = Parent.RectangleToScreen(rc);
// if the user can type, position the combo
if (_allowTyping)
{
rc.Inflate(2, 2);
ItemHeight = Math.Max(3, rc.Height - 6);
Bounds = rc;
}
else // can't type, so hide the control
{
Bounds = Rectangle.Empty;
}
}
#endregion
//===========================================================================
#region ** overrides
// if the user can't type, show drop down right away
override protected void OnEnter(EventArgs e)
{
if (!_allowTyping)
DoDropDown();
}
// if the user can type, show drop down when requested
override protected void OnDropDown(EventArgs e)
{
if (_allowTyping)
DoDropDown();
}
// suppress OnLeave event until we're done editing
override protected void OnLeave(EventArgs e)
{
// if we dropped down, wait until we're done editing
if (_dropped)
return;
// we didn't drop down, allow dfault processing
base.OnLeave(e);
}
// this is done only to avoid annoying beeps from the ComboBoc
override public bool PreProcessMessage(ref Message msg)
{
switch (msg.Msg)
{
case 0x100: // WM_KEYDOWN:
// digest key that was pressed
KeyEventArgs e = new KeyEventArgs((Keys)(int)msg.WParam);
// if it was a tab or enter, handle internally but don't pass
// to stupid base class to avoid annoying beeps.
switch (e.KeyCode)
{
case Keys.Tab:
case Keys.Enter:
case Keys.Escape:
OnKeyDown(e);
return true;
}
break;
}
// allow regular processing
return false;
}
#endregion
//===========================================================================
#region ** private members
private void DoDropDown()
{
// fire event as usual
base.OnDropDown(EventArgs.Empty);
// if this is a popup, hide editing area
if (_editor.GetEditStyle() == UITypeEditorEditStyle.Modal)
Bounds = Rectangle.Empty;
// show editor and get the new value
_dropped = true;
_value = _editor.EditValue((IServiceProvider)this, _value);
// force the drop down to close
DrawMode = DrawMode.OwnerDrawFixed;
DroppedDown = true;
Capture = true;
// fire OnLeave so grid knows we're done
base.OnLeave(EventArgs.Empty);
}
#endregion
//===========================================================================
#region ** event handlers
// close drop down when form deactivated
private void _form_Deactivate(object sender, EventArgs e)
{
((IWindowsFormsEditorService)this).CloseDropDown();
}
#endregion
//===========================================================================
#region ** IServiceProvider interface
object IServiceProvider.GetService(Type serviceType)
{
if (serviceType == typeof(IWindowsFormsEditorService))
return (IWindowsFormsEditorService)this;
return null;
}
#endregion
//===========================================================================
#region ** IWindowsFormsEditorService interface
void IWindowsFormsEditorService.DropDownControl(Control control)
{
// size form
_form.ClientSize = control.Size;
// calculate form location to avoid being off the screen
Point pt = new Point(_bounds.Right - control.Width, _bounds.Bottom);
Rectangle rc = Screen.GetWorkingArea(this);
if (_bounds.Bottom + control.Height > rc.Bottom) // check bottom
pt.Y = _bounds.Top - _form.Height;
if (pt.Y < 0) pt.Y = 0; // check top
if (_bounds.X + control.Width > rc.Right) // check right
pt.X = rc.Right - _form.Width;
if (pt.X < 0) pt.X = 0; // check left
// position form
_form.Location = pt;
// add control to form and show it
_form.Controls.Add(control);
_form.Show();
// readjust form size (seems redundant, but isn't...)
_form.ClientSize = control.Size;
// wait until user makes a selection
while (control.Visible)
{
Application.DoEvents();
MsgWaitForMultipleObjects(1, IntPtr.Zero, 0, 5, 255);
}
// done
_form.Hide();
_form.Controls.Clear();
}
void IWindowsFormsEditorService.CloseDropDown()
{
_form.Hide();
}
DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog)
{
// support modal editors
return dialog.ShowDialog();
}
#endregion
//===========================================================================
#region ** dll imports
[System.Runtime.InteropServices.DllImport("User32")]
private static extern int MsgWaitForMultipleObjects(
int nCount, IntPtr pHandles, short bWaitAll, int dwMilliseconds, int dwWakeMask);
#endregion
}
}
调用的代码如下:
private void Form2_Load(object sender, EventArgs e)
{
for (int i = fgData.Rows.Fixed; i < fgData.Rows.Count; i++)
{
fgData.Rows[i].Height = 80;
}
for (int i = fgData.Cols.Fixed; i < fgData.Cols.Count; i++)
{
fgData.Cols[i].Width = 100;
}
C1FlexGrid _flex = new C1FlexGrid();
CellStyle cs = fgData.Styles.Add("custom");
_flex.Cols.Count = 1;
_flex.Cols.Fixed = 0;
_flex.Cols.MinSize = 100;
_flex.Rows.Count = 0;
_flex.Rows.Fixed = 0;
_flex.Rows.MinSize = 80;
_flex.AllowEditing = false;
for (int i = 0; i < imageList2.Images.Count; i++)
{
_flex.Rows.Add();
_flex.SetCellImage(_flex.Rows.Count - 1, 0, imageList2.Images[i]);
}
Console.WriteLine("rows={0},cols={1}", _flex.Rows.Count,_flex.Cols.Count);
ImageCombo ic = new ImageCombo(_flex);
cs.Editor = new ImageComboControl(ic, false);
fgData.SetCellStyle(1, 1, cs);
}