将ListBox中的多个项目复制到ClipBoard

时间:2013-10-03 14:06:13

标签: wpf string listbox copy textblock

我有一个TextBlock的ListBox,我希望最终用户能够从显示器复制文本,然后他们可以将它粘贴到他们喜欢的地方。我可以通过右键单击>获得单行副本。复制,并用用户的ctrl + c键按。我也可以通过用户的ctrl + c键按下来获得多行副本。我希望能够使用右键单击>复制功能以及菜单下拉调用进行多行复制。

我的列表框:

    <!--Progress Window-->
    <ListBox x:Name="Progress_Window" ItemsSource="{Binding _displayString}" ScrollViewer.ScrollChanged="Progress_Window_ScrollChanged" KeyDown="Progress_Window_KeyDown" SelectionMode="Extended">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding _string}" Foreground="{Binding _color}" FontSize="{Binding _fontSize}">

                    <TextBlock.ContextMenu>
                        <ContextMenu>
                            <MenuItem Command="Copy">
                                <MenuItem.CommandBindings>
                                    <CommandBinding Command="ApplicationCommands.Copy" CanExecute="RightClickCopyCmdCanExecute" Executed="RightClickCopyCmdExecuted" />
                                </MenuItem.CommandBindings>
                            </MenuItem>
                        </ContextMenu>
                    </TextBlock.ContextMenu>

                </TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

背后的代码:

    [DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);


    [DllImport("kernel32.dll")]
    static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);


    public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
    public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
    public const int VK_LCONTROL = 0xA3;   //0xA2; //Left Control key code
    public const int C = 0x43; //A Control key code


    private void Progress_Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
        {
            try
            {
                ListBox lb = (ListBox)(sender);

                string collectedText = "";

                foreach (DisplayData dd in lb.SelectedItems)
                {
                    collectedText += dd._string + "\r\n";
                }

                if (lb.SelectedItems != null)
                {
                    Clipboard.SetText(collectedText);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }


    private void RightClickCopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        MenuItem mi = (MenuItem)sender;
        DisplayData selected = (DisplayData)mi.DataContext;

        if (selected != null)
        {
            Clipboard.SetText(selected._string);
        }
    }


    private void RightClickCopyCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }


    public void CallKeyDown()
    {
        //Progress_Window.Focus();

        //// Hold Control down and press C
        //keybd_event(VK_LCONTROL, 0, 0, 0);
        //keybd_event(C, 0, 0, 0);
        //keybd_event(C, 0, KEYEVENTF_KEYUP, 0);
        //keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0);

        System.Windows.Forms.SendKeys.SendWait("^{c}");

        var key = Key.C;             // Key to send            
        var target = Progress_Window;               // Target element
        var routedEvent = Keyboard.KeyDownEvent;    // Event to send

        target.RaiseEvent(new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(target), 0, key) { RoutedEvent = routedEvent });
    }
}

从菜单下拉菜单中

<Grid>
    <Menu>
        <!--File-->
        <MenuItem Header="_File">
            <MenuItem Header="_Close" Command="{Binding Close}" />
        </MenuItem>

        <!--Edit-->
        <MenuItem Header="_Edit">
            <MenuItem Header="_Copy     Ctrl+C" Command="{Binding CtrlC}" />
        </MenuItem>

CtrlC命令调用触发CallKeyDown()的Action。

我试图将我的ContextMenu从TextBlock移动到ListBox,但这给了我ViewModel的DataContext而不是给我_displayString数据。

正如你在CallKeyDown()中看到的那样,我试图从后面的代码模拟一个ctrl + c键按下但没有成功。我不知道这是否是解决这个问题的最佳方法。我也尝试使用SendKeys.Send(“^ {c}”),但这只适用于Window Forms。

1 个答案:

答案 0 :(得分:3)

我只需要将RightClickCopyCmdExecuted中的代码复制到CallKeyDown(),一切都很顺利。然后我会从CallKeyDown致电RightClickCopyCmdExecuted

我在列表框中获得了右键单击&gt;副本的多行。 所以我的ListBox变成了:

    <!--Progress Window-->
    <ListBox x:Name="Progress_Window" ItemsSource="{Binding _displayString}" ScrollViewer.ScrollChanged="Progress_Window_ScrollChanged" KeyDown="Progress_Window_KeyDown" SelectionMode="Extended">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding _string}" Foreground="{Binding _color}" FontSize="{Binding _fontSize}" />
            </DataTemplate>
        </ListBox.ItemTemplate>

        <ListBox.ContextMenu>
            <ContextMenu>
                <MenuItem Command="Copy">
                    <MenuItem.CommandBindings>
                        <CommandBinding Command="ApplicationCommands.Copy" CanExecute="RightClickCopyCmdCanExecute" Executed="RightClickCopyCmdExecuted" />
                    </MenuItem.CommandBindings>
                </MenuItem>
            </ContextMenu>
        </ListBox.ContextMenu>
    </ListBox>

后面的代码变成了:

    private void RightClickCopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        string collectedText = "";

        foreach (DisplayData dd in Progress_Window.SelectedItems)
        {
            collectedText += dd._string + "\r\n";
        }

        if (Progress_Window.SelectedItems != null)
        {
            Clipboard.SetText(collectedText);
        }
    }