CMain.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. using System.ComponentModel;
  2. using System.Diagnostics;
  3. using System.Drawing.Drawing2D;
  4. using System.Drawing.Imaging;
  5. using System.Drawing.Text;
  6. using System.Runtime.InteropServices;
  7. using System.Security;
  8. using Client.MirControls;
  9. using Client.MirGraphics;
  10. using Client.MirNetwork;
  11. using Client.MirScenes;
  12. using Client.MirSounds;
  13. using SlimDX.Direct3D9;
  14. using SlimDX.Windows;
  15. using Font = System.Drawing.Font;
  16. namespace Client
  17. {
  18. public partial class CMain : RenderForm
  19. {
  20. public static MirControl DebugBaseLabel, HintBaseLabel;
  21. public static MirLabel DebugTextLabel, HintTextLabel, ScreenshotTextLabel;
  22. public static Graphics Graphics;
  23. public static Point MPoint;
  24. public readonly static Stopwatch Timer = Stopwatch.StartNew();
  25. public readonly static DateTime StartTime = DateTime.UtcNow;
  26. public static long Time;
  27. public static DateTime Now { get { return StartTime.AddMilliseconds(Time); } }
  28. public static readonly Random Random = new Random();
  29. public static string DebugText = "";
  30. private static long _fpsTime;
  31. private static int _fps;
  32. private static long _cleanTime;
  33. private static long _drawTime;
  34. public static int FPS;
  35. public static int DPS;
  36. public static int DPSCounter;
  37. public static long PingTime;
  38. public static long NextPing = 10000;
  39. public static bool Shift, Alt, Ctrl, Tilde, SpellTargetLock;
  40. public static double BytesSent, BytesReceived;
  41. public static KeyBindSettings InputKeys = new KeyBindSettings();
  42. public CMain()
  43. {
  44. InitializeComponent();
  45. Application.Idle += Application_Idle;
  46. MouseClick += CMain_MouseClick;
  47. MouseDown += CMain_MouseDown;
  48. MouseUp += CMain_MouseUp;
  49. MouseMove += CMain_MouseMove;
  50. MouseDoubleClick += CMain_MouseDoubleClick;
  51. KeyPress += CMain_KeyPress;
  52. KeyDown += CMain_KeyDown;
  53. KeyUp += CMain_KeyUp;
  54. Deactivate += CMain_Deactivate;
  55. MouseWheel += CMain_MouseWheel;
  56. SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.Selectable, true);
  57. FormBorderStyle = Settings.FullScreen || Settings.Borderless ? FormBorderStyle.None : FormBorderStyle.FixedDialog;
  58. Graphics = CreateGraphics();
  59. Graphics.SmoothingMode = SmoothingMode.AntiAlias;
  60. Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
  61. Graphics.CompositingQuality = CompositingQuality.HighQuality;
  62. Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
  63. Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
  64. Graphics.TextContrast = 0;
  65. }
  66. private void CMain_Load(object sender, EventArgs e)
  67. {
  68. this.Text = GameLanguage.ClientTextMap.GetLocalization(ClientTextKeys.GameName);
  69. try
  70. {
  71. ClientSize = new Size(Settings.ScreenWidth, Settings.ScreenHeight);
  72. LoadMouseCursors();
  73. SetMouseCursor(MouseCursor.Default);
  74. SlimDX.Configuration.EnableObjectTracking = true;
  75. DXManager.Create();
  76. SoundManager.Create();
  77. CenterToScreen();
  78. }
  79. catch (Exception ex)
  80. {
  81. SaveError(ex.ToString());
  82. }
  83. }
  84. private static void Application_Idle(object sender, EventArgs e)
  85. {
  86. try
  87. {
  88. while (AppStillIdle)
  89. {
  90. UpdateTime();
  91. UpdateEnviroment();
  92. if (IsDrawTime())
  93. {
  94. RenderEnvironment();
  95. UpdateFrameTime();
  96. }
  97. }
  98. }
  99. catch (Exception ex)
  100. {
  101. SaveError(ex.ToString());
  102. }
  103. }
  104. private static void CMain_Deactivate(object sender, EventArgs e)
  105. {
  106. MapControl.MapButtons = MouseButtons.None;
  107. Shift = false;
  108. Alt = false;
  109. Ctrl = false;
  110. Tilde = false;
  111. SpellTargetLock = false;
  112. }
  113. public static void CMain_KeyDown(object sender, KeyEventArgs e)
  114. {
  115. Shift = e.Shift;
  116. Alt = e.Alt;
  117. Ctrl = e.Control;
  118. if (!String.IsNullOrEmpty(InputKeys.GetKey(KeybindOptions.TargetSpellLockOn)))
  119. {
  120. SpellTargetLock = e.KeyCode == (Keys)Enum.Parse(typeof(Keys), InputKeys.GetKey(KeybindOptions.TargetSpellLockOn), true);
  121. }
  122. else
  123. {
  124. SpellTargetLock = false;
  125. }
  126. if (e.KeyCode == Keys.Oem8)
  127. CMain.Tilde = true;
  128. try
  129. {
  130. if (e.Alt && e.KeyCode == Keys.Enter)
  131. {
  132. ToggleFullScreen();
  133. return;
  134. }
  135. if (MirScene.ActiveScene != null)
  136. MirScene.ActiveScene.OnKeyDown(e);
  137. }
  138. catch (Exception ex)
  139. {
  140. SaveError(ex.ToString());
  141. }
  142. }
  143. public static void CMain_MouseMove(object sender, MouseEventArgs e)
  144. {
  145. if (Settings.FullScreen || Settings.MouseClip)
  146. Cursor.Clip = Program.Form.RectangleToScreen(Program.Form.ClientRectangle);
  147. MPoint = Program.Form.PointToClient(Cursor.Position);
  148. try
  149. {
  150. if (MirScene.ActiveScene != null)
  151. MirScene.ActiveScene.OnMouseMove(e);
  152. }
  153. catch (Exception ex)
  154. {
  155. SaveError(ex.ToString());
  156. }
  157. }
  158. public static void CMain_KeyUp(object sender, KeyEventArgs e)
  159. {
  160. Shift = e.Shift;
  161. Alt = e.Alt;
  162. Ctrl = e.Control;
  163. if (!String.IsNullOrEmpty(InputKeys.GetKey(KeybindOptions.TargetSpellLockOn)))
  164. {
  165. SpellTargetLock = e.KeyCode == (Keys)Enum.Parse(typeof(Keys), InputKeys.GetKey(KeybindOptions.TargetSpellLockOn), true);
  166. }
  167. else
  168. {
  169. SpellTargetLock = false;
  170. }
  171. if (e.KeyCode == Keys.Oem8)
  172. CMain.Tilde = false;
  173. foreach (KeyBind KeyCheck in CMain.InputKeys.Keylist)
  174. {
  175. if (KeyCheck.function != KeybindOptions.Screenshot) continue;
  176. if (KeyCheck.Key != e.KeyCode)
  177. continue;
  178. if ((KeyCheck.RequireAlt != 2) && (KeyCheck.RequireAlt != (Alt ? 1 : 0)))
  179. continue;
  180. if ((KeyCheck.RequireShift != 2) && (KeyCheck.RequireShift != (Shift ? 1 : 0)))
  181. continue;
  182. if ((KeyCheck.RequireCtrl != 2) && (KeyCheck.RequireCtrl != (Ctrl ? 1 : 0)))
  183. continue;
  184. if ((KeyCheck.RequireTilde != 2) && (KeyCheck.RequireTilde != (Tilde ? 1 : 0)))
  185. continue;
  186. Program.Form.CreateScreenShot();
  187. break;
  188. }
  189. try
  190. {
  191. if (MirScene.ActiveScene != null)
  192. MirScene.ActiveScene.OnKeyUp(e);
  193. }
  194. catch (Exception ex)
  195. {
  196. SaveError(ex.ToString());
  197. }
  198. }
  199. public static void CMain_KeyPress(object sender, KeyPressEventArgs e)
  200. {
  201. try
  202. {
  203. if (MirScene.ActiveScene != null)
  204. MirScene.ActiveScene.OnKeyPress(e);
  205. }
  206. catch (Exception ex)
  207. {
  208. SaveError(ex.ToString());
  209. }
  210. }
  211. public static void CMain_MouseDoubleClick(object sender, MouseEventArgs e)
  212. {
  213. try
  214. {
  215. if (MirScene.ActiveScene != null)
  216. MirScene.ActiveScene.OnMouseClick(e);
  217. }
  218. catch (Exception ex)
  219. {
  220. SaveError(ex.ToString());
  221. }
  222. }
  223. public static void CMain_MouseUp(object sender, MouseEventArgs e)
  224. {
  225. MapControl.MapButtons &= ~e.Button;
  226. if (e.Button != MouseButtons.Right || !Settings.NewMove)
  227. GameScene.CanRun = false;
  228. try
  229. {
  230. if (MirScene.ActiveScene != null)
  231. MirScene.ActiveScene.OnMouseUp(e);
  232. }
  233. catch (Exception ex)
  234. {
  235. SaveError(ex.ToString());
  236. }
  237. }
  238. public static void CMain_MouseDown(object sender, MouseEventArgs e)
  239. {
  240. if (Program.Form.ActiveControl is TextBox)
  241. {
  242. MirTextBox textBox = Program.Form.ActiveControl.Tag as MirTextBox;
  243. if (textBox != null && textBox.CanLoseFocus)
  244. Program.Form.ActiveControl = null;
  245. }
  246. if (e.Button == MouseButtons.Right && (GameScene.SelectedCell != null || GameScene.PickedUpGold))
  247. {
  248. GameScene.SelectedCell = null;
  249. GameScene.PickedUpGold = false;
  250. return;
  251. }
  252. try
  253. {
  254. if (MirScene.ActiveScene != null)
  255. MirScene.ActiveScene.OnMouseDown(e);
  256. }
  257. catch (Exception ex)
  258. {
  259. SaveError(ex.ToString());
  260. }
  261. }
  262. public static void CMain_MouseClick(object sender, MouseEventArgs e)
  263. {
  264. try
  265. {
  266. if (MirScene.ActiveScene != null)
  267. MirScene.ActiveScene.OnMouseClick(e);
  268. }
  269. catch (Exception ex)
  270. {
  271. SaveError(ex.ToString());
  272. }
  273. }
  274. public static void CMain_MouseWheel(object sender, MouseEventArgs e)
  275. {
  276. try
  277. {
  278. if (MirScene.ActiveScene != null)
  279. MirScene.ActiveScene.OnMouseWheel(e);
  280. }
  281. catch (Exception ex)
  282. {
  283. SaveError(ex.ToString());
  284. }
  285. }
  286. private static void UpdateTime()
  287. {
  288. Time = Timer.ElapsedMilliseconds;
  289. }
  290. private static void UpdateFrameTime()
  291. {
  292. if (Time >= _fpsTime)
  293. {
  294. _fpsTime = Time + 1000;
  295. FPS = _fps;
  296. _fps = 0;
  297. DPS = DPSCounter;
  298. DPSCounter = 0;
  299. }
  300. else
  301. _fps++;
  302. }
  303. private static bool IsDrawTime()
  304. {
  305. int targetUpdates = 1000 / Math.Max(1, Settings.MaxFPS);
  306. if (Time >= _drawTime)
  307. {
  308. _drawTime = Time + targetUpdates;
  309. return true;
  310. }
  311. return false;
  312. }
  313. private static void UpdateEnviroment()
  314. {
  315. if (Time >= _cleanTime)
  316. {
  317. _cleanTime = Time + 1000;
  318. DXManager.Clean(); // Clean once a second.
  319. }
  320. Network.Process();
  321. if (MirScene.ActiveScene != null)
  322. MirScene.ActiveScene.Process();
  323. for (int i = 0; i < MirAnimatedControl.Animations.Count; i++)
  324. MirAnimatedControl.Animations[i].UpdateOffSet();
  325. for (int i = 0; i < MirAnimatedButton.Animations.Count; i++)
  326. MirAnimatedButton.Animations[i].UpdateOffSet();
  327. CreateHintLabel();
  328. if (Settings.DebugMode)
  329. {
  330. CreateDebugLabel();
  331. }
  332. }
  333. private static void RenderEnvironment()
  334. {
  335. try
  336. {
  337. if (DXManager.DeviceLost)
  338. {
  339. DXManager.AttemptReset();
  340. Thread.Sleep(1);
  341. return;
  342. }
  343. DXManager.Device.Clear(ClearFlags.Target, Color.Black, 0, 0);
  344. DXManager.Device.BeginScene();
  345. DXManager.Sprite.Begin(SpriteFlags.AlphaBlend);
  346. DXManager.SetSurface(DXManager.MainSurface);
  347. if (MirScene.ActiveScene != null)
  348. MirScene.ActiveScene.Draw();
  349. DXManager.Sprite.End();
  350. DXManager.Device.EndScene();
  351. DXManager.Device.Present();
  352. }
  353. catch (Direct3D9Exception ex)
  354. {
  355. DXManager.DeviceLost = true;
  356. SaveError(ex.ToString());
  357. }
  358. catch (Exception ex)
  359. {
  360. SaveError(ex.ToString());
  361. DXManager.AttemptRecovery();
  362. }
  363. }
  364. private static void CreateDebugLabel()
  365. {
  366. string text;
  367. if (MirControl.MouseControl != null)
  368. {
  369. text = string.Format("FPS: {0}", FPS);
  370. text += string.Format(", DPS: {0}", DPS);
  371. text += string.Format(", Time: {0:HH:mm:ss UTC}", Now);
  372. if (MirControl.MouseControl is MapControl)
  373. text += string.Format(", Co Ords: {0}", MapControl.MapLocation);
  374. if (MirControl.MouseControl is MirImageControl)
  375. text += string.Format(", Control: {0}", MirControl.MouseControl.GetType().Name);
  376. if (MirScene.ActiveScene is GameScene)
  377. text += string.Format(", Objects: {0}", MapControl.Objects.Count);
  378. if (MirScene.ActiveScene is GameScene && !string.IsNullOrEmpty(DebugText))
  379. text += string.Format(", Debug: {0}", DebugText);
  380. if (MirObjects.MapObject.MouseObject != null)
  381. {
  382. text += string.Format(", Target: {0}", MirObjects.MapObject.MouseObject.Name);
  383. }
  384. else
  385. {
  386. text += string.Format(", Target: none");
  387. }
  388. }
  389. else
  390. {
  391. text = string.Format("FPS: {0}", FPS);
  392. }
  393. text += string.Format(", Ping: {0}", PingTime);
  394. text += string.Format(", Sent: {0}, Received: {1}", Functions.ConvertByteSize(BytesSent), Functions.ConvertByteSize(BytesReceived));
  395. text += string.Format(", TLC: {0}", DXManager.TextureList.Count(x => x.TextureValid));
  396. text += string.Format(", CLC: {0}", DXManager.ControlList.Count(x => x.IsDisposed == false));
  397. if (Settings.FullScreen)
  398. {
  399. if (DebugBaseLabel == null || DebugBaseLabel.IsDisposed)
  400. {
  401. DebugBaseLabel = new MirControl
  402. {
  403. BackColour = Color.FromArgb(50, 50, 50),
  404. Border = true,
  405. BorderColour = Color.Black,
  406. DrawControlTexture = true,
  407. Location = new Point(5, 5),
  408. NotControl = true,
  409. Opacity = 0.5F
  410. };
  411. }
  412. if (DebugTextLabel == null || DebugTextLabel.IsDisposed)
  413. {
  414. DebugTextLabel = new MirLabel
  415. {
  416. AutoSize = true,
  417. BackColour = Color.Transparent,
  418. ForeColour = Color.White,
  419. Parent = DebugBaseLabel,
  420. };
  421. DebugTextLabel.SizeChanged += (o, e) => DebugBaseLabel.Size = DebugTextLabel.Size;
  422. }
  423. DebugTextLabel.Text = text;
  424. }
  425. else
  426. {
  427. if (DebugBaseLabel != null && DebugBaseLabel.IsDisposed == false)
  428. {
  429. DebugBaseLabel.Dispose();
  430. DebugBaseLabel = null;
  431. }
  432. if (DebugTextLabel != null && DebugTextLabel.IsDisposed == false)
  433. {
  434. DebugTextLabel.Dispose();
  435. DebugTextLabel = null;
  436. }
  437. Program.Form.Text = $"{GameLanguage.ClientTextMap.GetLocalization(ClientTextKeys.GameName)} - {text}";
  438. }
  439. }
  440. private static void CreateHintLabel()
  441. {
  442. if (HintBaseLabel == null || HintBaseLabel.IsDisposed)
  443. {
  444. HintBaseLabel = new MirControl
  445. {
  446. BackColour = Color.FromArgb(255, 0, 0, 0),
  447. Border = true,
  448. DrawControlTexture = true,
  449. BorderColour = Color.FromArgb(255, 144, 144, 0),
  450. ForeColour = Color.Yellow,
  451. Parent = MirScene.ActiveScene,
  452. NotControl = true,
  453. Opacity = 0.5F
  454. };
  455. }
  456. if (HintTextLabel == null || HintTextLabel.IsDisposed)
  457. {
  458. HintTextLabel = new MirLabel
  459. {
  460. AutoSize = true,
  461. BackColour = Color.Transparent,
  462. ForeColour = Color.Yellow,
  463. Parent = HintBaseLabel,
  464. };
  465. HintTextLabel.SizeChanged += (o, e) => HintBaseLabel.Size = HintTextLabel.Size;
  466. }
  467. if (MirControl.MouseControl == null || string.IsNullOrEmpty(MirControl.MouseControl.Hint))
  468. {
  469. HintBaseLabel.Visible = false;
  470. return;
  471. }
  472. HintBaseLabel.Visible = true;
  473. HintTextLabel.Text = MirControl.MouseControl.Hint;
  474. Point point = MPoint.Add(-HintTextLabel.Size.Width, 20);
  475. if (point.X + HintBaseLabel.Size.Width >= Settings.ScreenWidth)
  476. point.X = Settings.ScreenWidth - HintBaseLabel.Size.Width - 1;
  477. if (point.Y + HintBaseLabel.Size.Height >= Settings.ScreenHeight)
  478. point.Y = Settings.ScreenHeight - HintBaseLabel.Size.Height - 1;
  479. if (point.X < 0)
  480. point.X = 0;
  481. if (point.Y < 0)
  482. point.Y = 0;
  483. HintBaseLabel.Location = point;
  484. }
  485. private static void ToggleFullScreen()
  486. {
  487. Settings.FullScreen = !Settings.FullScreen;
  488. Program.Form.FormBorderStyle = Settings.FullScreen || Settings.Borderless ? FormBorderStyle.None : FormBorderStyle.FixedDialog;
  489. Program.Form.TopMost = Settings.FullScreen;
  490. DXManager.Parameters.Windowed = !Settings.FullScreen;
  491. Program.Form.ClientSize = new Size(Settings.ScreenWidth, Settings.ScreenHeight);
  492. DXManager.ResetDevice();
  493. if (MirScene.ActiveScene == GameScene.Scene)
  494. {
  495. GameScene.Scene.MapControl.FloorValid = false;
  496. GameScene.Scene.TextureValid = false;
  497. }
  498. Program.Form.CenterToScreen();
  499. }
  500. public void CreateScreenShot()
  501. {
  502. string text = string.Format("[{0} Server {1}] {2} {3:hh\\:mm\\:ss}",
  503. Settings.P_ServerName.Length > 0 ? Settings.P_ServerName : "Crystal",
  504. MapControl.User != null ? MapControl.User.Name : "",
  505. Now.ToShortDateString(),
  506. Now.TimeOfDay);
  507. Surface backbuffer = DXManager.Device.GetBackBuffer(0, 0);
  508. using (var stream = Surface.ToStream(backbuffer, ImageFileFormat.Png))
  509. {
  510. Bitmap image = new Bitmap(stream);
  511. using (Graphics graphics = Graphics.FromImage(image))
  512. {
  513. StringFormat sf = new StringFormat
  514. {
  515. LineAlignment = StringAlignment.Center,
  516. Alignment = StringAlignment.Center
  517. };
  518. graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 3, 10), sf);
  519. graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 4, 9), sf);
  520. graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 5, 10), sf);
  521. graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 4, 11), sf);
  522. graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.White, new Point((Settings.ScreenWidth / 2) + 4, 10), sf);//SandyBrown
  523. string path = Path.Combine(Application.StartupPath, @"Screenshots\");
  524. if (!Directory.Exists(path))
  525. Directory.CreateDirectory(path);
  526. int count = Directory.GetFiles(path, "*.png").Length;
  527. image.Save(Path.Combine(path, string.Format("Image {0}.png", count)), ImageFormat.Png);
  528. }
  529. }
  530. }
  531. public static void SaveError(string ex)
  532. {
  533. try
  534. {
  535. if (Settings.RemainingErrorLogs-- > 0)
  536. {
  537. File.AppendAllText(@".\Error.txt",
  538. string.Format("[{0}] {1}{2}", Now, ex, Environment.NewLine));
  539. }
  540. }
  541. catch
  542. {
  543. }
  544. }
  545. public static void SetResolution(int width, int height)
  546. {
  547. if (Settings.ScreenWidth == width && Settings.ScreenHeight == height) return;
  548. Settings.ScreenWidth = width;
  549. Settings.ScreenHeight = height;
  550. Program.Form.ClientSize = new Size(width, height);
  551. DXManager.Device.Clear(ClearFlags.Target, Color.Black, 0, 0);
  552. DXManager.Device.Present();
  553. DXManager.ResetDevice();
  554. if (!Settings.FullScreen)
  555. Program.Form.CenterToScreen();
  556. }
  557. #region ScreenCapture
  558. //private Bitmap CaptureScreen()
  559. //{
  560. //}
  561. #endregion
  562. #region Idle Check
  563. private static bool AppStillIdle
  564. {
  565. get
  566. {
  567. PeekMsg msg;
  568. return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
  569. }
  570. }
  571. [SuppressUnmanagedCodeSecurity]
  572. [DllImport("User32.dll", CharSet = CharSet.Auto)]
  573. private static extern bool PeekMessage(out PeekMsg msg, IntPtr hWnd, uint messageFilterMin,
  574. uint messageFilterMax, uint flags);
  575. [StructLayout(LayoutKind.Sequential)]
  576. private struct PeekMsg
  577. {
  578. private readonly IntPtr hWnd;
  579. private readonly Message msg;
  580. private readonly IntPtr wParam;
  581. private readonly IntPtr lParam;
  582. private readonly uint time;
  583. private readonly Point p;
  584. }
  585. #endregion
  586. private void CMain_FormClosing(object sender, FormClosingEventArgs e)
  587. {
  588. if (CMain.Time < GameScene.LogTime && !Settings.UseTestConfig && !GameScene.Observing)
  589. {
  590. GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.ClientTextMap.GetLocalization((ClientTextKeys.CannotLeaveGame) , (GameScene.LogTime - CMain.Time) / 1000), ChatType.System);
  591. e.Cancel = true;
  592. }
  593. else
  594. {
  595. Settings.Save();
  596. DXManager.Dispose();
  597. SoundManager.Dispose();
  598. }
  599. }
  600. protected override void WndProc(ref Message m)
  601. {
  602. if (m.Msg == 0x0112) // WM_SYSCOMMAND
  603. {
  604. if (m.WParam.ToInt32() == 0xF100) // SC_KEYMENU
  605. {
  606. m.Result = IntPtr.Zero;
  607. return;
  608. }
  609. else if (m.WParam.ToInt32() == 0xF030) // SC_MAXIMISE
  610. {
  611. ToggleFullScreen();
  612. return;
  613. }
  614. }
  615. base.WndProc(ref m);
  616. }
  617. public static Cursor[] Cursors;
  618. public static MouseCursor CurrentCursor = MouseCursor.None;
  619. public static void SetMouseCursor(MouseCursor cursor)
  620. {
  621. if (!Settings.UseMouseCursors) return;
  622. if (CurrentCursor != cursor)
  623. {
  624. CurrentCursor = cursor;
  625. Program.Form.Cursor = Cursors[(byte)cursor];
  626. }
  627. }
  628. private static void LoadMouseCursors()
  629. {
  630. Cursors = new Cursor[8];
  631. Cursors[(int)MouseCursor.None] = Program.Form.Cursor;
  632. string path = $"{Settings.MouseCursorPath}Cursor_Default.CUR";
  633. if (File.Exists(path))
  634. Cursors[(int)MouseCursor.Default] = LoadCustomCursor(path);
  635. path = $"{Settings.MouseCursorPath}Cursor_Normal_Atk.CUR";
  636. if (File.Exists(path))
  637. Cursors[(int)MouseCursor.Attack] = LoadCustomCursor(path);
  638. path = $"{Settings.MouseCursorPath}Cursor_Compulsion_Atk.CUR";
  639. if (File.Exists(path))
  640. Cursors[(int)MouseCursor.AttackRed] = LoadCustomCursor(path);
  641. path = $"{Settings.MouseCursorPath}Cursor_Npc.CUR";
  642. if (File.Exists(path))
  643. Cursors[(int)MouseCursor.NPCTalk] = LoadCustomCursor(path);
  644. path = $"{Settings.MouseCursorPath}Cursor_TextPrompt.CUR";
  645. if (File.Exists(path))
  646. Cursors[(int)MouseCursor.TextPrompt] = LoadCustomCursor(path);
  647. path = $"{Settings.MouseCursorPath}Cursor_Trash.CUR";
  648. if (File.Exists(path))
  649. Cursors[(int)MouseCursor.Trash] = LoadCustomCursor(path);
  650. path = $"{Settings.MouseCursorPath}Cursor_Upgrade.CUR";
  651. if (File.Exists(path))
  652. Cursors[(int)MouseCursor.Upgrade] = LoadCustomCursor(path);
  653. }
  654. public static Cursor LoadCustomCursor(string path)
  655. {
  656. IntPtr hCurs = LoadCursorFromFile(path);
  657. if (hCurs == IntPtr.Zero) throw new Win32Exception();
  658. var curs = new Cursor(hCurs);
  659. // Note: force the cursor to own the handle so it gets released properly
  660. //var fi = typeof(Cursor).GetField("ownHandle", BindingFlags.NonPublic | BindingFlags.Instance);
  661. //fi.SetValue(curs, true);
  662. return curs;
  663. }
  664. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  665. private static extern IntPtr LoadCursorFromFile(string path);
  666. }
  667. }