Browse Source

添加嵌入窗口,准备制作自定义控件

yuzhengyang 8 years ago
parent
commit
b74713c845

+ 24 - 0
Fork.Net/Y.Skin/Y.Skin.csproj

@@ -43,6 +43,18 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="YoPanel\EmbedArticlePanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="YoPanel\EmbedArticlePanel.Designer.cs">
+      <DependentUpon>EmbedArticlePanel.cs</DependentUpon>
+    </Compile>
+    <Compile Include="YoPanel\EmbedPanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="YoPanel\EmbedPanel.Designer.cs">
+      <DependentUpon>EmbedPanel.cs</DependentUpon>
+    </Compile>
     <Compile Include="YoPanel\FlexiblePanel.cs">
       <SubType>Component</SubType>
     </Compile>
@@ -51,8 +63,20 @@
     </Compile>
   </ItemGroup>
   <ItemGroup>
+    <Folder Include="YoCtrl\" />
     <Folder Include="YoForm\IrregularForm\" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Y.Utils\Y.Utils.csproj">
+      <Project>{5b8eeec7-aeb5-407d-9dc1-1c59e53f78d5}</Project>
+      <Name>Y.Utils</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="YoPanel\EmbedPanel.resx">
+      <DependentUpon>EmbedPanel.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

+ 36 - 0
Fork.Net/Y.Skin/YoPanel/EmbedArticlePanel.Designer.cs

@@ -0,0 +1,36 @@
+namespace Y.Skin.YoPanel
+{
+    partial class EmbedArticlePanel
+    {
+        /// <summary> 
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 组件设计器生成的代码
+
+        /// <summary> 
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+        }
+
+        #endregion
+    }
+}

+ 202 - 0
Fork.Net/Y.Skin/YoPanel/EmbedArticlePanel.cs

