Нужно, чтобы код, который проверяет буфер обмена, работал постоянно. Сейчас он у меня срабатывает только по нажатию на кнопку. Как это можно организовать ?
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];
}
Копируется что-то в буфер, нажимается кнопка А и из буфера значение заносится в массив, потом снова копируется значение, нажимается А и значение копируется в массив на позицию i+1. А мне нужно, чтобы это происходило без нажатия на кнопку А. Бесконечным циклом не вышло:программа просто не запускается.
Ответ
Конечно, можно запустить бесконечный цикл где-нибудь в отдельном потоке, но на мой взгляд такое решение как минимум некорректно. Windows предоставляет возможность отслеживать изменения буфера обмена - т.е., изменения будут отслеживаться и обрабатываться в реальном времени. Как я понимаю, вас интересует именно это, а не while (true) :)
В статье за авторством Тома Арчера рассказывается, как организовать отслеживание в WinForms. Приведу краткое переложение раздела "Пошаговые инструкции" (с переводом и некоторыми изменениями в коде).
1
Необходимо вызвать пару функций из библиотеки Win32 —SetClipboardViewer, ChangeClipboardChain, и SendMessage Для того, чтобы сделать это в приложении .NET, необходимо импортировать их, используя атрибут DllImport. В примере ниже эти функции импортируются в приложение WinForms:
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 hold the current first window in the Clipboard notification chain:
public partial class frmMain : Form
{
...
IntPtr nextClipboardViewer;
3
Вызовем функцию SetClipboardViewer. В примере она вызывается в конструкторе формы:
public frmMain()
{
InitializeComponent();
nextClipboardViewer = (IntPtr)SetClipboardViewer((int)
this.Handle);
}
4
Внутри класса frmMain переопределим метод WndProc.
В примере обрабатываются только два сообщения: WM_DRAWCLIPBOARD и WM_CHANGECBCHAIN
В коде, обрабатывающем WM_DRAWCLIPBOARD, вызывается пользовательский метод DisplayClipboardData(), который выводит содержимое буфера; затем то же сообщение передаётся следующему в цепи окну.
В коде, обрабатывающем WM_CHANGECBCHAIN, проверяется, является ли окно, удалённое из цепи буфера, следующим (по отношению к текущему). Если да, nextClipboardViewer присваивается окно, следующее за удалённым.
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;
}
}
5
Наконец, окно удаляется из цепи буфера, когда .NET Runtime вызывает метод Dispose класса frmMain
protected override void Dispose( bool disposing )
{
ChangeClipboardChain(this.Handle, nextClipboardViewer);
...
В инструкции не описан, собственно, метод DisplayClipboardData. У меня он выглядит так:
private void DisplayClipboardData()
{
txtBox.Text = Clipboard.GetText();
}
Т.е., в текстовое поле на форме просто выводится текст из буфера. В вашем случае нужно вставить обработку массива.
На всякий случай, полный листинг того, что вышло у меня:
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();
}
}
}
Плюс не забываем добавить строку ChangeClipboardChain(this.Handle, nextClipboardViewer); в метод Dispose в файле frmMain.Designer.cs
Код компилируется и прекрасно работает в Win10 x64. Текст из буфера вставляется в текстовое поле сразу после копирования, никаких кнопок дополнительно нажимать не надо
Комментариев нет:
Отправить комментарий