SkinNumericUpDown.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. using LYFZ.OtherExpansion.Win32;
  2. using LYFZ.OtherExpansion.Win32.Struct;
  3. using System;
  4. using System.ComponentModel;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.Windows.Forms;
  8. namespace LYFZ.OtherExpansion.SkinControl
  9. {
  10. [ToolboxBitmap(typeof(NumericUpDown))]
  11. public class SkinNumericUpDown : NumericUpDown
  12. {
  13. private class UpDownButtonNativeWindow : NativeWindow, IDisposable
  14. {
  15. private const int WM_PAINT = 15;
  16. private const int VK_LBUTTON = 1;
  17. private const int VK_RBUTTON = 2;
  18. private SkinNumericUpDown _owner;
  19. private Control _upDownButton;
  20. private IntPtr _upDownButtonWnd;
  21. private bool _bPainting;
  22. private static readonly IntPtr TRUE = new IntPtr(1);
  23. public UpDownButtonNativeWindow(SkinNumericUpDown owner)
  24. {
  25. this._owner = owner;
  26. this._upDownButton = owner.UpDownButton;
  27. this._upDownButtonWnd = this._upDownButton.Handle;
  28. if (Environment.OSVersion.Version.Major > 5 && NativeMethods.IsAppThemed())
  29. {
  30. NativeMethods.SetWindowTheme(this._upDownButtonWnd, "", "");
  31. }
  32. base.AssignHandle(this._upDownButtonWnd);
  33. }
  34. private bool LeftKeyPressed()
  35. {
  36. if (SystemInformation.MouseButtonsSwapped)
  37. {
  38. return NativeMethods.GetKeyState(2) < 0;
  39. }
  40. return NativeMethods.GetKeyState(1) < 0;
  41. }
  42. private void DrawUpDownButton()
  43. {
  44. bool mousePress = this.LeftKeyPressed();
  45. Rectangle clipRect = this._upDownButton.ClientRectangle;
  46. RECT windowRect = default(RECT);
  47. NativeMethods.Point cursorPoint = default(NativeMethods.Point);
  48. NativeMethods.GetCursorPos(ref cursorPoint);
  49. NativeMethods.GetWindowRect(this._upDownButtonWnd, ref windowRect);
  50. bool mouseOver = NativeMethods.PtInRect(ref windowRect, cursorPoint);
  51. cursorPoint.x -= windowRect.Left;
  52. cursorPoint.y -= windowRect.Top;
  53. bool mouseInUpButton = cursorPoint.y < clipRect.Height / 2;
  54. using (Graphics g = Graphics.FromHwnd(this._upDownButtonWnd))
  55. {
  56. UpDownButtonPaintEventArgs e = new UpDownButtonPaintEventArgs(g, clipRect, mouseOver, mousePress, mouseInUpButton);
  57. this._owner.OnPaintUpDownButton(e);
  58. }
  59. }
  60. protected override void WndProc(ref Message m)
  61. {
  62. int msg = m.Msg;
  63. if (msg != 15)
  64. {
  65. base.WndProc(ref m);
  66. return;
  67. }
  68. if (!this._bPainting)
  69. {
  70. this._bPainting = true;
  71. PAINTSTRUCT ps = default(PAINTSTRUCT);
  72. NativeMethods.BeginPaint(m.HWnd, ref ps);
  73. this.DrawUpDownButton();
  74. NativeMethods.EndPaint(m.HWnd, ref ps);
  75. this._bPainting = false;
  76. m.Result = SkinNumericUpDown.UpDownButtonNativeWindow.TRUE;
  77. return;
  78. }
  79. base.WndProc(ref m);
  80. }
  81. public void Dispose()
  82. {
  83. this._owner = null;
  84. this._upDownButton = null;
  85. base.ReleaseHandle();
  86. }
  87. }
  88. private SkinNumericUpDown.UpDownButtonNativeWindow _upDownButtonNativeWindow;
  89. private Color _baseColor = Color.FromArgb(166, 222, 255);
  90. private Color _borderColor = Color.FromArgb(23, 169, 254);
  91. private Color _arrowColor = Color.FromArgb(0, 95, 152);
  92. private static readonly object EventPaintUpDownButton = new object();
  93. public event UpDownButtonPaintEventHandler PaintUpDownButton
  94. {
  95. add
  96. {
  97. base.Events.AddHandler(SkinNumericUpDown.EventPaintUpDownButton, value);
  98. }
  99. remove
  100. {
  101. base.Events.RemoveHandler(SkinNumericUpDown.EventPaintUpDownButton, value);
  102. }
  103. }
  104. [Category("Skin"), DefaultValue(typeof(Color), "166, 222, 255"), Description("色调")]
  105. public Color BaseColor
  106. {
  107. get
  108. {
  109. return this._baseColor;
  110. }
  111. set
  112. {
  113. this._baseColor = value;
  114. this.UpDownButton.Invalidate();
  115. }
  116. }
  117. [Category("Skin"), DefaultValue(typeof(Color), "23, 169, 254"), Description("边框颜色")]
  118. public Color BorderColor
  119. {
  120. get
  121. {
  122. return this._borderColor;
  123. }
  124. set
  125. {
  126. this._borderColor = value;
  127. base.Invalidate(true);
  128. }
  129. }
  130. [Category("Skin"), DefaultValue(typeof(Color), "0, 95, 152"), Description("箭头颜色")]
  131. public Color ArrowColor
  132. {
  133. get
  134. {
  135. return this._arrowColor;
  136. }
  137. set
  138. {
  139. this._arrowColor = value;
  140. this.UpDownButton.Invalidate();
  141. }
  142. }
  143. public override Color BackColor
  144. {
  145. get
  146. {
  147. return base.BackColor;
  148. }
  149. set
  150. {
  151. base.BackColor = value;
  152. base.Invalidate(true);
  153. }
  154. }
  155. public Control UpDownButton
  156. {
  157. get
  158. {
  159. return base.Controls[0];
  160. }
  161. }
  162. bool isCustomColor = false;
  163. /// <summary>
  164. ///
  165. /// </summary>
  166. [DescriptionAttribute("设置是否可以自定义下拉框颜色"), CategoryAttribute("组件扩展属性")]
  167. public bool IsCustomColor
  168. {
  169. get { return isCustomColor; }
  170. set { isCustomColor = value; Invalidate(false); }
  171. }
  172. protected virtual void OnPaintUpDownButton(UpDownButtonPaintEventArgs e)
  173. {
  174. Graphics g = e.Graphics;
  175. Rectangle rect = e.ClipRectangle;
  176. if (!IsCustomColor)
  177. {
  178. _baseColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExBaseColor;
  179. _borderColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExBorderColor;
  180. _arrowColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExArrowColor;
  181. }
  182. Color upButtonBaseColor = this._baseColor;
  183. Color upButtonBorderColor = this._borderColor;
  184. Color upButtonArrowColor = this._arrowColor;
  185. Color downButtonBaseColor = this._baseColor;
  186. Color downButtonBorderColor = this._borderColor;
  187. Color downButtonArrowColor = this._arrowColor;
  188. Rectangle upButtonRect = rect;
  189. upButtonRect.Y++;
  190. upButtonRect.Width -= 2;
  191. upButtonRect.Height = rect.Height / 2 - 2;
  192. Rectangle downButtonRect = rect;
  193. downButtonRect.Y = upButtonRect.Bottom + 2;
  194. downButtonRect.Height = rect.Height - upButtonRect.Bottom - 4;
  195. downButtonRect.Width -= 2;
  196. if (base.Enabled)
  197. {
  198. if (e.MouseOver)
  199. {
  200. if (e.MousePress)
  201. {
  202. if (e.MouseInUpButton)
  203. {
  204. upButtonBaseColor = this.GetColor(this._baseColor, 0, -35, -24, -9);
  205. }
  206. else
  207. {
  208. downButtonBaseColor = this.GetColor(this._baseColor, 0, -35, -24, -9);
  209. }
  210. }
  211. else
  212. {
  213. if (e.MouseInUpButton)
  214. {
  215. upButtonBaseColor = this.GetColor(this._baseColor, 0, 35, 24, 9);
  216. }
  217. else
  218. {
  219. downButtonBaseColor = this.GetColor(this._baseColor, 0, 35, 24, 9);
  220. }
  221. }
  222. }
  223. }
  224. else
  225. {
  226. upButtonBaseColor = SystemColors.Control;
  227. upButtonBorderColor = SystemColors.ControlDark;
  228. upButtonArrowColor = SystemColors.ControlDark;
  229. downButtonBaseColor = SystemColors.Control;
  230. downButtonBorderColor = SystemColors.ControlDark;
  231. downButtonArrowColor = SystemColors.ControlDark;
  232. }
  233. g.SmoothingMode = SmoothingMode.AntiAlias;
  234. Color backColor = base.Enabled ? base.BackColor : SystemColors.Control;
  235. using (SolidBrush brush = new SolidBrush(backColor))
  236. {
  237. rect.Inflate(1, 1);
  238. g.FillRectangle(brush, rect);
  239. }
  240. this.RenderButton(g, upButtonRect, upButtonBaseColor, upButtonBorderColor, upButtonArrowColor, ArrowDirection.Up);
  241. this.RenderButton(g, downButtonRect, downButtonBaseColor, downButtonBorderColor, downButtonArrowColor, ArrowDirection.Down);
  242. UpDownButtonPaintEventHandler handler = base.Events[SkinNumericUpDown.EventPaintUpDownButton] as UpDownButtonPaintEventHandler;
  243. if (handler != null)
  244. {
  245. handler(this, e);
  246. }
  247. }
  248. protected override void OnHandleCreated(EventArgs e)
  249. {
  250. base.OnHandleCreated(e);
  251. if (this._upDownButtonNativeWindow == null)
  252. {
  253. this._upDownButtonNativeWindow = new SkinNumericUpDown.UpDownButtonNativeWindow(this);
  254. }
  255. }
  256. protected override void OnHandleDestroyed(EventArgs e)
  257. {
  258. base.OnHandleDestroyed(e);
  259. if (this._upDownButtonNativeWindow != null)
  260. {
  261. this._upDownButtonNativeWindow.Dispose();
  262. this._upDownButtonNativeWindow = null;
  263. }
  264. }
  265. protected override void WndProc(ref Message m)
  266. {
  267. if (!IsCustomColor)
  268. {
  269. _baseColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExBaseColor;
  270. _borderColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExBorderColor;
  271. _arrowColor = LYFZ.ComponentLibrary.GetUIResources.ComboBoxExArrowColor;
  272. }
  273. int msg = m.Msg;
  274. if (msg != 15)
  275. {
  276. if (msg != 133)
  277. {
  278. base.WndProc(ref m);
  279. return;
  280. }
  281. }
  282. else
  283. {
  284. base.WndProc(ref m);
  285. if (base.BorderStyle == BorderStyle.None)
  286. {
  287. return;
  288. }
  289. Color borderColor = base.Enabled ? this._borderColor : SystemColors.ControlDark;
  290. using (Graphics g = Graphics.FromHwnd(m.HWnd))
  291. {
  292. ControlPaint.DrawBorder(g, base.ClientRectangle, borderColor, ButtonBorderStyle.Solid);
  293. return;
  294. }
  295. }
  296. if (base.BorderStyle != BorderStyle.None)
  297. {
  298. Color backColor = base.Enabled ? base.BackColor : SystemColors.Control;
  299. Rectangle rect = new Rectangle(0, 0, base.Width, base.Height);
  300. IntPtr hdc = NativeMethods.GetWindowDC(m.HWnd);
  301. if (hdc == IntPtr.Zero)
  302. {
  303. throw new Win32Exception();
  304. }
  305. try
  306. {
  307. using (Graphics g2 = Graphics.FromHdc(hdc))
  308. {
  309. using (Brush brush = new SolidBrush(backColor))
  310. {
  311. g2.FillRectangle(brush, rect);
  312. }
  313. }
  314. }
  315. finally
  316. {
  317. NativeMethods.ReleaseDC(m.HWnd, hdc);
  318. }
  319. }
  320. m.Result = IntPtr.Zero;
  321. }
  322. public void RenderArrowInternal(Graphics g, Rectangle dropDownRect, ArrowDirection direction, Brush brush)
  323. {
  324. Point point = new Point(dropDownRect.Left + dropDownRect.Width / 2, dropDownRect.Top + dropDownRect.Height / 2);
  325. Point[] points;
  326. switch (direction)
  327. {
  328. case ArrowDirection.Left:
  329. points = new Point[]
  330. {
  331. new Point(point.X + 2, point.Y - 3),
  332. new Point(point.X + 2, point.Y + 3),
  333. new Point(point.X - 1, point.Y)
  334. };
  335. break;
  336. case ArrowDirection.Up:
  337. points = new Point[]
  338. {
  339. new Point(point.X - 3, point.Y + 1),
  340. new Point(point.X + 3, point.Y + 1),
  341. new Point(point.X, point.Y - 1)
  342. };
  343. break;
  344. default:
  345. if (direction != ArrowDirection.Right)
  346. {
  347. points = new Point[]
  348. {
  349. new Point(point.X - 3, point.Y - 1),
  350. new Point(point.X + 3, point.Y - 1),
  351. new Point(point.X, point.Y + 1)
  352. };
  353. }
  354. else
  355. {
  356. points = new Point[]
  357. {
  358. new Point(point.X - 2, point.Y - 3),
  359. new Point(point.X - 2, point.Y + 3),
  360. new Point(point.X + 1, point.Y)
  361. };
  362. }
  363. break;
  364. }
  365. g.FillPolygon(brush, points);
  366. }
  367. public void RenderButton(Graphics g, Rectangle rect, Color baseColor, Color borderColor, Color arrowColor, ArrowDirection direction)
  368. {
  369. this.RenderBackgroundInternal(g, rect, baseColor, borderColor, 0.45f, true, LinearGradientMode.Vertical);
  370. using (SolidBrush brush = new SolidBrush(arrowColor))
  371. {
  372. this.RenderArrowInternal(g, rect, direction, brush);
  373. }
  374. }
  375. public void RenderBackgroundInternal(Graphics g, Rectangle rect, Color baseColor, Color borderColor, float basePosition, bool drawBorder, LinearGradientMode mode)
  376. {
  377. using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, mode))
  378. {
  379. Color[] colors = new Color[]
  380. {
  381. this.GetColor(baseColor, 0, 35, 24, 9),
  382. this.GetColor(baseColor, 0, 13, 8, 3),
  383. baseColor,
  384. this.GetColor(baseColor, 0, 68, 69, 54)
  385. };
  386. brush.InterpolationColors = new ColorBlend
  387. {
  388. Positions = new float[]
  389. {
  390. 0f,
  391. basePosition,
  392. basePosition + 0.05f,
  393. 1f
  394. },
  395. Colors = colors
  396. };
  397. g.FillRectangle(brush, rect);
  398. }
  399. if (baseColor.A > 80)
  400. {
  401. Rectangle rectTop = rect;
  402. if (mode == LinearGradientMode.Vertical)
  403. {
  404. rectTop.Height = (int)((float)rectTop.Height * basePosition);
  405. }
  406. else
  407. {
  408. rectTop.Width = (int)((float)rect.Width * basePosition);
  409. }
  410. using (SolidBrush brushAlpha = new SolidBrush(Color.FromArgb(80, 255, 255, 255)))
  411. {
  412. g.FillRectangle(brushAlpha, rectTop);
  413. }
  414. }
  415. if (drawBorder)
  416. {
  417. using (Pen pen = new Pen(borderColor))
  418. {
  419. g.DrawRectangle(pen, rect);
  420. }
  421. }
  422. }
  423. private Color GetColor(Color colorBase, int a, int r, int g, int b)
  424. {
  425. int a2 = (int)colorBase.A;
  426. int r2 = (int)colorBase.R;
  427. int g2 = (int)colorBase.G;
  428. int b2 = (int)colorBase.B;
  429. if (a + a2 > 255)
  430. {
  431. a = 255;
  432. }
  433. else
  434. {
  435. a = Math.Max(a + a2, 0);
  436. }
  437. if (r + r2 > 255)
  438. {
  439. r = 255;
  440. }
  441. else
  442. {
  443. r = Math.Max(r + r2, 0);
  444. }
  445. if (g + g2 > 255)
  446. {
  447. g = 255;
  448. }
  449. else
  450. {
  451. g = Math.Max(g + g2, 0);
  452. }
  453. if (b + b2 > 255)
  454. {
  455. b = 255;
  456. }
  457. else
  458. {
  459. b = Math.Max(b + b2, 0);
  460. }
  461. return Color.FromArgb(a, r, g, b);
  462. }
  463. }
  464. }