@@ -0,0 +1,202 @@
+//############################################################
+//      quote:SmileWei.EmbeddedApp
+//      https://github.com/yuzhengyang
+//      author:yuzhengyang
+//############################################################
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.IO;
+
+namespace Y.Skin.YoPanel
+{
+    public partial class EmbedArticlePanel : Panel
+    {
+
+        /// <summary>
+        /// Track if the application has been created
+        /// </summary>
+        bool created = false;
+
+        /// <summary>
+        /// Handle to the application Window
+        /// </summary>
+        IntPtr appWin;
+
+        /// <summary>
+        /// The name of the exe to launch
+        /// </summary>
+        private string exeName = "";
+
+        /// <summary>
+        /// Get/Set if we draw the tick marks
+        /// </summary>
+        [
+        Category("Data"),
+        Description("Name of the executable to launch"),
+        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
+        ]
+        public string ExeName
+        {
+            get
+            {
+                return exeName;
+            }
+            set
+            {
+                exeName = value;
+            }
+        }
+
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public EmbedArticlePanel()
+        {
+        }
+
+
+        [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
+             CharSet = CharSet.Unicode, ExactSpelling = true,
+             CallingConvention = CallingConvention.StdCall)]
+        private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
+
+        [DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
+        private static extern long GetWindowLong(IntPtr hwnd, int nIndex);
+
+        [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
+        private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
+
+        [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
+        private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
+
+        private const int SWP_NOOWNERZORDER = 0x200;
+        private const int SWP_NOREDRAW = 0x8;
+        private const int SWP_NOZORDER = 0x4;
+        private const int SWP_SHOWWINDOW = 0x0040;
+        private const int WS_EX_MDICHILD = 0x40;
+        private const int SWP_FRAMECHANGED = 0x20;
+        private const int SWP_NOACTIVATE = 0x10;
+        private const int SWP_ASYNCWINDOWPOS = 0x4000;
+        private const int SWP_NOMOVE = 0x2;
+        private const int SWP_NOSIZE = 0x1;
+        private const int GWL_STYLE = (-16);
+        private const int WS_VISIBLE = 0x10000000;
+        private const int WM_CLOSE = 0x10;
+        private const int WS_CHILD = 0x40000000;
+
+        /// <summary>
+        /// Force redraw of control when size changes
+        /// </summary>
+        /// <param name="e">Not used</param>
+        protected override void OnSizeChanged(EventArgs e)
+        {
+            this.Invalidate();
+            base.OnSizeChanged(e);
+        }
+
+
+        /// <summary>
+        /// Creeate control when visibility changes
+        /// </summary>
+        /// <param name="e">Not used</param>
+        protected override void OnVisibleChanged(EventArgs e)
+        {
+
+            // If control needs to be initialized/created
+            if (created == false)
+            {
+
+                // Mark that control is created
+                created = true;
+
+                // Initialize handle value to invalid
+                appWin = IntPtr.Zero;
+
+                // Start the remote application
+                Process p = null;
+                try
+                {
+
+                    // Start the process
+                    p = System.Diagnostics.Process.Start(this.exeName);
+
+                    // Wait for process to be created and enter idle condition
+                    p.WaitForInputIdle();
+
+                    // Get the main handle
+                    appWin = p.MainWindowHandle;
+                }
+                catch (Exception ex)
+                {
+                    MessageBox.Show(this, ex.Message, "Error");
+                }
+                // Put it into this form
+                SetParent(appWin, this.Handle);
+
+                // Remove border and whatnot
+                SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
+
+                // Move the window to overlay it on this window
+                MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
+            }
+
+            base.OnVisibleChanged(e);
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="e"></param>
+        protected override void OnHandleDestroyed(EventArgs e)
+        {
+            // Stop the application
+            if (appWin != IntPtr.Zero)
+            {
+
+                // Post a colse message
+                PostMessage(appWin, WM_CLOSE, 0, 0);
+
+                // Delay for it to get the message
+                System.Threading.Thread.Sleep(1000);
+
+                // Clear internal handle
+                appWin = IntPtr.Zero;
+
+            }
+
+            base.OnHandleDestroyed(e);
+        }
+
+
+        /// <summary>
+        /// Update display of the executable
+        /// </summary>
+        /// <param name="e">Not used</param>
+        protected override void OnResize(EventArgs e)
+        {
+            if (this.appWin != IntPtr.Zero)
+            {
+                MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
+            }
+            base.OnResize(e);
+        }
+
+    }
+}

+ 39 - 0
Fork.Net/Y.Skin/YoPanel/EmbedPanel.Designer.cs

@@ -0,0 +1,39 @@
+namespace Y.Skin.YoPanel
+{
+    partial class EmbedPanel
+    {
+        /// <summary> 
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 组件设计器生成的代码
+
+        /// <summary> 
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            //this.SuspendLayout();
+            //this.Name = "EmbedPanel";
+            //this.ResumeLayout(false);
+            components = new System.ComponentModel.Container();
+        }
+
+        #endregion
+    }
+}

+ 343 - 0
Fork.Net/Y.Skin/YoPanel/EmbedPanel.cs

@@ -0,0 +1,343 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Y.Skin.YoPanel
+{
+    public partial class EmbedPanel : Panel
+    {
+        Action<object, EventArgs> appIdleAction = null;
+        EventHandler appIdleEvent = null;
+        public EmbedPanel()
+        {
+            InitializeComponent();
+            appIdleAction = new Action<object, EventArgs>(Application_Idle);
+            appIdleEvent = new EventHandler(appIdleAction);
+        }
+
+        public EmbedPanel(IContainer container)
+        {
+            container.Add(this);
+            InitializeComponent();
+            appIdleAction = new Action<object, EventArgs>(Application_Idle);
+            appIdleEvent = new EventHandler(appIdleAction);
+        }
+        /// <summary>
+        /// 将属性<code>AppFilename</code>指向的应用程序打开并嵌入此容器
+        /// </summary>
+        public void Start()
+        {
+            if (m_AppProcess != null)
+            {
+                Stop();
+            }
+            try
+            {
+                ProcessStartInfo info = new ProcessStartInfo(this.m_AppFilename);
+                info.UseShellExecute = true;
+                info.WindowStyle = ProcessWindowStyle.Minimized;
+                //info.WindowStyle = ProcessWindowStyle.Hidden;
+                m_AppProcess = Process.Start(info);
+                // Wait for process to be created and enter idle condition
+                m_AppProcess.WaitForInputIdle();
+                //todo:下面这两句会引发 NullReferenceException 异常,不知道怎么回事                
+                //m_AppProcess.Exited += new EventHandler(m_AppProcess_Exited);
+                //m_AppProcess.EnableRaisingEvents = true;
+                Application.Idle += appIdleEvent;
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(this, string.Format("{1}{0}{2}{0}{3}"
+                    , Environment.NewLine
+                    , "*" + ex.ToString()
+                    , "*StackTrace:" + ex.StackTrace
+                    , "*Source:" + ex.Source
+                    ), "内嵌程序加载失败");
+                if (m_AppProcess != null)
+                {
+                    if (!m_AppProcess.HasExited)
+                        m_AppProcess.Kill();
+                    m_AppProcess = null;
+                }
+            }
+
+        }
+        /// <summary>
+        /// 确保应用程序嵌入此容器
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        void Application_Idle(object sender, EventArgs e)
+        {
+            if (this.m_AppProcess == null || this.m_AppProcess.HasExited)
+            {
+                this.m_AppProcess = null;
+                Application.Idle -= appIdleEvent;
+                return;
+            }
+            if (m_AppProcess.MainWindowHandle == IntPtr.Zero) return;
+            Application.Idle -= appIdleEvent;
+            EmbedProcess(m_AppProcess, this);
+            //ShowWindow(m_AppProcess.MainWindowHandle, SW_SHOWNORMAL);
+            //var parent = GetParent(m_AppProcess.MainWindowHandle);//你妹,不管用,全是0
+            //if (parent == this.Handle)
+            //{
+            //    Application.Idle -= appIdleEvent;
+            //}
+        }
+        /// <summary>
+        /// 应用程序结束运行时要清除这里的标识
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        void m_AppProcess_Exited(object sender, EventArgs e)
+        {
+            m_AppProcess = null;
+        }
+        //public void Start(string appFilename)
+        //{
+        //    this.AppFilename = AppFilename;
+        //    Start();
+        //}
+        /// <summary>
+        /// 将属性<code>AppFilename</code>指向的应用程序关闭
+        /// </summary>
+        public void Stop()
+        {
+            if (m_AppProcess != null)// && m_AppProcess.MainWindowHandle != IntPtr.Zero)
+            {
+                try
+                {
+                    if (!m_AppProcess.HasExited)
+                        m_AppProcess.Kill();
+                }
+                catch (Exception)
+                {
+                }
+                m_AppProcess = null;
+            }
+        }
+
+        protected override void OnHandleDestroyed(EventArgs e)
+        {
+            Stop();
+            base.OnHandleDestroyed(e);
+        }
+
+        protected override void OnResize(EventArgs eventargs)
+        {
+            if (m_AppProcess != null)
+            {
+                MoveWindow(m_AppProcess.MainWindowHandle, 0, 0, this.Width, this.Height, true);
+            }
+            base.OnResize(eventargs);
+        }
+
+        protected override void OnSizeChanged(EventArgs e)
+        {
+            this.Invalidate();
+            base.OnSizeChanged(e);
+        }
+
+        #region 属性
+        /// <summary>
+        /// application process
+        /// </summary>
+        Process m_AppProcess = null;
+        public Process AppProcess
+        {
+            get { return this.m_AppProcess; }
+            set { this.m_AppProcess = value; }
+        }
+
+        /// <summary>
+        /// 要嵌入的程序文件名
+        /// </summary>
+        private string m_AppFilename = "";
+        /// <summary>
+        /// 要嵌入的程序文件名
+        /// </summary>
+        [Category("Data")]
+        [Description("要嵌入的程序文件名")]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+        //[Editor(typeof(AppFilenameEditor), typeof(UITypeEditor))]
+        public string AppFilename
+        {
+            get
+            {
+                return m_AppFilename;
+            }
+            set
+            {
+                if (value == null || value == m_AppFilename) return;
+                var self = Application.ExecutablePath;
+                if (value.ToLower() == self.ToLower())
+                {
+                    MessageBox.Show("不能自己嵌入自己!", "SmileWei.EmbeddedApp");
+                    return;
+                }
+                if (!value.ToLower().EndsWith(".exe"))
+                {
+                    MessageBox.Show("要嵌入的文件扩展名不是exe!", "SmileWei.EmbeddedApp");
+                }
+                if (!File.Exists(value))
+                {
+                    MessageBox.Show("要嵌入的程序不存在!", "SmileWei.EmbeddedApp");
+                    return;
+                }
+                m_AppFilename = value;
+            }
+        }
+        /// <summary>
+        /// 标识内嵌程序是否已经启动
+        /// </summary>
+        public bool IsStarted { get { return (this.m_AppProcess != null); } }
+
+        #endregion 属性
+
+        #region Win32 API
+        [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
+             CharSet = CharSet.Unicode, ExactSpelling = true,
+             CallingConvention = CallingConvention.StdCall)]
+        private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        public static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
+
+        [DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
+        private static extern long GetWindowLong(IntPtr hwnd, int nIndex);
+
+        public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong)
+        {
+            if (IntPtr.Size == 4)
+            {
+                return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
+            }
+            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
+        }
+        [DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
+        public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, int dwNewLong);
+        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
+        public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, int dwNewLong);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
+
+        [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
+        private static extern bool PostMessage(IntPtr hwnd, uint Msg, uint wParam, uint lParam);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        private static extern IntPtr GetParent(IntPtr hwnd);
+        ///// <summary>
+        ///// ShellExecute(IntPtr.Zero, "Open", "C:/Program Files/TTPlayer/TTPlayer.exe", "", "", 1);
+        ///// </summary>
+        ///// <param name="hwnd"></param>
+        ///// <param name="lpOperation"></param>
+        ///// <param name="lpFile"></param>
+        ///// <param name="lpParameters"></param>
+        ///// <param name="lpDirectory"></param>
+        ///// <param name="nShowCmd"></param>
+        ///// <returns></returns>
+        //[DllImport("shell32.dll", EntryPoint = "ShellExecute")]
+        //public static extern int ShellExecute(
+        //IntPtr hwnd,
+        //string lpOperation,
+        //string lpFile,
+        //string lpParameters,
+        //string lpDirectory,
+        //int nShowCmd
+        //);
+        //[DllImport("kernel32.dll")]
+        //public static extern int OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); 
+        [DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]
+        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+
+
+        private const int SWP_NOOWNERZORDER = 0x200;
+        private const int SWP_NOREDRAW = 0x8;
+        private const int SWP_NOZORDER = 0x4;
+        private const int SWP_SHOWWINDOW = 0x0040;
+        private const int WS_EX_MDICHILD = 0x40;
+        private const int SWP_FRAMECHANGED = 0x20;
+        private const int SWP_NOACTIVATE = 0x10;
+        private const int SWP_ASYNCWINDOWPOS = 0x4000;
+        private const int SWP_NOMOVE = 0x2;
+        private const int SWP_NOSIZE = 0x1;
+        private const int GWL_STYLE = (-16);
+        private const int WS_VISIBLE = 0x10000000;
+        private const int WM_CLOSE = 0x10;
+        private const int WS_CHILD = 0x40000000;
+
+        private const int SW_HIDE = 0; //{隐藏, 并且任务栏也没有最小化图标}
+        private const int SW_SHOWNORMAL = 1; //{用最近的大小和位置显示, 激活}
+        private const int SW_NORMAL = 1; //{同 SW_SHOWNORMAL}
+        private const int SW_SHOWMINIMIZED = 2; //{最小化, 激活}
+        private const int SW_SHOWMAXIMIZED = 3; //{最大化, 激活}
+        private const int SW_MAXIMIZE = 3; //{同 SW_SHOWMAXIMIZED}
+        private const int SW_SHOWNOACTIVATE = 4; //{用最近的大小和位置显示, 不激活}
+        private const int SW_SHOW = 5; //{同 SW_SHOWNORMAL}
+        private const int SW_MINIMIZE = 6; //{最小化, 不激活}
+        private const int SW_SHOWMINNOACTIVE = 7; //{同 SW_MINIMIZE}
+        private const int SW_SHOWNA = 8; //{同 SW_SHOWNOACTIVATE}
+        private const int SW_RESTORE = 9; //{同 SW_SHOWNORMAL}
+        private const int SW_SHOWDEFAULT = 10; //{同 SW_SHOWNORMAL}
+        private const int SW_MAX = 10; //{同 SW_SHOWNORMAL}
+
+        //const int PROCESS_ALL_ACCESS = 0x1F0FFF;
+        //const int PROCESS_VM_READ = 0x0010;
+        //const int PROCESS_VM_WRITE = 0x0020;     
+        #endregion Win32 API
+
+
+        public void EmbedAgain()
+        {
+            EmbedProcess(m_AppProcess, this);
+            MessageBox.Show("完毕");
+        }
+        /// <summary>
+        /// 将指定的程序嵌入指定的控件
+        /// </summary>
+        private void EmbedProcess(Process app, Control control)
+        {
+            // Get the main handle
+            if (app == null || app.MainWindowHandle == IntPtr.Zero || control == null) return;
+            try
+            {
+                // Put it into this form
+                SetParent(app.MainWindowHandle, control.Handle);
+            }
+            catch (Exception)
+            { }
+            try
+            {
+                // Remove border and whatnot               
+                SetWindowLong(new HandleRef(this, app.MainWindowHandle), GWL_STYLE, WS_VISIBLE);
+            }
+            catch (Exception)
+            { }
+            try
+            {
+                // Move the window to overlay it on this window
+                MoveWindow(app.MainWindowHandle, 0, 0, control.Width, control.Height, true);
+            }
+            catch (Exception)
+            { }
+        }
+    }
+}

+ 120 - 0
Fork.Net/Y.Skin/YoPanel/EmbedPanel.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 21 - 7
Fork.Net/Y.Test/Form1.Designer.cs

@@ -28,6 +28,8 @@
         /// </summary>
         private void InitializeComponent()
         {
+            this.components = new System.ComponentModel.Container();
+            this.embedPanel1 = new Y.Skin.YoPanel.EmbedPanel(this.components);
             this.flexiblePanel1 = new Y.Skin.YoPanel.FlexiblePanel();
             this.listBox1 = new System.Windows.Forms.ListBox();
             this.label1 = new System.Windows.Forms.Label();
@@ -35,21 +37,31 @@
             this.flexiblePanel1.SuspendLayout();
             this.SuspendLayout();
             // 
+            // embedPanel1
+            // 
+            this.embedPanel1.AppFilename = "D:\\Soft\\LogReader\\logreader.exe";
+            this.embedPanel1.AppProcess = null;
+            this.embedPanel1.BackColor = System.Drawing.SystemColors.ActiveCaption;
+            this.embedPanel1.Location = new System.Drawing.Point(205, 15);
+            this.embedPanel1.Name = "embedPanel1";
+            this.embedPanel1.Size = new System.Drawing.Size(222, 157);
+            this.embedPanel1.TabIndex = 2;
+            // 
             // flexiblePanel1
             // 
             this.flexiblePanel1.Controls.Add(this.listBox1);
             this.flexiblePanel1.Controls.Add(this.label1);
             this.flexiblePanel1.Controls.Add(this.button1);
-            this.flexiblePanel1.Location = new System.Drawing.Point(109, 112);
+            this.flexiblePanel1.Location = new System.Drawing.Point(12, 12);
             this.flexiblePanel1.Name = "flexiblePanel1";
-            this.flexiblePanel1.Size = new System.Drawing.Size(516, 499);
+            this.flexiblePanel1.Size = new System.Drawing.Size(172, 369);
             this.flexiblePanel1.TabIndex = 0;
             // 
             // listBox1
             // 
             this.listBox1.FormattingEnabled = true;
             this.listBox1.ItemHeight = 12;
-            this.listBox1.Location = new System.Drawing.Point(66, 271);
+            this.listBox1.Location = new System.Drawing.Point(17, 200);
             this.listBox1.Name = "listBox1";
             this.listBox1.Size = new System.Drawing.Size(120, 88);
             this.listBox1.TabIndex = 2;
@@ -57,7 +69,7 @@
             // label1
             // 
             this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(111, 161);
+            this.label1.Location = new System.Drawing.Point(15, 45);
             this.label1.Name = "label1";
             this.label1.Size = new System.Drawing.Size(41, 12);
             this.label1.TabIndex = 1;
@@ -65,7 +77,7 @@
             // 
             // button1
             // 
-            this.button1.Location = new System.Drawing.Point(111, 69);
+            this.button1.Location = new System.Drawing.Point(17, 3);
             this.button1.Name = "button1";
             this.button1.Size = new System.Drawing.Size(75, 23);
             this.button1.TabIndex = 0;
@@ -76,10 +88,11 @@
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(1144, 727);
+            this.ClientSize = new System.Drawing.Size(780, 413);
+            this.Controls.Add(this.embedPanel1);
             this.Controls.Add(this.flexiblePanel1);
             this.Name = "Form1";
-            this.Text = "Form1";
+            this.Text = "D:\\Soft\\LogReader\\logreader.exe";
             this.Load += new System.EventHandler(this.Form1_Load);
             this.flexiblePanel1.ResumeLayout(false);
             this.flexiblePanel1.PerformLayout();
@@ -93,6 +106,7 @@
         private System.Windows.Forms.ListBox listBox1;
         private System.Windows.Forms.Label label1;
         private System.Windows.Forms.Button button1;
+        private Skin.YoPanel.EmbedPanel embedPanel1;
     }
 }
 

+ 9 - 9
Fork.Net/Y.Test/Form1.cs

@@ -1,11 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows.Forms;
 
 namespace Y.Test
@@ -15,11 +8,18 @@ namespace Y.Test
         public Form1()
         {
             InitializeComponent();
+            Application.Idle += Application_Idle;
+        }
+        void Application_Idle(object sender, EventArgs e)
+        {
+            if (embedPanel1.IsStarted)
+                MessageBox.Show(string.Format("{0}", embedPanel1.AppProcess.MainWindowHandle));
         }
-
         private void Form1_Load(object sender, EventArgs e)
         {
-            flexiblePanel1.InitMouseAndContolStyle();
+            //flexiblePanel1.InitMouseAndContolStyle();
+            //embedPanel1.AppFilename = @"D:\Temp\n.exe";
+            embedPanel1.Start();
         }
     }
 }

+ 1 - 0
Fork.Net/Y.Utils/WindowsUtils/InfoUtils/ShortcutTool.cs

@@ -2,6 +2,7 @@
 //      https://github.com/yuzhengyang
 //      author:yuzhengyang
 //############################################################
+using System.IO;
 using Y.Utils.IOUtils.PathUtils;
 
 namespace Y.Utils.WindowsUtils.InfoUtils