Задача:
Условия:
Реализации которые я видел используют WinApi, вот один пример из таких реализаций:
[DllImport("user32.dll")]
static extern IntPtr SetClipboardViewer(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ChangeClipboardChain(IntPtr hWndDel, IntPtr hWndNext);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wparam1, IntPtr lparam);
IntPtr hWndNextWnd; //Для хранения указателя на следующее окно
protected override void WndProc(ref Message m) // переопределяем метод
{
switch (m.Msg) //Анализируем сообщение Windows
{
case (0x0001): // Код WM_CREATE наше окно создано
hWndNextWnd = SetClipboardViewer(this.Handle); // Помещаем наше окно в цепочку и сохраняем указатель на следующее
break;
case (0x0002): // Код WM_DESTROY окно будет разрушено, нужно удалитmся из цепочки буфера обмена
ChangeClipboardChain(this.Handle, hWndNextWnd); // Удаляем наше окно и передаём указатель на следующее окно
break;
case (0x030D): // Код WM_CHANGECBCHAIN одно из окон удаено из цепочки, нужно востоновить цепочку
if (m.WParam == hWndNextWnd) // Если удаляемое окно это следующие окно в цепочке
hWndNextWnd = m.LParam; //Следующим окном делаем окно идущее в цепочке за удаляемым
else if (hWndNextWnd != IntPtr.Zero) // Если дескриптор следующего окна определён
SendMessage(hWndNextWnd, m.Msg, m.WParam, m.LParam);// Посылаем сообщение этому окну
break;
case (0x0308): //Код WM_DRAWCLIPBOARD содержимое буфера изменилось можно работать
{
//НА МЕСТЕ ЭТОГО КОММЕНТАРИЯ ПИШИТЕ СВОЙ КОД
SendMessage(hWndNextWnd, m.Msg, m.WParam, m.LParam);// Посылаем сообщение о изменении бефера дальше по цепочке
}
break;
}
base.WndProc(ref m); //обращаемся к нашему методу
Вопрос: Как реализовать такое без WinForm(как в данном примере)?
Т.Е. что делать если у меня консоль и мне негде переопределять метод WndProc?
Совсем без WinForms такое проделать будет затруднительно. Но кто вам мешает использовать Windows Forms в консольном приложении?
Достаточно подключить библиотеку System.Windows.Forms.dll и написать что-то вроде вот такого
using (var handler = new ClipboardHandler())
{
handler.CreateControl();
Application.Run();
}
Только не забудьте про STAThread. Если же вам нужен способ прервать цикл обработки сообщений - можно воспользоваться CancellationToken:
var cts = new CancellationTokenSource();
// ...
using (var handler = new ClipboardHandler())
{
handler.CreateControl();
using (cts.Token.Register(Application.ExitThread, useSynchronizationContext: true))
Application.Run();
}
Например, можно настроить правильную остановку при нажатии Ctrl+C или Ctrl+Break:
Console.CancelKeyPress += (o, e) =>
{
e.Cancel = true;
cts.Cancel();
};
К сожалению, закрытие консольного окна так просто не перехватывается.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей