none
C# 给窗体传参问题 RRS feed

  • 问题

  • 我做了一个Winform的程序。从Program.cs类Main中接收参数传给窗体Glsd。但是每次接收一次参数args时都要重新在运行一个新的实例Application.Run(glsd)能看到效果;能否不弹出新的Glsd,而是在原来Glsd中更新它的属性。

    static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { // bool ret; // System.Threading.Mutex mutex = new System.Threading.Mutex(true, Application.ProductName, out ret); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if(args!=null||args.Length!=0) { string strSBBH = args[0]; if (strSBBH.Equals("-1")) { Glsd glsd = new Glsd(); glsd.Id = strSBBH; Application.Run(glsd); }

    else if (strSBBH.Equals("-2"))
                    {
                        Glsd glsd = new Glsd();
                        glsd.Id = strSBBH;
                        Application.Run(glsd);
                    } } } }


    2012年8月15日 5:12

答案

  • public class Win32
    {
        [DllImport("User32.dll ")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll ")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
    
        [DllImport("User32.dll ")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
    
        public const int SW_MAXIMIZE = 3;
    
        public const int WM_COPYDATA = 0x004A;
    
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        public uint dwData;
        public uint cbData;
        public IntPtr lpData;
    }
    
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Process p = Process.GetProcesses().Where(o => o.MainWindowTitle == "Glsd").FirstOrDefault();
            if (p != null)
            {
    
                IntPtr strPtr = Marshal.StringToHGlobalAnsi(args[0]);
                COPYDATASTRUCT copyData;
                copyData.dwData = 0;
                copyData.cbData = (uint)Encoding.Default.GetByteCount(args[0].ToCharArray(), 0, args[0].Length);
                copyData.lpData = strPtr;
                IntPtr ptr = Marshal.AllocHGlobal((IntPtr)(Marshal.SizeOf(copyData)));
                Marshal.StructureToPtr(copyData, ptr, true);
                Win32.SendMessage(p.MainWindowHandle, Win32.WM_COPYDATA, -1, (int)ptr);
                Win32.ShowWindowAsync(p.MainWindowHandle, Win32.SW_MAXIMIZE);
                Win32.SetForegroundWindow(p.MainWindowHandle);
    
            }
            else
            {
                if (args == null || args.Length == 0)
                {
                    Application.Run(new Glsd());
                }
                else
                {
                    string strSBBH = args[0];
                    Glsd glsd = new Glsd();
                    glsd.Id = args[0];
                    Application.Run(glsd);
                }
            }
        }
    }
    
    public partial class Glsd : Form
    {
    
        #region 字段
        string id = null;
    
        public string Id
        {
            get { return id; }
            set { lbID.Text = "ID:"+ value; }
        }
        #endregion
    
        #region 构造函数
        public Glsd()
        {
            InitializeComponent();
        }
        #endregion
    
        #region 事件
        void Program_SetIdEvent(string id)
        {
            MessageBox.Show(id);
            Id = id;
        }
        #endregion
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_COPYDATA:
                    if (m.WParam != IntPtr.Zero)
                    {
                        COPYDATASTRUCT copyData = (COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)m.LParam, typeof(COPYDATASTRUCT));
                        if (copyData.lpData != IntPtr.Zero)
                            Id = Marshal.PtrToStringAnsi(copyData.lpData, (int)copyData.cbData);
                    }
                    break;
            }
            base.WndProc(ref m);
        }
    }
    

    • 已标记为答案 MaJiXiang 2012年8月15日 8:44
    2012年8月15日 8:32

