我有一个应用程序,在热键组合后它实际上“发送”一个Ctrl + C到前台窗口,将所选文本发送到剪贴板。然后我需要从剪贴板中获取文本。这样做的代码如下:
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
private void CopyHighlighted()
{
uint KEYEVENTF_KEYUP = 2;
byte VK_CONTROL = 0x11;
SetForegroundWindow(GetForegroundWindow());
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(0x43, 0, 0, 0);
keybd_event(0x43, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0x9d, KEYEVENTF_KEYUP, 0);
bool containsStuff = (Clipboard.ContainsAudio() || Clipboard.ContainsFileDropList() || Clipboard.ContainsImage() || Clipboard.ContainsText());
//The behavior changing MessageBox:
//MessageBox.Show("the clipboard contains some data: " + containsStuff.ToString());
string rawNumber = Clipboard.GetText();
MessageBox.Show("raw contents of clipboard " + Environment.NewLine + rawNumber);
}
如果注释了MessageBox
,我会得到一个弹出窗口,上面写着“剪贴板包含一些数据:False”。这是非常奇怪的,因为下一个弹出窗口说“剪贴板的原始内容Clipboard.ContainsText()返回false ...但确定rawNumber
确实包含预期的文本。
但是当我评论第一个MessageBox
时,我只获得了1个弹出窗口(正如预期的那样),但它只说“剪贴板的原始内容”而rawNumber是一个空字符串。
为什么包含此中间MessageBox
会导致我能够获取剪贴板文本?为什么在此之前Clipboard.ContainsText()
返回false? <_ 1}}可以帮助您理解这一点,以及让它与NO MessageBox
配合使用会很棒。
答案 0 :(得分:0)
尝试检查Clipboard Sequence Number更改:
定义导入:
[DllImport("user32.dll")]
static extern uint GetClipboardSequenceNumber();
使用它:
System.Threading.Thread.Sleep(5000); // Give me time to switch windows
uint KEYEVENTF_KEYUP = 2;
byte VK_CONTROL = 0x11;
SetForegroundWindow(GetForegroundWindow());
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(0x43, 0, 0, 0);
keybd_event(0x43, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0x9d, KEYEVENTF_KEYUP, 0);
uint startClip = GetClipboardSequenceNumber();
uint nextClip = startClip;
while (nextClip == startClip)
{
nextClip = GetClipboardSequenceNumber();
}
string rawNumber = Clipboard.GetText();
MessageBox.Show("raw contents of clipboard " + Environment.NewLine + rawNumber);
您应该在非ui线程中执行此操作,然后将其作为事件。您可能还想限制此代码,以便不会经常调用API。
答案 1 :(得分:0)
当我用这个简单的代码将鼠标移动到我的PictureBox时,我正在用记事本(以及其他各种应用程序)复制一些东西:
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
SendKeys.SendWait("^c");
if (Clipboard.ContainsText())
{
label1.Text = Clipboard.GetText();
}
}
使用管理员帐户运行Windows 8.1 x64。
答案 2 :(得分:0)
keybd_event将事件放入队列中,但在代码完成之前不会处理它们。如果你把
Application.DoEvents();
在keydb_event调用之后,应该处理键盘事件。我怀疑Thread.Sleep()不起作用,因为它只是睡觉,但不处理等待事件。
第一次调用MessageBox确实允许事件运行,因此在MessageBox之后,剪贴板中有东西。使用SendKeys.SendWait()将起作用,但SendKeys.Send不会,因为SendWait等待处理键盘事件,而SendKeys.Send不会。