c# 自定义多选下拉列表2

以下为工作中遇到的,备注一下

先需要几个辅助类

  1 #region GripBounds
  2 
  3 using System.Drawing;
  4 internal struct GripBounds
  5 {
  6     private const int GripSize = 6;
  7     private const int CornerGripSize = GripSize << 1;
  8 
  9     public GripBounds(Rectangle clientRectangle)
 10     {
 11         this.clientRectangle = clientRectangle;
 12     }
 13 
 14     private Rectangle clientRectangle;
 15     public Rectangle ClientRectangle
 16     {
 17         get { return clientRectangle; }
 18         //set { clientRectangle = value; }
 19     }
 20 
 21     public Rectangle Bottom
 22     {
 23         get
 24         {
 25             Rectangle rect = ClientRectangle;
 26             rect.Y = rect.Bottom - GripSize + 1;
 27             rect.Height = GripSize;
 28             return rect;
 29         }
 30     }
 31 
 32     public Rectangle BottomRight
 33     {
 34         get
 35         {
 36             Rectangle rect = ClientRectangle;
 37             rect.Y = rect.Bottom - CornerGripSize + 1;
 38             rect.Height = CornerGripSize;
 39             rect.X = rect.Width - CornerGripSize + 1;
 40             rect.Width = CornerGripSize;
 41             return rect;
 42         }
 43     }
 44 
 45     public Rectangle Top
 46     {
 47         get
 48         {
 49             Rectangle rect = ClientRectangle;
 50             rect.Height = GripSize;
 51             return rect;
 52         }
 53     }
 54 
 55     public Rectangle TopRight
 56     {
 57         get
 58         {
 59             Rectangle rect = ClientRectangle;
 60             rect.Height = CornerGripSize;
 61             rect.X = rect.Width - CornerGripSize + 1;
 62             rect.Width = CornerGripSize;
 63             return rect;
 64         }
 65     }
 66 
 67     public Rectangle Left
 68     {
 69         get
 70         {
 71             Rectangle rect = ClientRectangle;
 72             rect.Width = GripSize;
 73             return rect;
 74         }
 75     }
 76 
 77     public Rectangle BottomLeft
 78     {
 79         get
 80         {
 81             Rectangle rect = ClientRectangle;
 82             rect.Width = CornerGripSize;
 83             rect.Y = rect.Height - CornerGripSize + 1;
 84             rect.Height = CornerGripSize;
 85             return rect;
 86         }
 87     }
 88 
 89     public Rectangle Right
 90     {
 91         get
 92         {
 93             Rectangle rect = ClientRectangle;
 94             rect.X = rect.Right - GripSize + 1;
 95             rect.Width = GripSize;
 96             return rect;
 97         }
 98     }
 99 
100     public Rectangle TopLeft
101     {
102         get
103         {
104             Rectangle rect = ClientRectangle;
105             rect.Width = CornerGripSize;
106             rect.Height = CornerGripSize;
107             return rect;
108         }
109     }
110 }
111 
112 #endregion
  1 #region UnsafeMethods
  2 
  3 using System;
  4 using System.Drawing;
  5 using System.Runtime.InteropServices;
  6 internal class UnsafeMethods
  7 {
  8     public static readonly IntPtr TRUE = new IntPtr(1);
  9     public static readonly IntPtr FALSE = new IntPtr(0);
 10 
 11     public const int WM_LBUTTONDOWN = 0x201;
 12     public const int WM_RBUTTONDOWN = 0x204;
 13     public const int WM_MBUTTONDOWN = 0x207;
 14     public const int WM_NCLBUTTONDOWN = 0x0A1;
 15     public const int WM_NCRBUTTONDOWN = 0x0A4;
 16     public const int WM_NCMBUTTONDOWN = 0x0A7;
 17     public const int WM_NCCALCSIZE = 0x0083;
 18     public const int WM_NCHITTEST = 0x0084;
 19     public const int WM_NCPAINT = 0x0085;
 20     public const int WM_NCACTIVATE = 0x0086;
 21     public const int WM_MOUSELEAVE = 0x02A3;
 22     public const int WS_EX_NOACTIVATE = 0x08000000;
 23     public const int HTTRANSPARENT = -1;
 24     public const int HTLEFT = 10;
 25     public const int HTRIGHT = 11;
 26     public const int HTTOP = 12;
 27     public const int HTTOPLEFT = 13;
 28     public const int HTTOPRIGHT = 14;
 29     public const int HTBOTTOM = 15;
 30     public const int HTBOTTOMLEFT = 16;
 31     public const int HTBOTTOMRIGHT = 17;
 32     public const int WM_USER = 0x0400;
 33     public const int WM_REFLECT = WM_USER + 0x1C00;
 34     public const int WM_COMMAND = 0x0111;
 35     public const int CBN_DROPDOWN = 7;
 36     public const int WM_GETMINMAXINFO = 0x0024;
 37 
 38     public enum TrackerEventFlags : uint
 39     {
 40         TME_HOVER = 0x00000001,
 41         TME_LEAVE = 0x00000002,
 42         TME_QUERY = 0x40000000,
 43         TME_CANCEL = 0x80000000
 44     }
 45 
 46     [DllImport("user32.dll")]
 47     public static extern IntPtr GetWindowDC(IntPtr hWnd);
 48 
 49     [DllImport("user32.dll")]
 50     public static extern int ReleaseDC(IntPtr hwnd, IntPtr hDC);
 51 
 52     [DllImport("user32")]
 53     public static extern bool TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack);
 54 
 55     [DllImport("user32.dll")]
 56     public static extern bool SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
 57 
 58     internal static int HIWORD(int n)
 59     {
 60         return (n >> 16) & 0xffff;
 61     }
 62 
 63     internal static int HIWORD(IntPtr n)
 64     {
 65         return HIWORD(unchecked((int)(long)n));
 66     }
 67 
 68     internal static int LOWORD(int n)
 69     {
 70         return n & 0xffff;
 71     }
 72 
 73     internal static int LOWORD(IntPtr n)
 74     {
 75         return LOWORD(unchecked((int)(long)n));
 76     }
 77 
 78     [StructLayout(LayoutKind.Sequential)]
 79     internal struct TRACKMOUSEEVENT
 80     {
 81         public uint cbSize;
 82         public uint dwFlags;
 83         public IntPtr hwndTrack;
 84         public uint dwHoverTime;
 85     }
 86 
 87     [StructLayout(LayoutKind.Sequential)]
 88     internal struct MINMAXINFO
 89     {
 90         public Point reserved;
 91         public Size maxSize;
 92         public Point maxPosition;
 93         public Size minTrackSize;
 94         public Size maxTrackSize;
 95     }
 96 
 97     #region RECT structure
 98 
 99     [StructLayout(LayoutKind.Sequential)]
