c#定时器无效了?

时间:2022-09-04 00:10:47
我发现我对按钮重绘的那段代码会影响我设置的定时器的作用,在butto_paint中的代码同时注释后才可以正常使用
我原来已经写好了窗体像QQ一样可以隐藏到桌面上方的功能,用timer进行检测位置,今天写了新的功能,内容也比较多,然后我发现timer的tick事件却莫名没用了,我检查enable是true(一开始设置好了的),检查它的所有引用,没有发现使它成为false的代码,从新写过这个功能,也出现一样的情况,至于我原来为一个按钮添加的背景图片也无法正常的加载,总是要在我拖动一下窗体才可以显现,经过我对备份的文件进行添加我后来写上的代码,我发现最后在添加了对按钮的重绘后就会出现上面的两个问题

12 个解决方案

#1


估计你使用的是Form的Timer,这种Timer是基于Windows消息的,而Windows消息有可能被抛弃,这样就可能导致你的Tick处理不能被触发。另外你提到了做了重绘,重绘的机制设计不对的话有可能导致OnPaint的时候调用刷新引起新的重绘,这样就好像一个死循环,Timer不起作用和图片显示不出来也就正常了。
最好把代码贴一下

#2


 private void button2_Paint(object sender, PaintEventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = button2.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);     //绘制退出按钮形状
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            button2.Region = new System.Drawing.Region(buttonPath);
            
            Rectangle myrect2 = button2.ClientRectangle;
            Bitmap mybmp = new Bitmap(myrect2.Width, myrect2.Height);
            Graphics g2 = Graphics.FromImage(mybmp);
            LinearGradientBrush mybrush = new LinearGradientBrush(myrect2, Color.Yellow, Color.YellowGreen, LinearGradientMode.Horizontal);   //渐变色泽按钮
            g2.FillRectangle(mybrush, myrect2);
            button2.BackgroundImage = mybmp;
        }

        private void button3_Paint(object sender, PaintEventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = button3.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);     //绘制退出按钮形状
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            button3.Region = new System.Drawing.Region(buttonPath);

            Rectangle myrect3 = button3.ClientRectangle;
            Bitmap mybmp3 = new Bitmap(myrect3.Width, myrect3.Height);
            Graphics g3 = Graphics.FromImage(mybmp3);
            LinearGradientBrush mybrush3 = new LinearGradientBrush(myrect3, Color.Yellow, Color.YellowGreen, LinearGradientMode.Horizontal);   //渐变色泽按钮
            g3.FillRectangle(mybrush3, myrect3);
            button3.BackgroundImage = mybmp3;
        }  

#3


问题出在
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp;
在重载OnPaint或者响应Paint消息的处理中不要使用会引起刷新界面操作,设置背景图片会引起界面刷新,界面刷新又会进入到Paint消息的处理里面,如此循环就是问题所在了。
个人建议:如果你响应需要重载OnPaint或者响应Paint消息来达到界面自定义的要求,那么最好这个控件的所有绘制都用绘图来完成而不是用控件的属性。另外,你这样响应Paint消息不是很好,最好封装一个Button类。

#4


你在button2_Paint中几个数就明白我的意思了,两三秒会运行500-600次,而在正常的情况下只有界面刷新才会运行一次。

#5


你在button2_Paint中计个数就明白我的意思了,两三秒会运行500-600次,而在正常的情况下只有界面刷新才会运行一次。

#6


我断点后发现得是它只有在我拖动窗体出现重绘的时候才有运行这段代码,并没有说两三秒会运行500-600次

#7


我没遇到过定时器失效的问题。

#8


首先你要理解Paint事件是在什么时候触发的
我举个datagridview显示数据的例子吧
比如你在form的load事件里 给dgv绑定了数据源 
然后你再dgv的paint事件里去查看dgv.rows的话
实际上是有数据的 但是这个时候dgv上实际上是没有一行数据显示
它需要Paint事件执行完毕以后 才会绘制出数据到dgv上
同理 你的timer放在button的paint事件里 也只有在这个button绘制好以后才会执行timer的操作

所以 你的窗体和窗体的控件 还在绘制的时候 怎么可能出现你timer里控制的那些动作呢

#9


我使用你给的代码做的试验,问题就是我提到的那两句给背景图片赋值的语句上,去掉就没有问题了。
如果不改变你现在的重绘逻辑,我建议你在Form_Load中给按钮添加背景图片,其他不用变就可以解决问题了。
但是还是建议你封装Button类。
你的Timer做了什么操作?与界面相关吗?如果不相关就与你提的问题无关。

#10


