2013-11-17 3 views
0

Вот что я пытаюсь сделать: Существует некоторая игра, которая записывает некоторую информацию об элементе под курсором мыши в буфер обмена, когда я нажимаю Ctrl-C. Я пытаюсь захватить эту информацию и выбрать некоторые вещи, которые мне нужны. Im делает это так:Clipboard.GetText переопределяет буфер обмена?

//at form load 
    RegisterHotKey(this.Handle, 0, 0x002, (int)Keys.C); 

    protected override void WndProc(ref Message m) 
      { 
       if (m.Msg == 0x0312) 
       { 
        int id = m.WParam.ToInt32(); 
        if (id == 0) 
        { 
         System.Threading.Thread.Sleep(155); //ive thought if i add some delay it would help but it doesnt... 
         string textFromClipboard = Clipboard.GetText(); 
         if (textFromClipboard.Contains("Itemlevel: ")) 
         { 
          // do some stuff with data IF it exists in clipboard, doesnt important what i do - i never get here 
         } 
        } 
       } 
       base.WndProc(ref m); 
      } 

Так в основном, когда я нажимаю Ctrl-C в игре без этой программы на - все отлично работает, информация скопирована в буфер обмена. Когда я включаю программу - буфер обмена остается таким же, как и до того, как я нажму Ctrl-C в игре. Как я могу предотвратить это? Как правильно получить текст из буфера обмена? Может, способ, которым я получаю этот текст, не так? Или может быть, что зарегистрированная горячая клавиша вмешивается в горячую клавишу игры, так что она больше не работает?

обновление: Ive выяснил какое-то простое решение, но очень грубое и варварское. Но он отлично работает.

 public static void KeyDown(System.Windows.Forms.Keys key) 
      { 
       keybd_event((byte)key, 0x45, 0x0001 | 0, 0); 
      } 

      public static void KeyUp(System.Windows.Forms.Keys key) 
      { 
       keybd_event((byte)key, 0x45, 0x0001 | 0x0002, 0); 
      } 
    protected override void WndProc(ref Message m) 
      { 
       if (m.Msg == 0x0312) 
       { 
        int id = m.WParam.ToInt32(); 
        if (id == 0) 
        {     
         ToggleHotkeys(false); 
         KeyDown(Keys.Control); 
         KeyDown(Keys.C); 
         KeyUp(Keys.C); 
         KeyUp(Keys.Control); 
         System.Threading.Thread.Sleep(155); 
//if i comment this sleep - code executes too fast, making first Ctrl-C press 
//capture nothing, second press outputs results for first item 
//third press - for second item, ... 
         string textFromClipboard = Clipboard.GetText(); 
         if (textFromClipboard.Contains("Itemlevel: ")) 
         { 
          //do stuff with data 
         } 
         ToggleHotkeys(true); 
        } 
       } 
       base.WndProc(ref m); 
      } 

Возможно, существует более умный способ решить эту проблему?

+0

Почему вам нужно для 'Sleep' текущий поток? Я сомневаюсь, что это проблема. –

+0

С или без буфера обмена 'sleep' остается таким же, как и до того, как я нажму Ctrl-C –

+0

Я думаю, что когда вы не запустите код выше, будет обработан по умолчанию ** Ctrl + C ** и текст будет скопирован а также обновить содержимое буфера обмена. При запуске кода выше по умолчанию ** Ctrl + C ** может быть * переопределено * зарегистрированной горячей клавишей, и все * автоматическое * копирование не будет выполнено для вас, это означает, что вам нужно добавить код для копирования самостоятельно , –

ответ

1

Я хотел бы использовать монитор CLIPBOARD так что вы можете получить уведомление при изменении ClipBoard:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 

     private ClipBoardMonitor cbm = null; 

     public Form1() 
     { 
      InitializeComponent(); 
      cbm = new ClipBoardMonitor(); 
      cbm.NewText += cbm_NewText; 
     } 

     private void cbm_NewText(string txt) 
     { 
      Console.WriteLine(txt); 
     } 

    } 

    public class ClipBoardMonitor : NativeWindow 
    { 

     private const int WM_DESTROY = 0x2; 
     private const int WM_DRAWCLIPBOARD = 0x308; 
     private const int WM_CHANGECBCHAIN = 0x30d; 

     [DllImport("user32.dll")] 
     static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); 
     [DllImport("user32.dll")] 
     static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); 
     [DllImport("user32.dll", CharSet = CharSet.Auto)] 
     private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 

     public event NewTextEventHandler NewText; 
     public delegate void NewTextEventHandler(string txt); 

     private IntPtr NextClipBoardViewerHandle; 

     public ClipBoardMonitor() 
     { 
      this.CreateHandle(new CreateParams()); 
      NextClipBoardViewerHandle = SetClipboardViewer(this.Handle); 
     } 

     protected override void WndProc(ref Message m) 
     { 
      switch (m.Msg) 
      { 
       case WM_DRAWCLIPBOARD: 
        if (Clipboard.ContainsText()) 
        { 
         if (NewText != null) 
         { 
          NewText(Clipboard.GetText()); 
         } 
        } 
        SendMessage(NextClipBoardViewerHandle, m.Msg, m.WParam, m.LParam); 

        break; 

       case WM_CHANGECBCHAIN: 
        if (m.WParam.Equals(NextClipBoardViewerHandle)) 
        { 
         NextClipBoardViewerHandle = m.LParam; 
        } 
        else if (!NextClipBoardViewerHandle.Equals(IntPtr.Zero)) 
        { 
         SendMessage(NextClipBoardViewerHandle, m.Msg, m.WParam, m.LParam); 
        } 
        break; 

       case WM_DESTROY: 
        ChangeClipboardChain(this.Handle, NextClipBoardViewerHandle); 
        break; 

      } 

      base.WndProc(ref m); 
     } 

    } 

}