简体   繁体   English

向下模拟CTRL直到我想要使用C#?

[英]Simulate CTRL down until I desire in c#?

I'm trying to simulate a user pressing ctrl down, the main goal would be in a datagridview when I select something programarly (initially) I dont want the user to then change that selection if not just add on to it or subtract, just as if you were to hold ctrl + left mouse click. 我正在尝试模拟一个用户按下ctrl,主要目的是当我以编程方式选择某个对象时(最初),我不希望用户随后更改该选择,如果不只是添加或减去它,就像如果要按住Ctrl +鼠标左键。 I have no idea where to even begin. 我什至不知道从哪里开始。 I tried to create a selection change event conbined with logicals but that will cause an infinite loop since we would be selecting one by a user then the code change other and other etc infinitely triggering that event. 我试图创建一个与逻辑结合的选择更改事件,但这将导致无限循环,因为我们将由用户选择一个事件,然后代码更改其他事件和其他事件则无限触发该事件。 Please help, I'm sort of new to coding. 请帮助,我是编码的新手。 I also don't know how to determine whether a ctrl key has been pressed, is pressed and being held. 我也不知道如何确定是否已按下,按住了Ctrl键。

        private void selecttionh(object sender, EventArgs e)
    {

        if (stage == "4A" || stage == "3B" && ModifierKeys.HasFlag(Keys.Control))
        {
            int nothing = 0;
            btnclickercl bt = new btnclickercl();
            bt.dataGridView1_SelectionChanged(sender, e, dataGridViewReslist, dataGridViewnewres, nothing);
        }
        if (stage == "4A" || stage == "3B" && (ModifierKeys & Keys.Control) != Keys.Control)
        {
            MessageBox.Show("Please Press and hold " + "'ctrl'" + " to continue");
            dataGridViewReslist.ClearSelection();
            for (int i = 0; i < ResRoomSelections.Count; i++)
            {
                dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[ResRoomSelections[i][1]].Selected = true;
                dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[(ResRoomSelections[i][1]) + 1].Selected = true;
            }
        }
        else
        {
                dataGridViewReslist.ClearSelection();
                for (int i = 0; i < ResRoomSelections.Count; i++)
                {
                    dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[ResRoomSelections[i][1]].Selected = true;
                    dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[(ResRoomSelections[i][1]) + 1].Selected = true;
                }
        }  

    }

The way to make this happen is to store the selection state separately, update it when the user clicks a cell, then re-apply it. 实现此目的的方法是单独存储选择状态,在用户单击单元格时对其进行更新,然后重新应用它。 This prevents the selection from being lost every time they click. 这样可以防止每次单击时都丢失选择。 If you hook the proper event handlers (mouseup, not click) you can do this without the screen flickering and otherwise being a mess to look at. 如果您钩住了适当的事件处理程序(鼠标,而不是单击),则可以做到这一点,而不会导致屏幕闪烁,否则就一团糟。

Everything you need is in this class, including an extension method SetupToggledSelectionMode() , which is your entry point. 您需要的所有内容都在此类中,包括扩展方法SetupToggledSelectionMode() ,这是您的入口点。

static public class Example
{
    static private bool[][] GetSelectionState(DataGridView input)
    {
        int rowCount = input.Rows.Count;
        int columnCount = input.Columns.Count;
        var result = new bool[rowCount][];
        for (var r = 0; r < rowCount; r++)
        {
            result[r] = new bool[columnCount];
            for (var c = 0; c < columnCount; c++)
            {
                var cell = input.Rows[r].Cells[c];
                result[r][c] = cell.Selected;
            }
        }
        return result;
    }

    static private void SetSelectionState(DataGridView input, bool[][] selectionState)
    {
        for (int r = 0; r <= selectionState.GetUpperBound(0); r++)
        {
            for (int c = 0; c <= selectionState[r].GetUpperBound(0); c++)
            {
                input.Rows[r].Cells[c].Selected = selectionState[r][c];
            }
        }
    }


    static public void SetupToggledSelectionMode(this DataGridView input)
    {
        bool[][] selectionState = GetSelectionState(input);  //This will be stored in a closure due to the lambda expressions below

        input.CellMouseUp += (object sender, DataGridViewCellMouseEventArgs e) =>
        {
            selectionState[e.RowIndex][e.ColumnIndex] = !selectionState[e.RowIndex][e.ColumnIndex];
            SetSelectionState(input, selectionState);
        };

        input.SelectionChanged += (object sender, EventArgs e) =>
        {
            if (selectionState != null)
            {
                SetSelectionState(input, selectionState);
            }
        };
    }
}

To use, populate your gridview, set up the initial selection programmatically, and call it like this: 要使用,请填充您的gridview,以编程方式设置初始选择,然后按以下方式调用它:

myDataGrid.DataSource = myData;
myDataGrid.Refresh();
myDataGrid.SelectAll();
myDataGrid.SetupToggledSelectionMode();

The SetupToggledSelectionMode() method will register the necessary event handlers and store the selection state of the grid in a closed variable accessible to both handlers. SetupToggledSelectionMode()方法将注册必要的事件处理程序,并将网格的选择状态存储在两个处理程序均可访问的封闭变量中。 So you won't have to declare anything additional; 因此,您无需声明其他任何内容; just call the method. 只需调用该方法即可。

Thank you for this, this really helped me. 谢谢你,这真的帮了我。 all I did was to make it more efficient.Since it would call the Selection change every step of the way, so I got rid of that event completely and only kept the CellMouseup Event. 我所做的就是提高效率。因为它将在每个步骤中调用Selection进行更改,所以我完全摆脱了该事件,只保留了CellMouseup事件。

static private bool[][] GetSelectionState(DataGridView input)
{
    int rowCount = input.Rows.Count;
    int columnCount = input.Columns.Count;
    var result = new List<int[]>();
    for (var r = 0; r < rowCount; r++)
    {
        for (var c = 0; c < columnCount; c++)
        {
            if(input.Rows[r].Cells[c].Selected==true)
           {
            result.add(new int[]{r,c});//will keep only the integer of selected items
           }
        }
    }
    return result;//this for me was a recycled variable it can be used or recycled from somewhere else
}

private void SetSelectionState(DataGridView input,result)
    {
        for (int i=0;i<result.Count;i++)
        {
            input.Rows[result[i][0]].Cells[result[i][1]].Selected = true;

        }
    }
public void SetupToggledSelectionMode(DataGridView input,result)
    {
     for (int i=0;i<result.Count;i++)
            {
                if(result[i].SequenceEqual(new int[] { e.RowIndex, e.ColumnIndex }))
                {
                    result.RemoveAt(i);
                    continueer = 1;
                    break;
                }
            }
            if (continueer == 0)
            {
                ResRoomSelections.Add(new int[] { e.RowIndex, e.ColumnIndex });
            }
        SetSelectionState(input);
         //whatever else you need to do 
 }

I know there is still a better way to search List but I could not get a lamda search to work so I just used brute force 我知道还有一种更好的搜索列表的方法,但是我无法通过lamda搜索来工作,所以我只是使用蛮力

-Thank you John Wu for all -谢谢吴John

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM