MirTextBox.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. using Client.MirGraphics;
  2. using SlimDX;
  3. using SlimDX.Direct3D9;
  4. using System.Drawing.Imaging;
  5. namespace Client.MirControls
  6. {
  7. public sealed class MirTextBox : MirControl
  8. {
  9. #region Back Color
  10. protected override void OnBackColourChanged()
  11. {
  12. base.OnBackColourChanged();
  13. if (TextBox != null && !TextBox.IsDisposed)
  14. TextBox.BackColor = BackColour;
  15. }
  16. #endregion
  17. #region Enabled
  18. protected override void OnEnabledChanged()
  19. {
  20. base.OnEnabledChanged();
  21. if (TextBox != null && !TextBox.IsDisposed)
  22. TextBox.Enabled = Enabled;
  23. }
  24. #endregion
  25. #region Fore Color
  26. protected override void OnForeColourChanged()
  27. {
  28. base.OnForeColourChanged();
  29. if (TextBox != null && !TextBox.IsDisposed)
  30. TextBox.ForeColor = ForeColour;
  31. }
  32. #endregion
  33. #region Location
  34. protected override void OnLocationChanged()
  35. {
  36. base.OnLocationChanged();
  37. ApplyNativeTextBoxState();
  38. TextureValid = false;
  39. Redraw();
  40. }
  41. #endregion
  42. #region Max Length
  43. public int MaxLength
  44. {
  45. get
  46. {
  47. if (TextBox != null && !TextBox.IsDisposed)
  48. return TextBox.MaxLength;
  49. return -1;
  50. }
  51. set
  52. {
  53. if (TextBox != null && !TextBox.IsDisposed)
  54. TextBox.MaxLength = value;
  55. }
  56. }
  57. #endregion
  58. #region Parent
  59. protected override void OnParentChanged()
  60. {
  61. base.OnParentChanged();
  62. if (TextBox != null && !TextBox.IsDisposed)
  63. ApplyNativeTextBoxState();
  64. }
  65. #endregion
  66. #region Password
  67. public bool Password
  68. {
  69. get
  70. {
  71. if (TextBox != null && !TextBox.IsDisposed)
  72. return TextBox.UseSystemPasswordChar;
  73. return false;
  74. }
  75. set
  76. {
  77. if (TextBox != null && !TextBox.IsDisposed)
  78. TextBox.UseSystemPasswordChar = value;
  79. }
  80. }
  81. #endregion
  82. #region Font
  83. public System.Drawing.Font Font
  84. {
  85. get
  86. {
  87. if (TextBox != null && !TextBox.IsDisposed)
  88. return TextBox.Font;
  89. return null;
  90. }
  91. set
  92. {
  93. if (TextBox != null && !TextBox.IsDisposed)
  94. TextBox.Font = ScaleFont(value);
  95. }
  96. }
  97. #endregion
  98. #region Size
  99. protected override void OnSizeChanged()
  100. {
  101. TextBox.Size = Size;
  102. DisposeTexture();
  103. _size = Size;
  104. if (TextBox != null && !TextBox.IsDisposed)
  105. base.OnSizeChanged();
  106. }
  107. #endregion
  108. #region TextBox
  109. public bool CanLoseFocus;
  110. public readonly TextBox TextBox;
  111. private Pen CaretPen;
  112. private static Point HiddenTextBoxLocation
  113. {
  114. get { return new Point(-32000, -32000); }
  115. }
  116. private void ApplyNativeTextBoxState()
  117. {
  118. if (TextBox == null || TextBox.IsDisposed) return;
  119. TextBox.Location = HiddenTextBoxLocation;
  120. TextBox.Visible = Visible && TextBox.Parent != null;
  121. }
  122. #endregion
  123. #region Label
  124. public string Text
  125. {
  126. get
  127. {
  128. if (TextBox != null && !TextBox.IsDisposed)
  129. return TextBox.Text;
  130. return null;
  131. }
  132. set
  133. {
  134. if (TextBox != null && !TextBox.IsDisposed)
  135. {
  136. TextBox.Text = value;
  137. TextBox_NeedRedraw(this, EventArgs.Empty);
  138. }
  139. }
  140. }
  141. public string[] MultiText
  142. {
  143. get
  144. {
  145. if (TextBox != null && !TextBox.IsDisposed)
  146. return TextBox.Lines;
  147. return null;
  148. }
  149. set
  150. {
  151. if (TextBox != null && !TextBox.IsDisposed)
  152. {
  153. TextBox.Lines = value;
  154. TextBox_NeedRedraw(this, EventArgs.Empty);
  155. }
  156. }
  157. }
  158. #endregion
  159. #region Visible
  160. public override bool Visible
  161. {
  162. get
  163. {
  164. return base.Visible;
  165. }
  166. set
  167. {
  168. base.Visible = value;
  169. OnVisibleChanged();
  170. }
  171. }
  172. protected override void OnVisibleChanged()
  173. {
  174. base.OnVisibleChanged();
  175. ApplyNativeTextBoxState();
  176. }
  177. private void TextBox_VisibleChanged(object sender, EventArgs e)
  178. {
  179. DialogChanged();
  180. if (TextBox.Visible && TextBox.CanFocus)
  181. if (Program.Form.ActiveControl == null || Program.Form.ActiveControl == Program.Form)
  182. Program.Form.ActiveControl = TextBox;
  183. if (!TextBox.Visible)
  184. if (Program.Form.ActiveControl == TextBox)
  185. Program.Form.Focus();
  186. }
  187. private void SetFocus(object sender, EventArgs e)
  188. {
  189. if (TextBox.Visible)
  190. TextBox.VisibleChanged -= SetFocus;
  191. if (TextBox.Parent != null)
  192. TextBox.ParentChanged -= SetFocus;
  193. if (TextBox.CanFocus) TextBox.Focus();
  194. else if (TextBox.Visible && TextBox.Parent != null)
  195. Program.Form.ActiveControl = TextBox;
  196. }
  197. #endregion
  198. #region MultiLine
  199. public override void MultiLine()
  200. {
  201. TextBox.Multiline = true;
  202. TextBox.Size = Size;
  203. DisposeTexture();
  204. Redraw();
  205. }
  206. #endregion
  207. public MirTextBox()
  208. {
  209. BackColour = Color.Black;
  210. DrawControlTexture = true;
  211. TextureValid = false;
  212. TextBox = new TextBox
  213. {
  214. BackColor = BackColour,
  215. BorderStyle = BorderStyle.None,
  216. Font = new System.Drawing.Font(Settings.FontName, 10F * 96f / FontDpiX),
  217. ForeColor = ForeColour,
  218. Location = HiddenTextBoxLocation,
  219. Size = Size,
  220. Visible = Visible,
  221. Tag = this,
  222. Cursor = CMain.Cursors[(byte)MouseCursor.TextPrompt]
  223. };
  224. CaretPen = new Pen(ForeColour, 1);
  225. TextBox.VisibleChanged += TextBox_VisibleChanged;
  226. TextBox.ParentChanged += TextBox_VisibleChanged;
  227. TextBox.KeyUp += TextBoxOnKeyUp;
  228. TextBox.KeyPress += TextBox_KeyPress;
  229. TextBox.KeyPress += TextBox_NeedRedraw;
  230. TextBox.KeyUp += TextBox_NeedRedraw;
  231. TextBox.TextChanged += TextBox_NeedRedraw;
  232. TextBox.MouseDown += TextBox_NeedRedraw;
  233. TextBox.MouseUp += TextBox_NeedRedraw;
  234. TextBox.LostFocus += TextBox_NeedRedraw;
  235. TextBox.GotFocus += TextBox_NeedRedraw;
  236. TextBox.MouseWheel += TextBox_NeedRedraw;
  237. Shown += MirTextBox_Shown;
  238. TextBox.MouseMove += CMain.CMain_MouseMove;
  239. }
  240. private void TextBox_NeedRedraw(object sender, EventArgs e)
  241. {
  242. TextureValid = false;
  243. Redraw();
  244. }
  245. protected unsafe override void CreateTexture()
  246. {
  247. if (Size.IsEmpty)
  248. return;
  249. if (TextureSize != Size)
  250. DisposeTexture();
  251. if (ControlTexture == null || ControlTexture.Disposed)
  252. {
  253. DXManager.ControlList.Add(this);
  254. ControlTexture = new Texture(DXManager.Device, Size.Width, Size.Height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
  255. TextureSize = Size;
  256. }
  257. Point caret = GetCaretPosition();
  258. DataRectangle stream = ControlTexture.LockRectangle(0, LockFlags.Discard);
  259. using (Bitmap bm = new Bitmap(Size.Width, Size.Height, Size.Width * 4, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
  260. {
  261. TextBox.DrawToBitmap(bm, new Rectangle(0, 0, Size.Width, Size.Height));
  262. using (Graphics graphics = Graphics.FromImage(bm))
  263. {
  264. graphics.DrawImage(bm, Point.Empty);
  265. if (TextBox.Focused)
  266. graphics.DrawLine(CaretPen, new Point(caret.X, caret.Y), new Point(caret.X, caret.Y + TextBox.Font.Height));
  267. }
  268. }
  269. ControlTexture.UnlockRectangle(0);
  270. DXManager.Sprite.Flush();
  271. TextureValid = true;
  272. }
  273. public override void OnMouseDown(MouseEventArgs e)
  274. {
  275. base.OnMouseDown(e);
  276. if (!Enabled || TextBox == null || TextBox.IsDisposed || !TextBox.Visible) return;
  277. if (e.Button == MouseButtons.Left)
  278. {
  279. Point localPoint = new Point(e.X - DisplayLocation.X, e.Y - DisplayLocation.Y);
  280. int charIndex = TextBox.GetCharIndexFromPosition(localPoint);
  281. TextBox.SelectionStart = Math.Max(0, Math.Min(charIndex, TextBox.TextLength));
  282. TextBox.SelectionLength = 0;
  283. }
  284. SetFocus();
  285. }
  286. private Point GetCaretPosition()
  287. {
  288. Point result = TextBox.GetPositionFromCharIndex(TextBox.SelectionStart);
  289. if (result.X == 0 && TextBox.Text.Length > 0)
  290. {
  291. result = TextBox.GetPositionFromCharIndex(TextBox.Text.Length - 1);
  292. int s = result.X / TextBox.Text.Length;
  293. result.X = (int)(result.X + (s * 1.46));
  294. result.Y = TextBox.GetLineFromCharIndex(TextBox.SelectionStart) * TextBox.Font.Height;
  295. }
  296. return result;
  297. }
  298. private void TextBoxOnKeyUp(object sender, KeyEventArgs e)
  299. {
  300. switch (e.KeyCode)
  301. {
  302. case Keys.PrintScreen:
  303. CMain.CMain_KeyUp(sender, e);
  304. break;
  305. }
  306. }
  307. void TextBox_KeyPress(object sender, KeyPressEventArgs e)
  308. {
  309. base.OnKeyPress(e);
  310. if (e.KeyChar == (char)Keys.Escape)
  311. {
  312. Program.Form.ActiveControl = null;
  313. e.Handled = true;
  314. }
  315. }
  316. void MirTextBox_Shown(object sender, EventArgs e)
  317. {
  318. TextBox.Parent = Program.Form;
  319. ApplyNativeTextBoxState();
  320. CMain.Ctrl = false;
  321. CMain.Shift = false;
  322. CMain.Alt = false;
  323. CMain.Tilde = false;
  324. TextureValid = false;
  325. SetFocus();
  326. }
  327. public void SetFocus()
  328. {
  329. if (!TextBox.Visible)
  330. TextBox.VisibleChanged += SetFocus;
  331. else if (TextBox.Parent == null)
  332. TextBox.ParentChanged += SetFocus;
  333. else
  334. TextBox.Focus();
  335. }
  336. public void DialogChanged()
  337. {
  338. MirMessageBox box1 = null;
  339. MirInputBox box2 = null;
  340. MirAmountBox box3 = null;
  341. if (MirScene.ActiveScene != null && MirScene.ActiveScene.Controls.Count > 0)
  342. {
  343. box1 = (MirMessageBox) MirScene.ActiveScene.Controls.FirstOrDefault(ob => ob is MirMessageBox);
  344. box2 = (MirInputBox) MirScene.ActiveScene.Controls.FirstOrDefault(O => O is MirInputBox);
  345. box3 = (MirAmountBox) MirScene.ActiveScene.Controls.FirstOrDefault(ob => ob is MirAmountBox);
  346. }
  347. if ((box1 != null && box1 != Parent) || (box2 != null && box2 != Parent) || (box3 != null && box3 != Parent))
  348. TextBox.Visible = false;
  349. else
  350. ApplyNativeTextBoxState();
  351. }
  352. #region Disposable
  353. protected override void Dispose(bool disposing)
  354. {
  355. base.Dispose(disposing);
  356. if (!disposing) return;
  357. if (!TextBox.IsDisposed)
  358. TextBox.Dispose();
  359. }
  360. #endregion
  361. }
  362. }