100     internal struct RECT
101     {
102         public int left;
103         public int top;
104         public int right;
105         public int bottom;
106 
107         public RECT(int left, int top, int right, int bottom)
108         {
109             this.left = left;
110             this.top = top;
111             this.right = right;
112             this.bottom = bottom;
113         }
114 
115         public Rectangle Rect
116         {
117             get
118             {
119                 return new Rectangle(
120                     this.left,
121                     this.top,
122                     this.right - this.left,
123                     this.bottom - this.top);
124             }
125         }
126 
127         public static RECT FromXYWH(int x, int y, int width, int height)
128         {
129             return new RECT(x,
130                             y,
131                             x + width,
132                             y + height);
133         }
134 
135         public static RECT FromRectangle(Rectangle rect)
136         {
137             return new RECT(rect.Left,
138                              rect.Top,
139                              rect.Right,
140                              rect.Bottom);
141         }
142     }
143 
144     #endregion RECT structure
145 
146     #region WINDOWPOS
147 
148     [StructLayout(LayoutKind.Sequential)]
149     internal struct WINDOWPOS
150     {
151         internal IntPtr hwnd;
152         internal IntPtr hWndInsertAfter;
153         internal int x;
154         internal int y;
155         internal int cx;
156         internal int cy;
157         internal uint flags;
158     }
159     #endregion
160 
161     #region NCCALCSIZE_PARAMS
162     //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowstructures/nccalcsize_params.asp
163     [StructLayout(LayoutKind.Sequential)]
164     public struct NCCALCSIZE_PARAMS
165     {
166         /// <summary>
167         /// Contains the new coordinates of a window that has been moved or resized, that is, it is the proposed new window coordinates.
168         /// </summary>
169         public RECT rectProposed;
170         /// <summary>
171         /// Contains the coordinates of the window before it was moved or resized.
172         /// </summary>
173         public RECT rectBeforeMove;
174         /// <summary>
175         /// Contains the coordinates of the window's client area before the window was moved or resized.
176         /// </summary>
177         public RECT rectClientBeforeMove;
178         /// <summary>
179         /// Pointer to a WINDOWPOS structure that contains the size and position values specified in the operation that moved or resized the window.
180         /// </summary>
181         public WINDOWPOS lpPos;
182     }
183 
184     #endregion
185 }
186 
187 #endregion
  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Drawing.Drawing2D;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.Security.Permissions;
 10 using System.Runtime.InteropServices;
 11 using VS = System.Windows.Forms.VisualStyles;
 12 
 13 /*
 14 <li>Base class for custom tooltips.</li>
 15 <li>Office-2007-like tooltip class.</li>
 16 */
 17 namespace ZhuoYueE.Bpc.Controls
 18 {
 19     /// <summary>
 20     /// Represents a pop-up window.
 21     /// </summary>
 22     [ToolboxItem(false)]
 23     public partial class PopupForm : ToolStripDropDown
 24     {
 25         #region " Fields & Properties "
 26 
 27         private Control content;
 28         /// <summary>
 29         /// Gets the content of the pop-up.
 30         /// </summary>
 31         public Control Content
 32         {
 33             get { return content; }
 34         }
 35 
 36         private bool fade;
 37         /// <summary>
 38         /// Gets a value indicating whether the <see cref="PopupControl.Popup"/> uses the fade effect.
 39         /// </summary>
 40         /// <value><c>true</c> if pop-up uses the fade effect; otherwise, <c>false</c>.</value>
 41         /// <remarks>To use the fade effect, the FocusOnOpen property also has to be set to <c>true</c>.</remarks>
 42         public bool UseFadeEffect
 43         {
 44             get { return fade; }
 45             set
 46             {
 47                 if (fade == value) return;
 48                 fade = value;
 49             }
 50         }
 51 
 52         private bool focusOnOpen = true;
 53         /// <summary>
 54         /// Gets or sets a value indicating whether the content should receive the focus after the pop-up has been opened.
 55         /// </summary>
 56         /// <value><c>true</c> if the content should be focused after the pop-up has been opened; otherwise, <c>false</c>.</value>
 57         /// <remarks>If the FocusOnOpen property is set to <c>false</c>, then pop-up cannot use the fade effect.</remarks>
 58         public bool FocusOnOpen
 59         {
 60             get { return focusOnOpen; }
 61             set { focusOnOpen = value; }
 62         }
 63 
 64         private bool acceptAlt = true;
 65         /// <summary>
 66         /// Gets or sets a value indicating whether presing the alt key should close the pop-up.
 67         /// </summary>
 68         /// <value><c>true</c> if presing the alt key does not close the pop-up; otherwise, <c>false</c>.</value>
 69         public bool AcceptAlt
 70         {
 71             get { return acceptAlt; }
 72             set { acceptAlt = value; }
 73         }
 74 
 75         private PopupForm ownerPopup;
 76         private PopupForm childPopup;
 77 
 78         private bool _resizable;
 79         private bool resizable;
 80         /// <summary>
 81         /// Gets or sets a value indicating whether the <see cref="PopupControl.Popup" /> is resizable.
 82         /// </summary>
 83         /// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
 84         public bool Resizable
 85         {
 86             get { return resizable && _resizable; }
 87             set { resizable = value; }
 88         }
 89 
 90         private ToolStripControlHost host;
 91 
 92         private Size minSize;
 93         /// <summary>
 94         /// Gets or sets a minimum size of the pop-up.
 95         /// </summary>
 96         /// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
 97         public new Size MinimumSize
 98         {
 99             get { return minSize; }
100             set { minSize = value; }
101         }
102 
103         private Size maxSize;
104         /// <summary>
105         /// Gets or sets a maximum size of the pop-up.
106         /// </summary>
107         /// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
108         public new Size MaximumSize
109         {
110             get { return maxSize; }
111             set { maxSize = value; }
112         }
113 
114         private bool _isOpen;
115 
116         public bool IsOpen
117         {
118             get { return _isOpen; }
119         }
120 
121         /// <summary>
122         /// Gets parameters of a new window.
123         /// </summary>
124         /// <returns>An object of type <see cref="T:System.Windows.Forms.CreateParams" /> used when creating a new window.</returns>
125         protected override CreateParams CreateParams
126         {
127             [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
128             get
129             {
130                 CreateParams cp = base.CreateParams;
131                 cp.ExStyle |= UnsafeMethods.WS_EX_NOACTIVATE;
132                 return cp;
133             }
134         }
135 
136         #endregion
137 
138         #region " Constructors "
139 
140         /// <summary>
141         /// Initializes a new instance of the <see cref="PopupControl.Popup"/> class.
142         /// </summary>
143         /// <param name="content">The content of the pop-up.</param>
144         /// <remarks>
145         /// Pop-up will be disposed immediately after disposion of the content control.
146         /// </remarks>
147         /// <exception cref="T:System.ArgumentNullException"><paramref name="content" /> is <code>null</code>.</exception>
148         public PopupForm(Control content)
149         {
150             if (content == null)
151             {
152                 throw new ArgumentNullException("content");
153             }
154             this.content = content;
155             this.fade = SystemInformation.IsMenuAnimationEnabled && SystemInformation.IsMenuFadeEnabled;
156             this._resizable = true;
157             AutoSize = false;
158             DoubleBuffered = true;
159             ResizeRedraw = true;
160             host = new ToolStripControlHost(content);
161             Padding = Margin = host.Padding = host.Margin = Padding.Empty;
162             MinimumSize = content.MinimumSize;
163             content.MinimumSize = content.Size;
164             MaximumSize = content.MaximumSize;
165             content.MaximumSize = content.Size;
166             Size = content.Size;
167             content.Location = Point.Empty;
168             Items.Add(host);
169             content.Disposed += delegate(object sender, EventArgs e)
170             {
171                 content = null;
172                 Dispose(true);
173             };
174             content.RegionChanged += delegate(object sender, EventArgs e)
175             {
176                 UpdateRegion();
177             };
178             content.Paint += delegate(object sender, PaintEventArgs e)
179             {
180                 PaintSizeGrip(e);
181             };
182             UpdateRegion();
183         }
184 
185         #endregion
186 
187         #region " Methods "
188 
189         /// <summary>
190         /// Processes a dialog box key.
191         /// </summary>
192         /// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys" /> values that represents the key to process.</param>
193         /// <returns>
194         /// true if the key was processed by the control; otherwise, false.
195         /// </returns>
196         protected override bool ProcessDialogKey(Keys keyData)
197         {
198             if (acceptAlt && ((keyData & Keys.Alt) == Keys.Alt))
199             {
200                 if ((keyData & Keys.F4) != Keys.F4)
201                 {
202                     return false;
203                 }
204                 else
205                 {
206                     this.Close();
207                 }
208             }
209             return base.ProcessDialogKey(keyData);
210         }
211 
212         /// <summary>
213         /// Updates the pop-up region.
214         /// </summary>
215         protected void UpdateRegion()
216         {
217             if (this.Region != null)
218             {
219                 this.Region.Dispose();
220                 this.Region = null;
221             }
222             if (content.Region != null)
223             {
224                 this.Region = content.Region.Clone();
225             }
226         }
227 
228         /// <summary>
229         /// Shows the pop-up window below the specified control.
230         /// </summary>
231         /// <param name="control">The control below which the pop-up will be shown.</param>
232         /// <remarks>
233         /// When there is no space below the specified control, the pop-up control is shown above it.
234         /// </remarks>
235         /// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
236         public void Show(Control control)
237         {
238             Show(control, control.ClientRectangle);
239         }
240 
241         public void Show(Control control, bool center)
242         {
243             Show(control, control.ClientRectangle, center);
244         }
245 
246         /// <summary>
247         /// Shows the pop-up window below the specified area of the specified control.
248         /// </summary>
249         /// <param name="control">The control used to compute screen location of specified area.</param>
250         /// <param name="area">The area of control below which the pop-up will be shown.</param>
251         /// <remarks>
252         /// When there is no space below specified area, the pop-up control is shown above it.
253         /// </remarks>
254         /// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
255         public void Show(Control control, Rectangle area)
256         {
257             Show(control, area, false);
258         }
259 
260         public void Show(Control control, Rectangle area, bool center)
261         {
262             if (control == null)
263             {
264                 throw new ArgumentNullException("control");
265             }
266             SetOwnerItem(control);
267             resizableTop = resizableLeft = false;
268             Point location = control.PointToScreen(new Point(area.Left, area.Top + area.Height));
269             Rectangle screen = Screen.FromControl(control).WorkingArea;
270             if (center)
271             {
272                 if (location.X + (area.Width + Size.Width) / 2 > screen.Right)
273                 {
274                     resizableLeft = true;
275                     location.X = screen.Right - Size.Width;
276                 }
277                 else
278                 {
279                     resizableLeft = true;
280                     location.X = location.X - (Size.Width - area.Width) / 2;
281                 }
282             }
283             else
284             {
285                 if (location.X + Size.Width > (screen.Left + screen.Width))
286                 {
287                     resizableLeft = true;
288                     location.X = (screen.Left + screen.Width) - Size.Width;
289                 }
290             }
291 
292             if (location.Y + Size.Height > (screen.Top + screen.Height))
293             {
294                 resizableTop = true;
295                 location.Y -= Size.Height + area.Height;
296             }
297             location = control.PointToClient(location);
298             Show(control, location, ToolStripDropDownDirection.BelowRight);
299         }
300 
301         private const int frames = 5;
302         private const int totalduration = 100;
303         private const int frameduration = totalduration / frames;
304         /// <summary>
305         /// Adjusts the size of the owner <see cref="T:System.Windows.Forms.ToolStrip" /> to accommodate the <see cref="T:System.Windows.Forms.ToolStripDropDown" /> if the owner <see cref="T:System.Windows.Forms.ToolStrip" /> is currently displayed, or clears and resets active <see cref="T:System.Windows.Forms.ToolStripDropDown" /> child controls of the <see cref="T:System.Windows.Forms.ToolStrip" /> if the <see cref="T:System.Windows.Forms.ToolStrip" /> is not currently displayed.
306         /// </summary>
307         /// <param name="visible">true if the owner <see cref="T:System.Windows.Forms.ToolStrip" /> is currently displayed; otherwise, false.</param>
308         protected override void SetVisibleCore(bool visible)
309         {
310             double opacity = Opacity;
311             if (visible && fade && focusOnOpen) Opacity = 0;
312             base.SetVisibleCore(visible);
313             if (!visible || !fade || !focusOnOpen) return;
314             for (int i = 1; i <= frames; i++)
315             {
316                 if (i > 1)
317                 {
318                     System.Threading.Thread.Sleep(frameduration);
319                 }
320                 Opacity = opacity * (double)i / (double)frames;
321             }
322             Opacity = opacity;
323         }
324 
325         private bool resizableTop;
326         private bool resizableLeft;
327 
328         private void SetOwnerItem(Control control)
329         {
330             if (control == null)
331             {
332                 return;
333             }
334             if (control is PopupForm)
335             {
336                 PopupForm popupControl = control as PopupForm;
337                 ownerPopup = popupControl;
338                 ownerPopup.childPopup = this;
339                 OwnerItem = popupControl.Items[0];
340                 return;
341             }
342             if (control.Parent != null)
343             {
344                 SetOwnerItem(control.Parent);
345             }
346         }
347 
348         /// <summary>
349         /// Raises the <see cref="E:System.Windows.Forms.Control.SizeChanged" /> event.
350         /// </summary>
351         /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
352         protected override void OnSizeChanged(EventArgs e)
353         {
354             content.MinimumSize = Size;
355             content.MaximumSize = Size;
356             content.Size = Size;
357             content.Location = Point.Empty;
358             base.OnSizeChanged(e);
359         }
360 
361         /// <summary>
362         /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opening" /> event.
363         /// </summary>
364         /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs" /> that contains the event data.</param>
365         protected override void OnOpening(CancelEventArgs e)
366         {
367             if (content.IsDisposed || content.Disposing)
368             {
369                 e.Cancel = true;
370                 return;
371             }
372             UpdateRegion();
373             base.OnOpening(e);
374         }
375 
376         /// <summary>
377         /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opened" /> event.
378         /// </summary>
379         /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
380         protected override void OnOpened(EventArgs e)
381         {
382             if (ownerPopup != null)
383             {
384                 ownerPopup._resizable = false;
385             }
386             if (focusOnOpen)
387             {
388                 content.Focus();
389             }
390             _isOpen = true;
391             base.OnOpened(e);
392         }
393 
394         /// <summary>
395         /// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Closed"/> event.
396         /// </summary>
397         /// <param name="e">A <see cref="T:System.Windows.Forms.ToolStripDropDownClosedEventArgs"/> that contains the event data.</param>
398         protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
399         {
400             if (ownerPopup != null)
401             {
402                 ownerPopup._resizable = true;
403             }
404             _isOpen = false;
405             base.OnClosed(e);
406         }
407 
408         #endregion
409 
410         #region " Resizing Support "
411 
412         /// <summary>
413         /// Processes Windows messages.
414         /// </summary>
415         /// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message" /> to process.</param>
416         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
417         protected override void WndProc(ref Message m)
418         {
419             if (InternalProcessResizing(ref m, false))
420             {
421                 return;
422             }
423             base.WndProc(ref m);
424         }
425 
426         /// <summary>
427         /// Processes the resizing messages.
428         /// </summary>
429         /// <param name="m">The message.</param>
430         /// <returns>true, if the WndProc method from the base class shouldn't be invoked.</returns>
431         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
432         public bool ProcessResizing(ref Message m)
433         {
434             return InternalProcessResizing(ref m, true);
435         }
436 
437         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
438         private bool InternalProcessResizing(ref Message m, bool contentControl)
439         {
440             if (m.Msg == UnsafeMethods.WM_NCACTIVATE && m.WParam != IntPtr.Zero && childPopup != null && childPopup.Visible)
441             {
442                 childPopup.Hide();
443             }
444             if (!Resizable)
445             {
446                 return false;
447             }
448             if (m.Msg == UnsafeMethods.WM_NCHITTEST)
449             {
450                 return OnNcHitTest(ref m, contentControl);
451             }
452             else if (m.Msg == UnsafeMethods.WM_GETMINMAXINFO)
453             {
454                 return OnGetMinMaxInfo(ref m);
455             }
456             return false;
457         }
458 
459         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
460         private bool OnGetMinMaxInfo(ref Message m)
461         {
462             UnsafeMethods.MINMAXINFO minmax = (UnsafeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(UnsafeMethods.MINMAXINFO));
463             minmax.maxTrackSize = this.MaximumSize;
464             minmax.minTrackSize = this.MinimumSize;
465             Marshal.StructureToPtr(minmax, m.LParam, false);
466             return true;
467         }
468 
469         private bool OnNcHitTest(ref Message m, bool contentControl)
470         {
471             int x = UnsafeMethods.LOWORD(m.LParam);
472             int y = UnsafeMethods.HIWORD(m.LParam);
473             Point clientLocation = PointToClient(new Point(x, y));
474 
475             GripBounds gripBouns = new GripBounds(contentControl ? content.ClientRectangle : ClientRectangle);
476             IntPtr transparent = new IntPtr(UnsafeMethods.HTTRANSPARENT);
477 
478             if (resizableTop)
479             {
480                 if (resizableLeft && gripBouns.TopLeft.Contains(clientLocation))
481                 {
482                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOPLEFT;
483                     return true;
484                 }
485                 if (!resizableLeft && gripBouns.TopRight.Contains(clientLocation))
486                 {
487                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOPRIGHT;
488                     return true;
489                 }
490                 if (gripBouns.Top.Contains(clientLocation))
491                 {
492                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOP;
493                     return true;
494                 }
495             }
496             else
497             {
498                 if (resizableLeft && gripBouns.BottomLeft.Contains(clientLocation))
499                 {
500                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOMLEFT;
501                     return true;
502                 }
503                 if (!resizableLeft && gripBouns.BottomRight.Contains(clientLocation))
504                 {
505                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOMRIGHT;
506                     return true;
507                 }
508                 if (gripBouns.Bottom.Contains(clientLocation))
509                 {
510                     m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOM;
511                     return true;
512                 }
513             }
514             if (resizableLeft && gripBouns.Left.Contains(clientLocation))
515             {
516                 m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTLEFT;
517                 return true;
518             }
519             if (!resizableLeft && gripBouns.Right.Contains(clientLocation))
520             {
521                 m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTRIGHT;
522                 return true;
523             }
524             return false;
525         }
526 
527         private VS.VisualStyleRenderer sizeGripRenderer;
528         /// <summary>
529         /// Paints the sizing grip.
530         /// </summary>
531         /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
532         public void PaintSizeGrip(PaintEventArgs e)
533         {
534             if (e == null || e.Graphics == null || !resizable)
535             {
536                 return;
537             }
538             Size clientSize = content.ClientSize;
539             using (Bitmap gripImage = new Bitmap(0x10, 0x10))
540             {
541                 using (Graphics g = Graphics.FromImage(gripImage))
542                 {
543                     if (Application.RenderWithVisualStyles)
544                     {
545                         if (this.sizeGripRenderer == null)
546                         {
547                             this.sizeGripRenderer = new VS.VisualStyleRenderer(VS.VisualStyleElement.Status.Gripper.Normal);
548                         }
549                         this.sizeGripRenderer.DrawBackground(g, new Rectangle(0, 0, 0x10, 0x10));
550                     }
551                     else
552                     {
553                         ControlPaint.DrawSizeGrip(g, content.BackColor, 0, 0, 0x10, 0x10);
554                     }
555                 }
556                 GraphicsState gs = e.Graphics.Save();
557                 e.Graphics.ResetTransform();
558                 if (resizableTop)
559                 {
560                     if (resizableLeft)
561                     {
562                         e.Graphics.RotateTransform(180);
563                         e.Graphics.TranslateTransform(-clientSize.Width, -clientSize.Height);
564                     }
565                     else
566                     {
567                         e.Graphics.ScaleTransform(1, -1);
568                         e.Graphics.TranslateTransform(0, -clientSize.Height);
569                     }
570                 }
571                 else if (resizableLeft)
572                 {
573                     e.Graphics.ScaleTransform(-1, 1);
574                     e.Graphics.TranslateTransform(-clientSize.Width, 0);
575                 }
576                 e.Graphics.DrawImage(gripImage, clientSize.Width - 0x10, clientSize.Height - 0x10 + 1, 0x10, 0x10);
577                 e.Graphics.Restore(gs);
578             }
579         }
580 
581         #endregion
582     }
583 }

然后新建一个自定义控件,代码如下

  1 :
  2 using System;
  3 using System.Collections.Generic;
  4 using System.ComponentModel;
  5 using System.Drawing;
  6 using System.Data;
  7 using System.Linq;
  8 using System.Text;
  9 using System.Windows.Forms;
 10 using System.Collections;
 11 using System.Reflection;
 12 using Newtonsoft.Json.Linq;
 13 
 14 namespace Controls
 15 {
 16 
 17     /// <summary>
 18     /// 功能描述:自定义多选下拉框
 19     /// 作  者:huangzh
 20     /// 创建日期:2016-01-04 11:57:13
 21     /// 任务编号:
 22     /// </summary>
 23     public class ComboBoxEx : ComboBox
 24     {
 25         PopupForm frmhost;
 26         TreeView lst = new TreeView();
 27         /// <summary>
 28         /// 功能描述:构造方法
 29         /// 作  者:huangzh
 30         /// 创建日期:2016-01-04 11:57:27
 31         /// 任务编号:
 32         /// </summary>
 33         public ComboBoxEx()
 34         {
 35             this.DrawMode = DrawMode.OwnerDrawFixed;//只有设置这个属性为OwnerDrawFixed才可能让重画起作用   
 36 
 37             lst.Width = ListWidth == 0 ? this.Width : ListWidth;
 38             lst.Height = ListHeight == 0 ? 300 : ListHeight;
 39             lst.CheckBoxes = true;
 40             lst.ShowLines = false;
 41             lst.ShowPlusMinus = false;
 42             lst.ShowRootLines = false;
 43             lst.KeyUp += new KeyEventHandler(lst_KeyUp);
 44             lst.AfterCheck += new TreeViewEventHandler(lst_AfterCheck);
 45             this.DropDownHeight = 1;
 46             frmhost = new PopupForm(lst);
 47             //frmhost.Closed += new ToolStripDropDownClosedEventHandler(frmhost_Closed);
 48             //frmhost.Opened += new EventHandler(frmhost_Opened);
 49         }
 50 
 51         void lst_KeyUp(object sender, KeyEventArgs e)
 52         {
 53             OnKeyUp(e);
 54         }
 55 
 56         void lst_AfterCheck(object sender, TreeViewEventArgs e)
 57         {
 58             if (e.Node.Checked)
 59             {
 60                 if (Text != "")
 61                 {
 62                     Text += ",";
 63                 }
 64                 Text += e.Node.Tag.ToString();
 65             }
 66             else
 67             {
 68                 string strValue = e.Node.Tag.ToString().Trim();
 69                 if (Text != "")
 70                 {
 71                     List<string> strs = Text.Split(',').ToList();
 72                     strs.Remove("");
 73                     if (strs.Contains(strValue))
 74                     {
 75                         strs.Remove(strValue);
 76                         Text = string.Join(",", strs);
 77                     }
 78                 }
 79             }
 80         }
 81 
 82         void frmhost_Opened(object sender, EventArgs e)
 83         {
 84 
 85         }
 86 
 87         void frmhost_Closed(object sender, ToolStripDropDownClosedEventArgs e)
 88         {
 89 
 90         }
 91 
 92         #region Property
 93         /// <summary>
 94         /// 选中项
 95         /// </summary>
 96         [Description("选定项的值"), Category("Data")]
 97         public List<TreeNode> SelectedItems
 98         {
 99             get
100             {
101                 List<TreeNode> lsttn = new List<TreeNode>();
102                 foreach (TreeNode tn in lst.Nodes)
103                 {
104                     if (tn.Checked)
105                     {
106                         lsttn.Add(tn);
107                     }
108                 }
109                 return lsttn;
110             }
111         }
112 
113         /// <summary>
114         /// 数据源
115         /// </summary>
116         [Description("数据源"), Category("Data")]
117         public new object DataSource
118         {
119             get;
120             set;
121         }
122         /// <summary>
123         /// 显示字段
124         /// </summary>
125         [Description("显示字段"), Category("Data")]
126         public string DisplayFiled
127         {
128             get;
129             set;
130         }
131         /// <summary>
132         /// 值字段
133         /// </summary>
134         [Description("值字段"), Category("Data")]
135         public string ValueFiled
136         {
137             get;
138             set;
139         }
140         /// <summary>
141         /// 列表高度
142         /// </summary>
143         [Description("列表高度"), Category("Data")]
144         public int ListHeight
145         {
146             get;
147             set;
148         }
149 
150         /// <summary>
151         /// 列表宽度
152         /// </summary>
153         [Description("列表宽度"), Category("Data")]
154         public int ListWidth
155         {
156             get;
157             set;
158         }
159         #endregion
160 
161         /// <summary>
162         /// 功能描述:绑定数据
163         /// 作  者:huangzh
164         /// 创建日期:2016-01-04 10:38:51
165         /// 任务编号:
166         /// </summary>
167         public void DataBind()
168         {
169             this.BeginUpdate();
170             if (DataSource != null)
171             {
172                 if (DataSource is IDataReader)
173                 {
174                     DataTable dataTable = new DataTable();
175                     dataTable.Load(DataSource as IDataReader);
176 
177                     DataBindToDataTable(dataTable);
178                 }
179                 else if (DataSource is DataView || DataSource is DataSet || DataSource is DataTable)
180                 {
181                     DataTable dataTable = null;
182 
183                     if (DataSource is DataView)
184                     {
185                         dataTable = ((DataView)DataSource).ToTable();
186                     }
187                     else if (DataSource is DataSet)
188                     {
189                         dataTable = ((DataSet)DataSource).Tables[0];
190                     }
191                     else
192                     {
193                         dataTable = ((DataTable)DataSource);
194                     }
195 
196                     DataBindToDataTable(dataTable);
197                 }
198                 else if (DataSource is IEnumerable)
199                 {
200                     DataBindToEnumerable((IEnumerable)DataSource);
201                 }
202                 else
203                 {
204                     throw new Exception("DataSource doesn't support data type: " + DataSource.GetType().ToString());
205                 }
206             }
207             else
208             {
209                 lst.Nodes.Clear();
210             }
211 
212             this.EndUpdate();
213         }
214 
215         /// <summary>
216         /// 功能描述:绑定Table数据
217         /// 作  者:huangzh
218         /// 创建日期:2016-01-04 10:47:27
219         /// 任务编号:
220         /// </summary>
221         /// <param name="dt">dt</param>
222         private void DataBindToDataTable(DataTable dt)
223         {
224             foreach (DataRow dr in dt.Rows)
225             {
226                 TreeNode tn = new TreeNode();
227                 if (!string.IsNullOrEmpty(DisplayFiled) && !string.IsNullOrEmpty(ValueFiled))
228                 {
229                     tn.Text = dr[DisplayFiled].ToString();
230                     tn.Tag = dr[ValueFiled].ToString();
231                 }
232                 else if (string.IsNullOrEmpty(ValueFiled))
233                 {
234                     tn.Text = dr[DisplayFiled].ToString();
235                     tn.Tag = dr[DisplayFiled].ToString();
236                 }
237                 else if (string.IsNullOrEmpty(DisplayFiled))
238                 {
239                     tn.Text = dr[ValueFiled].ToString();
240                     tn.Tag = dr[ValueFiled].ToString();
241                 }
242                 else
243                 {
244                     throw new Exception("ValueFiled和DisplayFiled至少保证有一项有值");
245                 }
246                 tn.ToolTipText = tn.Text;
247 
248                 tn.Checked = false;
249                 lst.Nodes.Add(tn);
250             }
251         }
252 
253         /// <summary>
254         /// 绑定到可枚举类型
255         /// </summary>
256         /// <param name="enumerable">可枚举类型</param>
257         private void DataBindToEnumerable(IEnumerable enumerable)
258         {
259             IEnumerator enumerator = enumerable.GetEnumerator();
260             while (enumerator.MoveNext())
261             {
262                 object currentObject = enumerator.Current;
263                 lst.Nodes.Add(CreateListItem(currentObject));
264             }
265         }
266 
267 
268         /// <summary>
269         /// 功能描述:获取一个CheckBox
270         /// 作  者:huangzh
271         /// 创建日期:2016-01-04 10:53:12
272         /// 任务编号:
273         /// </summary>
274         /// <param name="obj">obj</param>
275         /// <returns>返回值</returns>
276         private TreeNode CreateListItem(Object obj)
277         {
278             TreeNode item = new TreeNode();
279 
280             if (obj is string)
281             {
282                 item.Text = obj.ToString();
283                 item.Tag = obj.ToString();
284             }
285             else
286             {
287                 if (DisplayFiled != "")
288                 {
289                     item.Text = GetPropertyValue(obj, DisplayFiled);
290                 }
291                 else
292                 {
293                     item.Text = obj.ToString();
294                 }
295 
296                 if (ValueFiled != "")
297                 {
298                     item.Tag = GetPropertyValue(obj, ValueFiled);
299                 }
300                 else
301                 {
302                     item.Tag = obj.ToString();
303                 }
304             }
305             item.ToolTipText = item.Text;
306             return item;
307         }
308 
309         /// <summary>
310         /// 取得属性值
311         /// </summary>
312         /// <param name="obj"></param>
313         /// <param name="propertyName"></param>
314         private string GetPropertyValue(object obj, string propertyName)
315         {
316             object result = null;
317 
318             result = ObjectUtil.GetPropertyValue(obj, propertyName);
319             return result == null ? String.Empty : result.ToString();
320         }
321 
322         #region override
323 
324         /// <summary>
325         /// 功能描述:OnKeyUp
326         /// 作  者:huangzh
327         /// 创建日期:2016-01-04 11:58:33
328         /// 任务编号:
329         /// </summary>
330         /// <param name="e">e</param>
331         protected override void OnKeyUp(KeyEventArgs e)
332         {
333             base.OnKeyDown(e);
334             bool Pressed = (e.Control && ((e.KeyData & Keys.A) == Keys.A));
335             if (Pressed)
336             {
337                 this.Text = "";
338                 for (int i = 0; i < lst.Nodes.Count; i++)
339                 {
340                     lst.Nodes[i].Checked = true;
341                 }
342             }
343         }
344 
345         /// <summary>
346         /// 功能描述:OnDropDown
347         /// 作  者:huangzh
348         /// 创建日期:2016-01-04 11:58:53
349         /// 任务编号:
350         /// </summary>
351         /// <param name="e">e</param>
352         protected override void OnDropDown(EventArgs e)
353         {
354             this.DroppedDown = false;
355             string strValue = this.Text;
356             if (!string.IsNullOrEmpty(strValue))
357             {
358                 List<string> lstvalues = strValue.Split(',').ToList<string>();
359                 foreach (TreeNode tn in lst.Nodes)
360                 {
361                     if (tn.Checked && !lstvalues.Contains(tn.Tag.ToString()) && !string.IsNullOrEmpty(tn.Tag.ToString().Trim()))
362                     {
363                         tn.Checked = false;
364                     }
365                     else if (!tn.Checked && lstvalues.Contains(tn.Tag.ToString()) && !string.IsNullOrEmpty(tn.Tag.ToString().Trim()))
366                     {
367                         tn.Checked = true;
368                     }
369                 }
370             }
371             else
372             {
373                 foreach (TreeNode tn in lst.Nodes)
374                 {
375                     tn.Checked = false;
376                 }
377             }
378             frmhost.Show(this);
379         }
380         #endregion
381     }
382 
383 
384     /// <summary>
385     /// 对象帮助类
386     /// </summary>
387     public class ObjectUtil
388     {
389         /// <summary>
390         /// 获取对象的属性值
391         /// </summary>
392         /// <param name="obj">可能是DataRowView或一个对象</param>
393         /// <param name="propertyName">属性名</param>
394         /// <returns>属性值</returns>
395         public static object GetPropertyValue(object obj, string propertyName)
396         {
397             object result = null;
398 
399             try
400             {
401                 if (obj is DataRow)
402                 {
403                     result = (obj as DataRow)[propertyName];
404                 }
405                 else if (obj is DataRowView)
406                 {
407                     result = (obj as DataRowView)[propertyName];
408                 }
409                 else if (obj is JObject)
410                 {
411                     result = (obj as JObject).Value<JValue>(propertyName).Value; //.getValue(propertyName);
412                 }
413                 else
414                 {
415                     result = GetPropertyValueFormObject(obj, propertyName);
416                 }
417             }
418             catch (Exception)
419             {
420                 // 找不到此属性
421             }
422 
423             return result;
424         }
425 
426         /// <summary>
427         /// 获取对象的属性值
428         /// </summary>
429         /// <param name="obj">对象</param>
430         /// <param name="propertyName">属性名("Color"、"BodyStyle"或者"Info.UserName")</param>
431         /// <returns>属性值</returns>
432         private static object GetPropertyValueFormObject(object obj, string propertyName)
433         {
434             object rowObj = obj;
435             object result = null;
436 
437             if (propertyName.IndexOf(".") > 0)
438             {
439                 string[] properties = propertyName.Split('.');
440                 object tmpObj = rowObj;
441 
442                 for (int i = 0; i < properties.Length; i++)
443                 {
444                     PropertyInfo property = tmpObj.GetType().GetProperty(properties[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
445                     if (property != null)
446                     {
447                         tmpObj = property.GetValue(tmpObj, null);
448                     }
449                 }
450 
451                 result = tmpObj;
452             }
453             else
454             {
455                 PropertyInfo property = rowObj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
456                 if (property != null)
457                 {
458                     result = property.GetValue(rowObj, null);
459                 }
460             }
461 
462             return result;
463         }
464     }
465 }

然后就是使用了,直接拖一个到界面上,然后设置值就可以了

ListHeight,ListWidth 这两个属性一定要修改下的哦

然后就是绑定数据源

  var varSourceFrom = from p in lstEnumEnitty
                                    where p.Type == "source"
                                    select p;
                cboSourceFromType.DataSource = varSourceFrom;
                cboSourceFromType.DisplayFiled = "Name";
                cboSourceFromType.ValueFiled = "Code";
                cboSourceFromType.DataBind();

效果就是这样的了

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券