SendMessage颜色到进度条时的奇数进度值行为

时间:2017-10-29 03:10:19

标签: vb.net winforms winapi

我正在使用SendMessage来更改进度条的颜色。这工作正常,但我看到一些与进度条值相关的奇怪行为。

当条形图为绿色时,它按预期工作,但当它为红色或黄色时,条形图块位于与进度条值不同步的一个块位置。下面的示例代码将进度条值从4逐步降低到0,进度条最大值设置为4。

当条形为绿色时,进度值4给出一个完整的条形,所有整数步长均为零,表现如预期。但是当条形为红色或黄色时,它显示完整条形或没有条形值4,具体取决于它之前的位置。它显示进度值3的FULL BAR,然后降低1个块与该值不同步,直到最后它在进度值重置为最大值时不显示任何块。如果这听起来很混乱,那么我一路跟你在一起。

我是SO的狂热拖网渔船,已经存在多年,迄今为止,我的问题一直得到解答,而无需特别询问。但是虽然我可以找到很多进度条问题,但我找不到任何与此问题有关的内容,这让我感到非常困惑。我在代码中遗漏了什么,或者这是一个错误?

Public Class Form1
    Private Declare Auto Function SendMessage Lib "user32.dll"
        (ByVal hWnd As IntPtr, ByVal msg As Integer,
         ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Sub Form1_Shown(sender As Object, e As EventArgs)
        ProgressBar1.Maximum = 4
        ProgressBar1.Value = ProgressBar1.Maximum
    End Sub

    'Step down through progress bar values (4 to 0)
    Private Sub Step(sender As Object, e As EventArgs) Handles CmdStep.Click
        If ProgressBar1.Value > 0 Then
            ProgressBar1.Increment(-1)
        Else 'Progress bar back to Max after reaching zero
            ProgressBar1.Value = ProgressBar1.Maximum
        End If
        'Show current progress bar value
            TextBox1.Text = ProgressBar1.Value
    End Sub

    'Set colour (1 to 3)
    Private mProgressColour As Integer = 1 'Initial colour: Green
    Private Sub TBox(sender As Object, e As EventArgs) Handles TextBox2.TextChanged
        'Change the progress bar colour according to colour value selected (1 to 3)
        If TextBox2.Text <> "" Then
            mProgressColour = CInt(TextBox2.Text)
            SendMessage(ProgressBar1.Handle, &H410, mProgressColour, 0)
        End If
    End Sub
End Class

Screen grab showing odd progress bar behaviour

编辑:根据Visual Vincent的建议,我查看了课堂声明,虽然没有解决这个问题,但他给了我一些很好的建议。因为Vincent向我指出了一个C#声明示例,我在C#中重写了该程序,并且在更改进度条颜色时它表现出完全相同的奇怪行为。如果在一个问题中混合C#和VB是不好的形式,我很抱歉,但在这种情况下,我觉得它有效,因为这两个问题似乎都很常见。

与VB版本(上图)一样,启动了一个新项目,将控件添加到表单中,并将代码输入到表单类中。没有其他代码,事件或后台工作人员干扰程序流程。

using System.Runtime.InteropServices; //For [DllImport]
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1(){InitializeComponent();}

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

        private void Form1_Load(object sender, EventArgs e)
        {
            ProgressBar1.Maximum = 4;
            ProgressBar1.Value = ProgressBar1.Maximum;
        }

        private void CmdStep_Click(object sender, EventArgs e)
        {
            if (ProgressBar1.Value > 0)
            {
                ProgressBar1.Increment(-1);
            }
            else //Progress bar back to Max after reaching zero
            {
                ProgressBar1.Value = ProgressBar1.Maximum;
            }
            TextBox1.Text = Convert.ToString(ProgressBar1.Value); //Show current progress bar value
        }

        private int mProgressColour = 1; //Green
        private void TextBox2_TextChanged(object sender, EventArgs e)
        {
            //Change the progress bar colour according to colour selected in TextBox2 (1 to 3)
            if (TextBox2.Text != "")
            {
                mProgressColour = Convert.ToInt32(TextBox2.Text); //Convert Text box value to Integer
                IntPtr ipProgColour = (IntPtr)mProgressColour; //Then convert the Integer to IntPtr
                SendMessage(ProgressBar1.Handle, 0x410, ipProgColour, IntPtr.Zero); //Do it!
            }
        }
    }
}

下面的screengrab显示了C#程序输出。我没有显示绿色条,因为它表现正常,这次我使用黄色条只是为了表明这个颜色条表现出与红色条相同的行为。

Screengrab showing C# example of progress bar colour issue.

我一直在努力思考原因。就像红色/黄色条形数据位旋转一样。但我认为它与绿色条相同,它具有相同的手柄。但也许它不是,那只是令人兴奋。有什么想法吗?如果你有一点时间,我可以谦虚地请求你尝试运行这个代码,将它复制粘贴到一个新的形式,如显示的那样,让我知道我不会生气!感谢。

1 个答案:

答案 0 :(得分:1)

这个问题似乎是Hans Passant发现的一个内部缓冲错误。 根据Visual Vincent的建议,该漏洞已报告给微软。 解决方法是在ProgressBar.Value语句之后增加(0)。 请注意,ProgressBar.Refresh和Update不能解决此问题。 以下子例程来自VB代码示例,并添加了增量(0)修复。

'Step down through progress bar values (4 to 0)
Private Sub CmdStep_Click(sender As Object, e As EventArgs) Handles CmdStep.Click
    If ProgressBar1.Value > 0 Then
        ProgressBar1.Value -= 1
    Else 'Progress bar back to Max after reaching zero
        ProgressBar1.Value = ProgressBar1.Maximum
    End If
    ''''''''''''''''''''''''''
    ProgressBar1.Increment(0) ' Incrementing by zero causes the progress bar to update
    ''''''''''''''''''''''''''
    'Show current progress bar value
    TextBox1.Text = ProgressBar1.Value
End Sub