需要给整个应用程序的所有Form的显示进行拦截,然后动态修改显示窗体的样式和标题,请问怎样实现?
用AddMessageFilter()好像找不到对应的消息,就算找到了如果得到正在显示的窗体的实例?
 

解决方案 »

  1.   

    是的,显示前进行拦截
    Form2 frm=new Form2();  //这里已经实例化
    frm.Show();   //**********执行到这里的时候进行拦截
      

  2.   

    直接把设置标题什么的代码写在Load事件里面不就行了么,为什么要拦截这个??
      

  3.   

    @viewsonic2235
    整个应用程序中有几百个Form,如果每个都加上比较冗余,而且有部分Form在一些没有代码的DLL中,所以需要进行拦截.
      

  4.   

    如果你没有FormBase的话
    就只能用API修改~~~~
    到网上去找找,例子很多
      

  5.   

    那个皮肤我觉得应该是所有的都继承自一个基类,比如写一个基类MyForm : Form
    ,在MyForm里面重写OnLoad方法,然后所有自己写的Form都去继承这个MyForm
      

  6.   

    @lovefootball 
    用哪个API,能提供一点线索吗?
      

  7.   

    不知道VS2008里面的静态方法能不能改写Form的Show()的默认行为?
      

  8.   

    @viewsonic2235 
    皮肤控件不需要你有基类,只需要你在Main()方法中增加一行初始化皮肤控件的语句就可以了.
      

  9.   

    Hookusing System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Reflection;
    using System.Xml;
    using System.Runtime.InteropServices;
    namespace WindowsApplication3
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                HookMsg.Install();
            }       
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                HookMsg.Install();
            }        private void button1_Click(object sender, EventArgs e)
            {
                Form frm = new Form();
                frm.Text = "新建窗口!";
                frm.Show();
            }
        }
        public class HookMsg
        {        private const int WH_CBT = 0x5;
            private const int IDC_OK = 0x1;
            private const int IDC_Text = 0xFFFF;
            [DllImport("user32.dll")]
            protected static extern IntPtr SetWindowsHookEx(int code, HookProc func, IntPtr hInstance, int threadID);
            [DllImport("user32.dll")]
            protected static extern int UnhookWindowsHookEx(IntPtr hhook);
            [DllImport("user32.dll")]
            protected static extern int CallNextHookEx(IntPtr hhook, int code, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll")]
            protected static extern int GetWindowText(IntPtr hwnd, [Out]StringBuilder lpString, int nMaxCount);        [DllImport("user32.dll")]
            protected static extern int GetClassName(IntPtr hwnd, [Out]StringBuilder lpString, int nMaxCount);        [DllImport("user32.dll")]
            protected static extern int SetWindowText(IntPtr hWnd, string lpString);        [DllImport("user32.dll")]
            protected static extern IntPtr GetDlgItem(IntPtr hwnd, int id);
            [DllImport("User32")]
            protected static extern int SetDlgItemText(IntPtr hDlg, int nIDDlgItem, string lpString);
            [DllImport("user32.dll")]
            protected static extern int GetDlgItemText(IntPtr hDlg, int nIDDlgItem, [Out] StringBuilder lpString, int nMaxCount);        [DllImport("user32.dll", EntryPoint = "MessageBox")]
            protected static extern int _MessageBox(IntPtr hwnd, string text, string caption,
                int options);        [DllImport("user32.dll")]
            protected static extern IntPtr GetActiveWindow();        [DllImport("user32.dll")]
            protected static extern void DestroyWindow(IntPtr hwnd);
            private static System.IntPtr m_hhook;        public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);        protected static HookProc m_filterFunc;        static HookMsg()
            {
                if (m_filterFunc == null)
                    m_filterFunc = new HookProc(CoreHookProc);
            }        public static void Install()
            {            m_hhook = SetWindowsHookEx(WH_CBT, m_filterFunc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
            }        public static void Uninstall()
            {
                UnhookWindowsHookEx(m_hhook);
            }        //CallBack
            protected static int CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
            {
                if (code == 5)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Capacity = 255;
                    //Title
                    GetWindowText(wParam, sb, 255);
                    string strTitle = "jinjazz看到了:" + sb.ToString();
                    SetWindowText(wParam, strTitle);
                }
                return 0;
            }
        }
    }
      

  10.   

    @jinjazz 
    非常感谢!感觉成功了99%,还有两个小问题:
            protected static int CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
            {
                if (code == 5)
                {
                    //【问题1】:这里如何只被调用一次,感觉窗体每刷新一次,这里调用一次 ***
                    StringBuilder sb = new StringBuilder();
                    sb.Capacity = 255;
                    //Title
                    GetWindowText(wParam, sb, 255);
                    string strTitle = "jinjazz看到了:" + sb.ToString();
                    SetWindowText(wParam, strTitle);                //【问题2】:如何通过wParam得到对应窗体的实例?
                    Form frm = XXX(wParam); 
                    frm.其它属性 = Value;
                }
                return 0;
            }
      

  11.   

    问题1,可以把hook过的句柄都保存下来
    问题2,如果都是.net的可以用系统函数
     //CallBack        static System.Collections.Generic.List<IntPtr> listForms = new List<IntPtr>();
            protected static int CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
            {
                if (code == 5)
                {
                    //问题1
                    if (listForms.Contains(wParam))
                    {
                        return 0;
                    }
                    else
                    {
                        listForms.Add(wParam);
                    }
                    StringBuilder sb = new StringBuilder();
                    sb.Capacity = 255;
                    //Title
                    GetWindowText(wParam, sb, 255);
                    string strTitle = "jinjazz看到了:" + sb.ToString();
                    SetWindowText(wParam, strTitle);                //问题2
                    try
                    {
                        Form frm = Form.FromHandle(wParam) as Form;
                        frm.Size = new Size(100, 100);
                    }
                    catch { }
                }
                return 0;
            }
      

  12.   

    你可能还需要考虑messagebox的窗口,一个更加详细的例子,参考我的blog
    http://blog.csdn.net/jinjazz/archive/2007/11/21/1896625.aspx这段代码是我为一个大型成品系统写多语言版本时用的一个插件,只需要在主窗体里面载入这个翻译插件,然后设置挂钩,配合资源文件来翻译成品系统的所有ui控件,在Form.FromHandle得到窗体实例后,可以递归遍历其中的所有已知控件。
      

  13.   

    自己解决了
    问题一,自己设置一个标志位,问题二使用Control.FromHandle感谢大家的关注!
    感谢jinjazz的代码!!
      

  14.   

    @jinjazz 
    刚才没看见你上面的回复,我search了一下,用Control.FromHandle 可以实现.thanks!