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去我的上一个文章里面下载吧
作者:冰封一夏
出处:http://www.cnblogs.com/bfyx/
HZHControls官网:http://www.hzhcontrols.cn
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git