EmbedArticlePanel.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //############################################################
  2. // quote:SmileWei.EmbeddedApp
  3. // https://github.com/yuzhengyang
  4. // author:yuzhengyang
  5. //############################################################
  6. using System;
  7. using System.ComponentModel;
  8. using System.Windows.Forms;
  9. using System.Diagnostics;
  10. using System.Runtime.InteropServices;
  11. using System.IO;
  12. namespace Y.Skin.YoPanel
  13. {
  14. public partial class EmbedArticlePanel : Panel
  15. {
  16. /// <summary>
  17. /// Track if the application has been created
  18. /// </summary>
  19. bool created = false;
  20. /// <summary>
  21. /// Handle to the application Window
  22. /// </summary>
  23. IntPtr appWin;
  24. /// <summary>
  25. /// The name of the exe to launch
  26. /// </summary>
  27. private string exeName = "";
  28. /// <summary>
  29. /// Get/Set if we draw the tick marks
  30. /// </summary>
  31. [
  32. Category("Data"),
  33. Description("Name of the executable to launch"),
  34. DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
  35. ]
  36. public string ExeName
  37. {
  38. get
  39. {
  40. return exeName;
  41. }
  42. set
  43. {
  44. exeName = value;
  45. }
  46. }
  47. /// <summary>
  48. /// Constructor
  49. /// </summary>
  50. public EmbedArticlePanel()
  51. {
  52. }
  53. [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
  54. CharSet = CharSet.Unicode, ExactSpelling = true,
  55. CallingConvention = CallingConvention.StdCall)]
  56. private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
  57. [DllImport("user32.dll", SetLastError = true)]
  58. private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  59. [DllImport("user32.dll", SetLastError = true)]
  60. private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
  61. [DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
  62. private static extern long GetWindowLong(IntPtr hwnd, int nIndex);
  63. [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
  64. private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
  65. [DllImport("user32.dll", SetLastError = true)]
  66. private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
  67. [DllImport("user32.dll", SetLastError = true)]
  68. private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
  69. [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
  70. private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
  71. private const int SWP_NOOWNERZORDER = 0x200;
  72. private const int SWP_NOREDRAW = 0x8;
  73. private const int SWP_NOZORDER = 0x4;
  74. private const int SWP_SHOWWINDOW = 0x0040;
  75. private const int WS_EX_MDICHILD = 0x40;
  76. private const int SWP_FRAMECHANGED = 0x20;
  77. private const int SWP_NOACTIVATE = 0x10;
  78. private const int SWP_ASYNCWINDOWPOS = 0x4000;
  79. private const int SWP_NOMOVE = 0x2;
  80. private const int SWP_NOSIZE = 0x1;
  81. private const int GWL_STYLE = (-16);
  82. private const int WS_VISIBLE = 0x10000000;
  83. private const int WM_CLOSE = 0x10;
  84. private const int WS_CHILD = 0x40000000;
  85. /// <summary>
  86. /// Force redraw of control when size changes
  87. /// </summary>
  88. /// <param name="e">Not used</param>
  89. protected override void OnSizeChanged(EventArgs e)
  90. {
  91. this.Invalidate();
  92. base.OnSizeChanged(e);
  93. }
  94. /// <summary>
  95. /// Creeate control when visibility changes
  96. /// </summary>
  97. /// <param name="e">Not used</param>
  98. protected override void OnVisibleChanged(EventArgs e)
  99. {
  100. // If control needs to be initialized/created
  101. if (created == false)
  102. {
  103. // Mark that control is created
  104. created = true;
  105. // Initialize handle value to invalid
  106. appWin = IntPtr.Zero;
  107. // Start the remote application
  108. Process p = null;
  109. try
  110. {
  111. // Start the process
  112. p = System.Diagnostics.Process.Start(this.exeName);
  113. // Wait for process to be created and enter idle condition
  114. p.WaitForInputIdle();
  115. // Get the main handle
  116. appWin = p.MainWindowHandle;
  117. }
  118. catch (Exception ex)
  119. {
  120. MessageBox.Show(this, ex.Message, "Error");
  121. }
  122. // Put it into this form
  123. SetParent(appWin, this.Handle);
  124. // Remove border and whatnot
  125. SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
  126. // Move the window to overlay it on this window
  127. MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
  128. }
  129. base.OnVisibleChanged(e);
  130. }
  131. /// <summary>
  132. ///
  133. /// </summary>
  134. /// <param name="e"></param>
  135. protected override void OnHandleDestroyed(EventArgs e)
  136. {
  137. // Stop the application
  138. if (appWin != IntPtr.Zero)
  139. {
  140. // Post a colse message
  141. PostMessage(appWin, WM_CLOSE, 0, 0);
  142. // Delay for it to get the message
  143. System.Threading.Thread.Sleep(1000);
  144. // Clear internal handle
  145. appWin = IntPtr.Zero;
  146. }
  147. base.OnHandleDestroyed(e);
  148. }
  149. /// <summary>
  150. /// Update display of the executable
  151. /// </summary>
  152. /// <param name="e">Not used</param>
  153. protected override void OnResize(EventArgs e)
  154. {
  155. if (this.appWin != IntPtr.Zero)
  156. {
  157. MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
  158. }
  159. base.OnResize(e);
  160. }
  161. }
  162. }