【发布时间】:2013-10-03 14:06:13
【问题描述】:
我有一个 TextBlock(s) 的 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() 的动作。
我试图将我的 ContextMenu 从 TextBlock 移动到 ListBox,但这给了我 ViewModel 的 DataContext 而不是给我 _displayString 数据。
正如您在 CallKeyDown() 中看到的那样,我试图从后面的代码中模拟 ctrl+c 按键,但没有成功。我不知道这是否是解决这个问题的最佳方法。我也尝试使用 SendKeys.Send("^{c}") 但这仅适用于窗口窗体。
【问题讨论】:
-
我在给你打字的时候发现了@nit。我只需要将 RightClickCopyCmdExecuted 中的代码复制到 CallKeyDown() 中,一切都很好。然后我会从 RightClickCopyCmdExecuted 调用 CallKeyDown。
-
我不知道 DisplayData 是什么类型。我想我在你的另一篇帖子stackoverflow.com/a/14158608/5652483 中找到了它。但是必须有一种方法可以在这里回答您的问题,而无需定义像 DisplayData 这样的自定义类。
标签: wpf string listbox copy textblock