1

我有一个应用程序,在热键组合后它实际上“发送”一个 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?任何有助于理解这一点,以及让它与 NO MessageBoxes 一起运行都会很棒。

4

3 回答 3

0

当我用这个简单的代码将鼠标移动到我的 PictureBox 中时,我正在从记事本(和其他各种应用程序)中复制东西就好了:

    private void pictureBox1_MouseEnter(object sender, EventArgs e)
    {
        SendKeys.SendWait("^c");
        if (Clipboard.ContainsText())
        {
            label1.Text = Clipboard.GetText();
        }
    }

使用管理员帐户运行 Windows 8.1 x64。

于 2013-11-07T16:26:51.437 回答
0

keybd_event 将事件放入队列中,但在您的代码完成之前不会处理它们。如果你把

Application.DoEvents();

在 keydb_event 调用之后,应该处理键盘事件。我怀疑 Thread.Sleep() 不起作用,因为它只是休眠,但不处理等待事件。

对 MessageBox 的第一次调用确实允许事件运行,因此在 MessageBox 之后,剪贴板中有东西。使用 SendKeys.SendWait() 会起作用,但 SendKeys.Send 不会,因为 SendWait 会等待键盘事件被处理,而 SendKeys.Send 不会。

于 2013-11-08T17:54:39.930 回答
0

尝试检查剪贴板序列号的变化:

定义导入:

[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。

于 2013-11-07T16:11:44.110 回答