为什么在进行循环时,它会在下一次迭代时一直重置为0?

时间:2016-03-11 01:34:18

标签: c# .net winforms

我有一个方法,里面有一些循环:

private void RefreshListBox()
        {
            int i = 0, j = 0, index, count;
            Boolean bl = false;

            index = listBox1.SelectedIndex;
            count = windowsHandles.Count;

            for (i = 0; i < count; i++)
            {
                if (!Constants.IsWindow(windowsHandles[j]))
                {
                    windowsHandles.RemoveAt(j);
                    windowsText.RemoveAt(j);
                    windowsBitmaps.RemoveAt(j);
                    rectanglesList.RemoveAt(j);
                    isCroppedList.RemoveAt(j);
                    canDrawNormallyList.RemoveAt(j);

                    if (j < index)
                    {
                        index--;
                    }
                    else if (j == index)
                    {

                    }
                    else
                    {

                    }

                }
                else { j++; }
            }

            if (index == windowsHandles.Count)
            {
                index--;
            }

            for (int x = 0; x < windows.Count; x++)
            {
                for (j = 0; j < windowsHandles.Count; j++)
                {
                    if (windowsHandles[j] == windows[x].Handle) { bl = true; break; }
                }

                        if (bl == false && Constants.IsIconic(windows[x].Handle))
                        {
                            windowsHandles.Add(windows[x].Handle);
                            windowsText.Add(windows[x].Title);
                            windowsBitmaps.Add(null);
                            rectanglesList.Add(new Rectangle(0, 0, 0, 0));
                            isCroppedList.Add(false);
                            canDrawNormallyList.Add(false);
                        }

                    bl = false;
            }

            if (windowsHandles.Count > 0 && index == -1)
            {
                index = 0;
            }


            if (listBox1.Items.Count > 0) { listBox1.Items.Clear(); }

            for (i = 0; i < windowsHandles.Count; i++)
            {
                listBox1.Items.Add(windowsText[i]);
            }

            if (index != -1)
            {
                listBox1.SelectedIndex = index;
            }

            textBoxIndex.Text = windowsHandles.Count.ToString();
            drawPicBox(index);
        }

        private void listBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var item = listBox1.IndexFromPoint(e.Location);
                if (item >= 0)
                {
                    listBox1.SelectedIndex = item;

                    drawPicBox(listBox1.SelectedIndex);
                }
            }
        }

当问题进入此行的循环时,问题就开始了:

for (int x = 0; x < windows.Count; x++)

在这种情况下,Windows List的计数为21。 然后它进入第一次,但是如果我在这一行上设置一个断点并且一直点击继续,我看到x是0.

当我在这一行上设置一个断点时:

windowsHandles.Add(windows[x].Handle);

每次我点击继续停在那里然后我看到变量x它的值一直是20。 List windowsHandles只包含1个项目。

然后我在线上设置了一个断点:

listBox1.Items.Add(windowsText[i]);

当我继续它时,它停在线上,但即使它在线上,listBox1上也没有任何项目。

如果我不使用任何断点,只是让它继续让它运行它永远不会显示/到达表单它就像卡在这个方法的某个地方无法弄清楚在哪里和为什么。

在构造函数中,我调用了两个方法。 首先是GetWindows然后是RefreshList

GetWindows();
RefreshListBox();

在GetWindows中:

private List<Window> windows = new List<Window>();

        private void GetWindows()
        {
            windows = new List<Window>();
            Constants.EnumWindows(Callback, 0);
        }


        private bool Callback(IntPtr hwnd, int lParam)
        {
            try
            {
                if (this.Handle != hwnd && (Constants.GetWindowLongA(hwnd, Constants.GWL_STYLE) & Constants.TARGETWINDOW) == Constants.TARGETWINDOW)
                {
                    StringBuilder sb = new StringBuilder(100);
                    Constants.GetWindowText(hwnd, sb, sb.Capacity);

                    Window t = new Window();
                    t.Handle = hwnd;
                    t.Title = sb.ToString();
                    windows.Add(t);
                }
            }
            catch(Exception err)
            {
                StreamWriter w = new StreamWriter(@"e:\errors.txt");
                w.Write(err.ToString());
                w.Close();
            }
            return true;
        }

在GetWindows操作结束时,我看到窗口包含21个项目。 问题似乎在RefreshList方法中的某处,但我无法弄清楚问题出在哪里。

最终所有这一切的目标是将windowsText中的所有项添加到listBox1。

2 个答案:

答案 0 :(得分:2)

我刚注意到其他事情:

windowsHandles.Add(windows[x].Handle);
windowsText.Add(windows[x].Title);
windowsBitmaps.Add(null); // <------
rectanglesList.Add(new Rectangle(0, 0, 0, 0));
isCroppedList.Add(false);
canDrawNormallyList.Add(false);

这是正确的猜测 - 您向null添加windowsBitmaps的原因是所有这六个集合都保持同步。如果每个集合中的项目具有相同的索引,则它们会以某种方式相关。

如果您创建了一个包含windowsHandlewindowsTextwindowsBitmaps等属性的类,然后拥有该类型的集合,那将会容易得多。这样,而不是管理六个集合,并试图让它们保持同步,你只有一个。

答案 1 :(得分:1)

这不是一个直接的答案,但我认为如果您能够得到答案,这是必要的步骤:将其分解为更小的方法。

你可以从循环开始。您可以将每个循环放在一个单独的方法中,并非常清楚地命名该方法,以便它表明它正在做什么以及它做了什么。 (将一些函数放在不同的类中甚至是值得的。)

其中一个原因是,没有人 - 不是你或后来工作的程序员 - 可以期望能够掌握一个长方法的复杂性,并且如果发生这种情况就会贯彻执行如果发生这种情况会怎么样。&#39;

变量名称也是如此。如果变量名称和方法名称很长,如果它们有助于明确它们的用途,那就没关系。我发现自己看到x并且不得不向上滚动以查看x是什么,然后我忘记了我的位置。

我知道这不是一个直接的答案。但如果你这样做,那么答案可能会更容易看到。如果将其分解为较小的函数(甚至编写单独的类),那么您也可以编写单元测试。这样,您可以一次只测试一个零件,而不是从上到下运行整个零件。

更直接相关

与代码更直接相关:如果您确实需要遍历集合并可能随时删除项目,那么从Count开始并向后工作会更好。这样你的索引就会停留在界限内。

更简单的方法是使用Linq查询元素并创建新集合。例如

Thing[] arrayOfSomething = GetAnArrayOfSomething();

var arrayWithElementsRemoved = arrayOfSomething.Where(
    item => !item.DeleteThisOne).ToArray();

第二个语句采用Thing数组并返回一个新数组,其中只包含DeleteThisOnefalse的数组。它只是一个声明,没有循环或担心。