我在winform上方一个button和一个textbox其中button负责关闭窗体然后textbox的causevalidated属性为默认值true用户在textbox中输入内容点button关闭窗体的时候,由于焦点从textbox向外转移,所以会自动触发textbox的validating事件我现在想实现在点button关闭窗体或直接点窗体右上角关闭按钮关闭窗体的时候不执行textbox的validating事件怎么实现?我看到validating事件中有一个canceleventargs参数是一个事件类型参数能否通过这个参数来判断事件的类型或判断事件是由哪个控件执行的
如果可以判断这个,我就可以在validating事件中进行判断来设置e.cancel的值

解决方案 »

  1.   

    个人感觉是不好实现
    是先TextBox是去焦点,再执行Button事件
    帮你顶一下
      

  2.   

            private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
            {            
                MessageBox.Show("S");
            }        private const int WM_CLOSE = 0x0010;
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_CLOSE)
                {
                    textBox1.CausesValidation = false;
                }
                base.WndProc(ref m);
            }        private void button1_Click(object sender, EventArgs e)
            {
                this.Close();
            }
      

  3.   

    谢谢楼楼上的。我以前使用delphi的,对消息知道一些,但还不知道C#也可以直接处理消息。再次谢谢!
      

  4.   

    private bool closing = false;
    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        e.Cancel = !closing & string.IsNullOrEmpty(((TextBox)sender).Text);
    }private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        closing = false;
    }protected override void WndProc(ref Message m)
    {
        const int WM_CLOSE = 0x0010;
        switch (m.Msg)
        {
            case WM_CLOSE:
                closing = true;
                break;
        }
        base.WndProc(ref m);
    }
      

  5.   

    先打个日志就知道执行次序:
    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        Console.WriteLine("textBox1_Validating");
    }private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        Console.WriteLine("Form1_FormClosing");
    }protected override void WndProc(ref Message m)
    {
        const int WM_CLOSE = 0x0010;
        switch (m.Msg)
        {
            case WM_CLOSE:
                Console.WriteLine("WM_CLOSE");
                break;
        }
        base.WndProc(ref m);
    }
    WM_CLOSE
    textBox1_Validating
    Form1_FormClosing
      

  6.   

    to zenghd  有个问题,老大  我看到你是重载了窗口过程,窗口过程负责处理所有发送到窗口的消息,然后转发到操作系统的消息队列  我也按照你写的方式重新写了wndproc的实现,针对自定义消息wm_close做了捕捉处理  但当在textbox中输入了内容,并将焦点转移开的时候,首先是发出标识validating的消息,由这个消息触发validating事件的发生  在发出标识validating的消息之前,转移焦点动作是不会发出wm_close消息的,所以这里的wm_close重载不起作用
     
      有没有办法可以解决?
      

  7.   

    你都没有关闭窗体,当然不会有WM_CLOSE
      

  8.   

    to zenghd  我在textbox中输入内容后直接点窗体关闭按钮,还是关不了
      

  9.   

            /// <summary>
            /// 定义窗口关闭消息WM_CLOSE
            /// </summary>
            private const int WM_CLOSE = 0X0010;        /// <summary>
            /// 重载窗体的WndProc窗口过程
            /// </summary>
            /// <param name="aMsg"></param>
            protected override void WndProc(ref Message aMsg)
            {
                if (aMsg .Msg ==WM_CLOSE)
                {
                    if (this.txtbxDepaName.CausesValidation == true)
                    {
                        this.txtbxDepaName.CausesValidation = false;
                    }
                }
                else
                {
                    if (this.txtbxDepaName.CausesValidation == false)
                    {
                        this.txtbxDepaName.CausesValidation = true;
                    }
                }
                base.WndProc (ref aMsg);
            }        /// <summary>
            /// 焦点离开文本框txtbxDepaName触发校验事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void txtbxDepaName_Validating(object sender, CancelEventArgs e)
            {
                if (txtbxDepaName.Text.Trim().Length > 0)
                {
                    if (gIntfDataValidator.IsChineseCharacter(this.txtbxDepaName.Text.Trim()) == false)
                    {
                        e.Cancel = true;  //不要使用txtbxDepaName.Focus();,效率低
                    }
                }
            }        /// <summary>
            /// 点击按钮【关闭】关闭当前部门添加界面
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnClose_Click(object sender, EventArgs e)
            {
                gFrmController.CloseForm(this);
            }
      

  10.   

                if (aMsg .Msg ==WM_CLOSE)
                {
                    if (this.txtbxDepaName.CausesValidation == true)
                    {
                        this.txtbxDepaName.CausesValidation = false;
                    }
                }
                else
                {
                    if (this.txtbxDepaName.CausesValidation == false)
                    {
                        this.txtbxDepaName.CausesValidation = true;
                    }
                } 窗体关闭的时候除了WM_CLOSE还有其他消息,你这个else写得太想当然了。private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        e.Cancel = string.IsNullOrEmpty(((TextBox)sender).Text);
    }private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        textBox1.CausesValidation = true;
    }protected override void WndProc(ref Message m)
    {
        const int WM_CLOSE = 0x0010;
        switch (m.Msg)
        {
            case WM_CLOSE:
                textBox1.CausesValidation = false;
                break;
        }
        base.WndProc(ref m);
    }
      

  11.   

            protected override void WndProc(ref Message aMsg) 
            { 
                if (aMsg .Msg ==WM_CLOSE) 
                { 
                    if (this.txtbxDepaName.CausesValidation == true) 
                    { 
                        this.txtbxDepaName.CausesValidation = false; 
                    } 
                } 
                else 
                { 
                    if (this.txtbxDepaName.CausesValidation == false) 
                    { 
                        this.txtbxDepaName.CausesValidation = true; 
                    } 
                } 
                base.WndProc (ref aMsg); 
            } 我在最后是由集成基类窗口过程的语句的
      

  12.   

    另外,一句代码的事情被你写成这样多!!
                if (aMsg .Msg ==WM_CLOSE)
                {
                    if (this.txtbxDepaName.CausesValidation == true)
                    {
                        this.txtbxDepaName.CausesValidation = false;
                    }
                }
                else
                {
                    if (this.txtbxDepaName.CausesValidation == false)
                    {
                        this.txtbxDepaName.CausesValidation = true;
                    }
                } this.txtbxDepaName.CausesValidation = aMsg .Msg != WM_CLOSE;
      

  13.   

    用zswang老大的方法,加标识判断
      

  14.   

    窗体的关系消息定义为WM_CLOSE那窗体上一个按钮BUTTON1的单击事件对应的消息如何定义?
      

  15.   

    示例截获子窗体的系统菜单消息
    参考如下代码:
    using System.Runtime.InteropServices;[DllImport("user32.dll")]
    public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
    public const uint GW_CHILD = 5;public class SubWindow : NativeWindow
    {
        protected override void WndProc(ref Message m)
        {
            const int WM_CONTEXTMENU = 0x007B;
            switch (m.Msg)
            {
                case WM_CONTEXTMENU: return;
            }
            base.WndProc(ref m);
        }
    }private void Form1_Load(object sender, EventArgs e)
    {
        SubWindow vSubWindow = new SubWindow();
        
        vSubWindow.AssignHandle(GetWindow(comboBox1.Handle, GW_CHILD));
    }