全部回复

  • 可以。假设你有两个窗体,那么请在一个窗体中定义委托和事件,另外一个窗体捕获该事件,直接处理事件,接受传入的参数即可。

    请参考周雪峰版主的这个回答:

    http://cloud.csdn.net/a/20100727/277303.html


    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年8月15日 5:41
    版主
  • 我在Program中定义了委托和事件。在调用的窗体中注册了事件。但是接收到参数的时候EventHandler一直为NULL只有再次执行 Application.Run后EventHandler不为NULL。

    但是这样只有关闭窗体后,才执行事件中的内容。

    2012年8月15日 5:54
  • 我在Program中定义了委托和事件。在调用的窗体中注册了事件。但是接收到参数的时候EventHandler一直为NULL只有再次执行 Application.Run后EventHandler不为NULL。

    但是这样只有关闭窗体后,才执行事件中的内容。


    请给出你的代码,你的意图以及你做了什么?出错信息?

    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年8月15日 6:03
    版主
  • 意图:程序A调用程序B, 通过程序B  Program.cs类Main程序入口给B传参数args。当Main接收到args时,把args传到B程序的Glsd窗口中。

     Glsd glsd = new Glsd();
     glsd.Id = args[0];
     Application.Run(glsd);

    当A程序再次通过程序B,  Program.cs类Main传入参数时.能否直接更新B程序的Glsd窗口而不再 Application.Run(glsd);

    B程序代码:http://files.cnblogs.com/midcn/GlsdWin32.zip

    2012年8月15日 6:32
  • static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Process p = Process.GetProcesses().Where(o => o.MainWindowTitle == "Glsd").FirstOrDefault(); if (p != null) { Glsd glsd = Form.FromHandle(p.MainWindowHandle) as Glsd; glsd.Id = args.Length == 0 ? string.Empty : args[0]; glsd.Activate();

    } else { if (args == null || args.Length == 0) { Application.Run(new Glsd()); } else { string strSBBH = args[0]; Glsd glsd = new Glsd(); glsd.Id = args[0]; Application.Run(glsd); } } } }



    • 已编辑 梁猛 2012年8月15日 7:43
    2012年8月15日 7:38
  • Form.FromHandle(p.MainWindowHandle)as Glsd

    这一句获取为NULL,是什么情况?谢谢
    2012年8月15日 8:00
  • 不好意思,跨进程的话Form.FromHandle不可以
    2012年8月15日 8:12
  • 嗯,我这是两个程序传参。
    2012年8月15日 8:15
  • public class Win32
    {
        [DllImport("User32.dll ")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll ")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
    
        [DllImport("User32.dll ")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
    
        public const int SW_MAXIMIZE = 3;
    
        public const int WM_COPYDATA = 0x004A;
    
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        public uint dwData;
        public uint cbData;
        public IntPtr lpData;
    }
    
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Process p = Process.GetProcesses().Where(o => o.MainWindowTitle == "Glsd").FirstOrDefault();
            if (p != null)
            {
    
                IntPtr strPtr = Marshal.StringToHGlobalAnsi(args[0]);
                COPYDATASTRUCT copyData;
                copyData.dwData = 0;
                copyData.cbData = (uint)Encoding.Default.GetByteCount(args[0].ToCharArray(), 0, args[0].Length);
                copyData.lpData = strPtr;
                IntPtr ptr = Marshal.AllocHGlobal((IntPtr)(Marshal.SizeOf(copyData)));
                Marshal.StructureToPtr(copyData, ptr, true);
                Win32.SendMessage(p.MainWindowHandle, Win32.WM_COPYDATA, -1, (int)ptr);
                Win32.ShowWindowAsync(p.MainWindowHandle, Win32.SW_MAXIMIZE);
                Win32.SetForegroundWindow(p.MainWindowHandle);
    
            }
            else
            {
                if (args == null || args.Length == 0)
                {
                    Application.Run(new Glsd());
                }
                else
                {
                    string strSBBH = args[0];
                    Glsd glsd = new Glsd();
                    glsd.Id = args[0];
                    Application.Run(glsd);
                }
            }
        }
    }
    
    public partial class Glsd : Form
    {
    
        #region 字段
        string id = null;
    
        public string Id
        {
            get { return id; }
            set { lbID.Text = "ID:"+ value; }
        }
        #endregion
    
        #region 构造函数
        public Glsd()
        {
            InitializeComponent();
        }
        #endregion
    
        #region 事件
        void Program_SetIdEvent(string id)
        {
            MessageBox.Show(id);
            Id = id;
        }
        #endregion
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_COPYDATA:
                    if (m.WParam != IntPtr.Zero)
                    {
                        COPYDATASTRUCT copyData = (COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)m.LParam, typeof(COPYDATASTRUCT));
                        if (copyData.lpData != IntPtr.Zero)
                            Id = Marshal.PtrToStringAnsi(copyData.lpData, (int)copyData.cbData);
                    }
                    break;
            }
            base.WndProc(ref m);
        }
    }
    

    • 已标记为答案 MaJiXiang 2012年8月15日 8:44
    2012年8月15日 8:32
  • 佩服啊。

    2012年8月15日 8:44
  • 你好梁猛,我还有个疑问。就是我在Main中调用属性都可以在一个窗体中更新。可是调用glsd窗体下的方法却只能执行一次。例如我把id传给

                    string strSBBH = args[0];
                    Glsd glsd = new Glsd();
                    glsd.GetID(strSBBH);//这个方法
                    Application.Run(glsd);
    
    2012年8月15日 11:42
  • 你的GetID方法的代码怎么写的,发上来看看呢。
    2012年8月15日 12:56
  • 类似操作WinForm控件的一些功能大部分都是操作WebBrowser的。
                        HtmlDocument doc = webBrowser1.Document;
                        doc.InvokeScript("getID", new object[] { 10002 });
                        HtmlElement panelElement = doc.GetElementById("Panel1");
                        HtmlElement btnUpdate = doc.GetElementById("btnUpdate");
                        HtmlElement imggl = doc.GetElementById("imggl");
                        if (panelElement != null && btnUpdate != null && imggl != null)
                        {
                            panelElement.OuterHtml = "";
                            imggl.OuterHtml = "";
                            btnUpdate.OuterHtml = "";
                        }

    2012年8月15日 13:00
  • 你在窗体还没呈现之前调用方法,整个窗体还没有显现,所以此时WebBrowser的Document还没有加载,调用这个方法也就没什么意义了。
    2012年8月15日 13:15
  • 写在窗体呈现之后调用方法会一直停留在Application.Run,只有关闭程序时,才能执行后面的代码。

    2012年8月15日 13:26
  • 如果要窗体第一次呈现是调用,可以写在窗体的Shown事件中。如果是WebBrowser加载完调用,最好写在WebBrowser的DocumentCompleted事件中
    2012年8月15日 13:34
  • 刚才我测试了一下。现在的窗体从第一次打开以后状态一直保持着,后面再从Main传入的参数就无法触发这些事件了。现在最好能每次Main接收到参数传给glsd。然后在glsd中根据获得的ID加载对应的页面。
    2012年8月15日 14:09
  • 那你应该在Id的Set方法里调用加载页面的方法。

    2012年8月16日 1:28
  • 非常感谢,我在之前使用的是Timer。在页面加载完毕后用Timer每隔一段时间监测一下Id是否有变化
    2012年8月16日 2:18