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();

效果就是这样的了

需要引用的一个DLL去我的上一个文章里面下载吧

时间: 2024-12-10 08:57:04

c# 自定义多选下拉列表2的相关文章

Flex4 双选下拉列表的实现(源代码)

本文属原创文章,如需转载,请注明出处,谢谢 企业应用中少不了双选下拉列表控件,但几乎都没有独立的控件,Flex在这上面得天独厚,ArrayCollection的过滤功能使得我们只需要一个数据源就可以将数据展示在两个下拉列表中 有呆毛才有真相: 为了实现上图我想要的控件效果,我需要先明确我希望得到的控件该怎么用: <ui:DDList width="400" height="300" labelField="label" labelFunct

javascript操作多选下拉列表

闲来无事,把javascript操作多选下拉列表有关的操作知识复习了一遍,代码附上 <%-- Created by IntelliJ IDEA. User: Administrator Date: 2014/8/9 Time: 18:05 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" lang

自定义复选框样式及全选操作

自定义复选框样式 复选框结构 input框去其样式宽高为0;定位到父盒子内,我们需用其:checked 属性 下面的span为自定义样式,定位到父盒子内 . 效果展示 js 代码 模拟复选框样式 $(".ck_MN").click(function(){ var ck_Inp = $(this).siblings(".ckIpt"); var Ck_box = $(this).parents(".Ckbox"); if(ck_Inp.prop(&

IOS开发—自定义多选相册

自定义多选相册 主要思路 导入AssetsLibrary框架 从资源库中获取获取资源组[0],过滤[1]照片后在列表中显示组. 点击资源组进入对应的相册中,获取组中的所有照片资源[2] [0]获取资源组 [_assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if (group) { [_assetsArray addObject:grou

自定义SWT控件二之自定义多选下拉框

2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import or

小程序自定义多选按钮 给后台传值方法

小程序自定义多选按钮 1.html部分 <checkbox-group bindchange="checkboxChange" class = "flex"> <label class="checkbox {{item.checked?'active':''}}" wx:for="{{items}}" bindtap="addclass" data-index="{{index}

微信小程序-自定义复选框

功能: 1.需要多选复选框,并且可以上拉滚动: 2.需要通过名称手写字母排序的,并且可以上拉滚动: 常规的小程序自带的原生picker无法满足我们的要求,因此一些特殊效果需要我们自定义来实现,废话不多说,我们直接看效果: index.wxml布局 <view class="container"> <view class='class bgFFF' bindtap='isDep'> <view class='class-text'> <text

bootstrap-select多选下拉列表插件使用小记

下载插件 插件地址:http://silviomoreto.github.io/bootstrap-select/ 下载好后引用css和js文件 <!-- 因为是jquery插件,所以引用前先引用jquery--> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <!-- bo

iOS开发系列之常用自定义控件开发集—自定义多选按钮控件开发

在实际开发中很多时候我们需要用到下拉列表,我们下面来实现一下. WHC_ComboBox.h头文件如下: // // WHC_ComboBox.h // WHC_ComboBox // // Created by 吴海超 on 15/4/2. // // #import <UIKit/UIKit.h> @interface WHC_ComboBox : UIButton @end WHC_ComboBox.m源文件如下: // // WHC_ComboBox.m // WHC_ComboBox