我之前回帖不知道为什么不显示,
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp3;
这两句会引起控件刷新从而调用重绘,这样相当于你的程序进到一个循环中,处理重绘->刷新->处理重绘...,你显示有问题就是这个原因。至于Timer不执行也是由于这个原因引起的。

#11


果然我把
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp3;
从paint事件中移出来到load事件中相应的问题就解决了,程序运行起来也不会那么容易卡死了

#12


解决问题就好了 自定义控件的时候会经常遇到这样那样的问题的

#1


估计你使用的是Form的Timer,这种Timer是基于Windows消息的,而Windows消息有可能被抛弃,这样就可能导致你的Tick处理不能被触发。另外你提到了做了重绘,重绘的机制设计不对的话有可能导致OnPaint的时候调用刷新引起新的重绘,这样就好像一个死循环,Timer不起作用和图片显示不出来也就正常了。
最好把代码贴一下

#2


 private void button2_Paint(object sender, PaintEventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = button2.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);     //绘制退出按钮形状
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            button2.Region = new System.Drawing.Region(buttonPath);
            
            Rectangle myrect2 = button2.ClientRectangle;
            Bitmap mybmp = new Bitmap(myrect2.Width, myrect2.Height);
            Graphics g2 = Graphics.FromImage(mybmp);
            LinearGradientBrush mybrush = new LinearGradientBrush(myrect2, Color.Yellow, Color.YellowGreen, LinearGradientMode.Horizontal);   //渐变色泽按钮
            g2.FillRectangle(mybrush, myrect2);
            button2.BackgroundImage = mybmp;
        }

        private void button3_Paint(object sender, PaintEventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = button3.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);     //绘制退出按钮形状
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            button3.Region = new System.Drawing.Region(buttonPath);

            Rectangle myrect3 = button3.ClientRectangle;
            Bitmap mybmp3 = new Bitmap(myrect3.Width, myrect3.Height);
            Graphics g3 = Graphics.FromImage(mybmp3);
            LinearGradientBrush mybrush3 = new LinearGradientBrush(myrect3, Color.Yellow, Color.YellowGreen, LinearGradientMode.Horizontal);   //渐变色泽按钮
            g3.FillRectangle(mybrush3, myrect3);
            button3.BackgroundImage = mybmp3;
        }  

#3


问题出在
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp;
在重载OnPaint或者响应Paint消息的处理中不要使用会引起刷新界面操作,设置背景图片会引起界面刷新,界面刷新又会进入到Paint消息的处理里面,如此循环就是问题所在了。
个人建议:如果你响应需要重载OnPaint或者响应Paint消息来达到界面自定义的要求,那么最好这个控件的所有绘制都用绘图来完成而不是用控件的属性。另外,你这样响应Paint消息不是很好,最好封装一个Button类。

#4


你在button2_Paint中几个数就明白我的意思了,两三秒会运行500-600次,而在正常的情况下只有界面刷新才会运行一次。

#5


你在button2_Paint中计个数就明白我的意思了,两三秒会运行500-600次,而在正常的情况下只有界面刷新才会运行一次。

#6


我断点后发现得是它只有在我拖动窗体出现重绘的时候才有运行这段代码,并没有说两三秒会运行500-600次

#7


我没遇到过定时器失效的问题。

#8


首先你要理解Paint事件是在什么时候触发的
我举个datagridview显示数据的例子吧
比如你在form的load事件里 给dgv绑定了数据源 
然后你再dgv的paint事件里去查看dgv.rows的话
实际上是有数据的 但是这个时候dgv上实际上是没有一行数据显示
它需要Paint事件执行完毕以后 才会绘制出数据到dgv上
同理 你的timer放在button的paint事件里 也只有在这个button绘制好以后才会执行timer的操作

所以 你的窗体和窗体的控件 还在绘制的时候 怎么可能出现你timer里控制的那些动作呢

#9


我使用你给的代码做的试验,问题就是我提到的那两句给背景图片赋值的语句上,去掉就没有问题了。
如果不改变你现在的重绘逻辑,我建议你在Form_Load中给按钮添加背景图片,其他不用变就可以解决问题了。
但是还是建议你封装Button类。
你的Timer做了什么操作?与界面相关吗?如果不相关就与你提的问题无关。

#10


我之前回帖不知道为什么不显示,
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp3;
这两句会引起控件刷新从而调用重绘,这样相当于你的程序进到一个循环中,处理重绘->刷新->处理重绘...,你显示有问题就是这个原因。至于Timer不执行也是由于这个原因引起的。

#11


果然我把
button2.BackgroundImage = mybmp;
button3.BackgroundImage = mybmp3;
从paint事件中移出来到load事件中相应的问题就解决了,程序运行起来也不会那么容易卡死了

#12


解决问题就好了 自定义控件的时候会经常遇到这样那样的问题的