It is necessary that the code that checks the clipboard, worked constantly. Now it works for me only by pressing a button. How can this be organized?

int i = 0; if (e.KeyCode == Keys.A) { stroka = Clipboard.GetText(); for (i = 0; i < array.Length; i++) { if (array[i] == "") { array[i] = stroka; break; } else if (array[9] != "") { DialogResult dr = MessageBox.Show("Ошибка. Буфер переполнен. Хотите очистить буфер ?","Предупреждение",MessageBoxButtons.OKCancel); if (dr == DialogResult.OK) { for (i = 0; i < array.Length; i++) { array[i] = ""; } } break; } } } if (e.KeyCode == Keys.D0) { textBox3.Text = array[0]; } if (e.KeyCode == Keys.D1) { textBox3.Text = array[1]; } if (e.KeyCode == Keys.D2) { textBox3.Text = array[2]; } if (e.KeyCode == Keys.D3) { textBox3.Text = array[3]; } if (e.KeyCode == Keys.D4) { textBox3.Text = array[4]; } if (e.KeyCode == Keys.D5) { textBox3.Text = array[5]; } if (e.KeyCode == Keys.D6) { textBox3.Text = array[6]; } if (e.KeyCode == Keys.D7) { textBox3.Text = array[7]; } if (e.KeyCode == Keys.D8) { textBox3.Text = array[8]; } if (e.KeyCode == Keys.D9) { textBox3.Text = array[9]; } 

Something is copied to the buffer, button A is pressed, and the value from the buffer is entered into the array, then the value is copied again, A is pressed and the value is copied to the i + 1 position. And I need this to happen without pressing the button A. The endless cycle did not work: the program simply does not start.

  • Which code, which buffer, which button ... the question is sorely lacking in details. - Kromster
  • +1 to the previous comment, but the hidden psychic tells me that you need a simple timer, which after a specified time interval will check the buffer. Read about the WinForms timer component on MSDN, there are even examples there, or look here, the topic has been raised repeatedly, here about all the dotneta timers, at least on one question with the answer and there. - rdorn
  • Understood thanks. - Andrei
  • just do not forget to reset the buffer after processing, otherwise I already foresee the next question =) and add the missing information to the current one - rdorn
  • I have the current state of the buffer in 2 variables. In the first variable immediately when copying, in the second after adding to the array. And then the next time I copy, I compare these variables. The first stores the new value of the buffer, the second variable is the old one. - Andrei

1 answer 1

Of course, you can run an infinite loop somewhere in a separate thread, but in my opinion such a solution is at least incorrect. Windows provides the ability to track clipboard changes — that is, changes will be tracked and processed in real time. As I understand it, this is what interests you, not while (true) :)

The article by Tom Archer describes how to organize tracking in WinForms. I will cite a brief transcription of the “Step-by-Step Instructions” section (with translation and some changes in the code).


one

You need to call a couple of functions from the Win32 library - SetClipboardViewer , ChangeClipboardChain , and SendMessage To do this in the .NET application, you must import them using the DllImport attribute. In the example below, these functions are imported into the WinForms application:

 using System.Runtime.InteropServices; ... public partial class frmMain : Form { [DllImport("User32.dll")] protected static extern int SetClipboardViewer(int hWndNewViewer); [DllImport("User32.dll", CharSet=CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); ... 

2

Define a class member to place the current window in the buffer notification chain. Original text:

 public partial class frmMain : Form { ... IntPtr nextClipboardViewer; 

3

Call the SetClipboardViewer function. In the example, it is called in the form constructor:

 public frmMain() { InitializeComponent(); nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle); } 

four

Inside the frmMain class frmMain override the WndProc method. In the example, only two messages are WM_DRAWCLIPBOARD : WM_DRAWCLIPBOARD and WM_CHANGECBCHAIN .

  • In the code that handles WM_DRAWCLIPBOARD , the user-defined method DisplayClipboardData() is called, which displays the contents of the buffer; then the same message is transmitted to the next window in the chain.

  • In the code processing WM_CHANGECBCHAIN , it is checked whether the window removed from the buffer chain is next (relative to the current one). If so, nextClipboardViewer assigned the window following the deleted one.

    protected override void WndProc(ref Message m)

     { const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; switch (m.Msg) { case WM_DRAWCLIPBOARD: DisplayClipboardData(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } 

five

Finally, the window is removed from the buffer chain when the .NET Runtime calls the Dispose method of the frmMain class frmMain

 protected override void Dispose( bool disposing ) { ChangeClipboardChain(this.Handle, nextClipboardViewer); ... 

The instructions do not describe the DisplayClipboardData method. It looks like this for me:

 private void DisplayClipboardData() { txtBox.Text = Clipboard.GetText(); } 

Ie, the text from the buffer is simply displayed in the text field on the form. In your case, you need to insert array processing.

Just in case, a full listing of what happened to me:

 using System.Windows.Forms; using System.Runtime.InteropServices; namespace clipborad { public partial class frmMain : Form { Random r = new Random(); [DllImport("User32.dll")] protected static extern int SetClipboardViewer(int hWndNewViewer); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); IntPtr nextClipboardViewer; public frmMain() { InitializeComponent(); nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle); } protected override void WndProc(ref System.Windows.Forms.Message m) { // defined in winuser.h const int WM_DRAWCLIPBOARD = 0x308; const int WM_CHANGECBCHAIN = 0x030D; switch (m.Msg) { case WM_DRAWCLIPBOARD: DisplayClipboardData(); SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; case WM_CHANGECBCHAIN: if (m.WParam == nextClipboardViewer) nextClipboardViewer = m.LParam; else SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); break; default: base.WndProc(ref m); break; } } private void DisplayClipboardData() { txtBox.Text = Clipboard.GetText(); } } } 

Plus, don't forget to add the line ChangeClipboardChain(this.Handle, nextClipboardViewer); to the Dispose method in the frmMain.Designer.cs file

The code compiles and works great in Win10 x64. The text from the buffer is inserted into the text field immediately after copying, no need to additionally press any buttons