Главная страница

лекция. Зиборов. Справочник для опытных и как пособие для начинающих программистов. Компактдиск содержит исходные коды примеров из книги


Скачать 7.39 Mb.
НазваниеСправочник для опытных и как пособие для начинающих программистов. Компактдиск содержит исходные коды примеров из книги
Анкорлекция
Дата13.04.2023
Размер7.39 Mb.
Формат файлаdoc
Имя файлаЗиборов.doc
ТипСправочник
#1060897
страница9 из 31
1   ...   5   6   7   8   9   10   11   12   ...   31

ГЛАВА 6 Управление буфером обмена с данными в текстовом и графическом форматах

Пример 38. Буфер обмена с данными в текстовом формате

Напишем программу для управления буфером обмена с данными в текстовом формате. Эта программа будет позволять записывать какой-либо текст в буфер об­мена (БО), а затем извлекать этот текст из БО. Для этой цели в форме создадим два текстовых поля, а также две командные кнопки под этими полями. Одну кнопку назовем Записать в БО, а другую — Извлечь из БО.

Чтобы записать какой-либо текст в БО, нужно записать его в верхнее поле, вы­делить (с помощью клавиш управления курсором при нажатой клавише <Shift>), а затем нажать кнопку Записать в БО. Нажимая кнопку Записать в БО, мы как бы моделируем комбинацию клавиш <Ctrl>+<C>.

Далее записанный в БО текст можно читать в каком-либо текстовом редакторе или вывести в нижнее текстовое поле прямо в нашей форме. Для этого служит кнопка Извлечь из БО (см. рис. 6.1). Текст данной программы приведен в листинге 6.1.

Листинг 6.1. Запись текстовых данных в буфер обмена и их чтение

// Эта программа имеет возможность записи какого-либо текста в буфер обмена,

// а затем извлечения этого текста из буфера обмена

using System;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace БуферОбменаТХТ

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

this.Text = "Введите текст в верхнее поле";

textBox1.Clear(); textBox2.Clear(); textBox1.Tablndex = 0;

button1.Text = "Записать в БО";

button2.Text = "Извлечь из БО";

}

private void button1_Click(object sender, EventArgs e)

{ // Записать выделенный в верхнем поле текст в БО

if (textBox1.SelectedText != String.Empty)

{

Clipboard.SetDataObject(textBox1.SelectedText);

textBox2 . Text = String. Empty;

}

else

textBox2.Text = "В верхнем поле текст не выделен";

}

private void button2_Click(object sender, EventArgs e)

{ // Объявление объекта-получателя из БО

IDataObject Получатель = Clipboard.GetDataObject();

// Если данные в БО представлены в текстовом формате...

if (Получатель.GetDataPresent(DataFormats.Text) == true)

//то записать их в Text тоже в текстовом формате

textBox2.Text = Получатель,GetData(DataFormats.Text).ToString();

else

textBox2.Text = "Запишите что-либо в буфер обмена";

}

}

}

Как видно из программного кода, при обработке события "щелчок на верхней кнопке", если текст в верхнем поле выделен, то записываем его (SelectedText) вбуфер обмена (Сlipboard) командой (методом) SetDataObject, иначе (else) сообщаем в нижнем поле textBox2 о том, что в верхнем поле текст не выделен.

Напомню, что, нажимая кнопку Извлечь из БО, в нижнем поле пользователь нашей программы должен увидеть содержимое буфера обмена. Для этого объявляем объектную переменную Получатель. Это объект-получатель из буфера обмена. Данная переменная сознательно названа по-русски для большей выразительности. Далее следует проверка: в текстовом ли формате (DataFormat.Text) данные, представленные в буфере обмена. Если формат текстовый, то в текстовое поле TextBox2 записываем содержимое буфера обмена, используя функцию ToString. Эта функ­ция конвертирует строковую часть объекта в строковую переменную. Пример работы приложения показан на рис. 6.1.



Рис. 6.1. Запись текстовых данных в буфер обмена и их чтение

Убедиться в работоспособности программы можно, открыв решение БуферОбменаTXT.sln в папке БуферОбменаТХТ.

Пример 39. Элемент управления PictureBox. Буфер обмена с растровыми данными

Обсудим программу, которая оперирует буфером обмена, когда тот содержит изображение. Здесь мы будем использовать элемент управления PictureBox (гра­фическое окно), который способен отображать в своем поле растровые файлы раз­личных форматов, в том числе BMP, JPEG, PNG, GIF и др. Возможность отображе­ния в PictureBox GIF-файлов позволяет просматривать анимацию, т. е. движущееся изображение, в экранной форме вашей программы. Пример отображения такой GIF -анимации вы можете посмотреть, открыв решение PictureBoxGif.sln в папке РictureBoxGif. Однако элемент управления PictureBox не способен отображать Flash-файлы в формате SWF, которые сочетают в себе векторную графику, растровую графику и воспроизведение звука. Замечу, что файлы SWF воспроизводит элемент управления Microsoft WebBrowser, который мы обсудим в главе 8.

Рассматриваемая программа выводит в поле элемента управления PictureBox "Сражение из растрового файла (например, PNG). При этом изображение запи­вается в БО. Пользователь может убедиться в этом, например, запустив Paint —стандартный графический редактор ОС Windows. Далее пользователь может по­ртить в БО любое изображение с помощью какого-нибудь графического редак тора, например того же Paint, ACDSee или др. Затем, нажав кнопку Извлечь из БО, нашей программы, получить в форме содержимое БО.

Для создания данной программы в форму из панели Toolbox перетащим элементы управления PictureBox (графическое окно) и кнопку Button. Текст программы приведен в листинге 6.2.

Листинг 6.2. Обмен графическими данными через буфер обмена

//Программа оперирует буфером обмена, когда тот содержит изображение

using System;

using System.Drawing;

using System. Windows. Forms ;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace Буфер0бменаВitmар

{

public partial class Form1: Form

{

public Form1 ()

{

InitializeComponent();

base.Text = "Содержимое БО:"; button1.Text = "Извлечь из БО";

// Записать в PictureBox изображение из файла

pictureBox1.Image = Image.FromFile(System.IO.Directory.GetCurrentDirectory () + @"\poryv.png");

// Записать в БО изображение из графического окна формы

Clipboard.SetDataObject(pictureBox1.Image);

}

private void button1_Click(object sender, EventArgs e)

{ // Объявление объекта-получателя из буфера обмена

IDataObject Получатель = Clipboard.GetDataObject();

Bitmap Растр;

// Если данные в БО представлены в формате Bitmap...

if (Получатель.GetDataPresent(DataFormats.Bitmap) == true)

{ //то записать эти данные из БО в переменную Растр //в формате Bitmap

Растр = (Bitmap)Получатель.GetData(DataFormats.Bitmap);

pictureBox1.Image = Растр;

}

}

}

}

Как видно из текста программы, при загрузке программы в графическое окно формы pictureBox1 записываем какой-нибудь файл, например poryv.png. Этот файл необходимо поместить в ту же папку, где расположен ехе-файл данной программы, т.е. в папку Debug (при отладке приложения). Функция Directory.GetCurrentDirectory () возвращает полный путь текущей папки. Данная « функция относится к пространству имен System.IO. Далее по команде Clipboard.SetDataObject(pictureBox1.Image)

происходит запись содержимого графического окна в буфер обмена.

Теперь пользователь может проверить содержимое БО с помощью какого-либо графического редактора, например Paint. Далее пользователь может записать что-либо в буфер обмена, опять же используя какой-нибудь графический редактор. Нажатие кнопки Извлечь из БО нашей программы в форме приведет к появлению изображения, находящегося в буфере обмена. Фрагмент работы программы пред­ставлен на рис. 6.2.



Рис. 6.2. Извлечение изображения из буфера обмена

В программном коде при обработке события "щелчок на кнопке" Извлечь из БО объявляем объектную переменную Получатель. Это объект, с помощью кото­рого будем получать изображение, записанное в буфер обмена. Эта переменная сонательно названа по-русски для большей выразительности. Далее следует про­верка: записаны ли данные, представленные в БО, в формате растровой графики Bitmap. Если да, то записать данные из БО в переменную Растр в формате Bitmap с помощью объектной переменной Получатель, используя неявное преобразование в переменную типа Bitmap. Далее, чтобы изображение появилось в элементе управ­ления pictureBox1 в форме, присваиваем свойству Image значение переменной Растр.

Убедиться в работоспособности программы можно, открыв решение БуферОбменаBitmap.sln в папке БуферОбменаBitmap.

Пример 40. Имитация нажатия комбинации клавиш <Alt>+<PnntScreen>. Вызов функции Microsoft API

Как известно, при нажатии клавиши <PrintScreen> происходит копирование изображения экрана в буфер обмена, т. е. получаем так называемый screen shot моментальный снимок экрана (другое название — screen capture). После извлечения из БО графической копии экрана в любом графическом редакторе (например Paint) эту графическую копию можно редактировать.

При нажатии комбинации клавиш <Alt>+<PrintScreen> в буфер обмена копиру ется не весь экран, а только активное окно. Для имитации нажатия сочетания клавиш <Alt>+<PrintScreen> можно использовать соответствующую функцию Microsoft API. В то же время современная система программирования Visual Studio в пространстве имен System.Windows.Forms имеет класс SendKeys, который предоставляет методы для отправки приложению сообщений о нажатиях клавиш, в том числе и нашей комбинации клавиш <Alt>+<PrintScreen>. В этом примере мы рассмотрим обе эти возможности.

Данная программа сознательно максимально упрощена, чтобы более вырази­тельно показать ее суть. Здесь в форме имеем только две кнопки. При обработке события "щелчок на первой кнопке" будем имитировать нажатие комбинации кла­виш <Alt>+<PrintScreen> с помощью функции Microsoft API, а при обработке со­бытия "щелчок на второй кнопке" будем имитировать нажатие этих же клавиш ме­тодом Send класса SendKeys. Результаты нажатия любой из кнопок будут совершенно одинаковы. При этом форму можно как угодно менять— растягивай по ширине и по высоте, но после нажатия любой из кнопок в форме изображение формы запишется в буфер обмена. Следует убедиться в этом: запустить Paint и из­влечь графическую копию формы из буфера обмена. Текст программы представлен в листинге 6.3.

Листинг 6.3. Имитация нажатия комбинации клавиш <Alt>+<PrintScreen>

// Программная имитация нажатия клавиш + с помощью

// функции Microsoft Windows API, а также методом Send класса SendKeys

using System;

using System. Windows. Forms ;

using System.Runtime. InteropServices; // - следует добавить эту директиву

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace AltPrintScreen

{

public partial class Form1: Form

{ // Следует добавить пространство имен

// using System.Runtime.InteropServices.

//Объявление функции Microsoft API

[DllImport("user32.dll")]

extern static void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtralnfo);

public Form1()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{ // Вызов функции Microsoft API

keybd_event(44, 1, 0, 0);

}

private void button2_Click(object sender, EventArgs e)

{ //Метод SendKeys.Send посылает сообщение активному приложению

//онажатии клавиш +


SendKeys.Send("%{PRTSC} ") ;

// string QQ = Keys.PrintScreen.ToString();

}

}

}

В этой программе при обработке события "щелчок на первой кнопке" мы вос­пользовались функцией Microsoft Windows API (Application Programming Interface, интерфейс программирования приложений). Функция keybd_event () позволяет имитировать (эмулировать) нажатие пользователем клавиш. Функция находится в динамической библиотеке user32.dll (см. программный код). В динамической биб­лиотеке user32.dll также присутствуют управляющие функции Windows для обра­ботки сообщений, таймеров, меню и взаимодействия. Эту библиотеку вы можете увидеть в системном каталоге C:\Windows\System32. В dll-файлах (dynamic link li­brary) находятся скомпилированные классы.

Как видно, сначала функцию API следует объявить с указанием типов аргумен­те, подаваемых на вход функции keybd_event(). Параметр "user32" или User32 .dll" определяет имя используемой библиотеки. В скобках записан список apгументов функции keybd_event (). Мы можем задавать любые имена аргументов, но их типы должны соответствовать формату функции API.

При обработке события "щелчок на кнопке" Button1_Click() мы программируем вызов API-функции keybd_event () по формату, заданному в объявлении функции. Из четырех аргументов функции keybd_event () важным является первый, он задает код клавиши <PrintScreen>. Можно задать шестнадцатеричный код, равный 0xH2CS, однако мы задали десятичный код клавиши <PrintScreen>, равный 44.

Также представляет интерес второй аргумент функции keybd_event (). Второй аргумент, равный единице, эмулирует одновременное нажатие клавиши <Alt> c клавишей <PrintScreen>. Таким образом, вызывая функцию keybd_event (44, 0, 0), мы эмулируем нажатие комбинации клавиш <Alt>+<PrintScreen>, а keybd_event(44, 0, 0, 0) — нажатие только <PrintScreen>. С помощью функции keybd_event () можно эмулировать нажатие любых клавиш, подавая вход функции коды соответствующих клавиш.

Обрабатывая событие "щелчок на второй кнопке", мы решаем абсолютно ту задачу, но более современными средствами. Метод Send класса SendKeys посылает сообщение активному приложению о нажатии комбинации клавиш <Alt> +<PrintScreen>. Кодом клавиши <PrintScreen> является код "{prtsc}". Чтобы указать сочетание клавиши <Alt> +<PrintScreen>, следует в этот код добавить символ процента: "%{prtsc}". Коды других клавиш можно посмотреть по адресу:

http://msdn.microsoft.com/ru-ru/library/system.windows.forms.sendkeys.aspх

Таким образом, результаты нажатия обеих клавиш одинаковы. Убедиться в работоспособности программы можно, открыв решение AltPrintScreen.sln в папке AltPrintScreen.

Пример 41. Запись содержимого буфера обмена в ВМР-файл

Напишем программу, которая читает буфер обмена, и если данные в нем п

ставлены в формате растровой графики, то записывает эти данные в ВМР-файл Текст этой программы приведен в листинге 6.4.

Листинг 6.4. Запись содержимого буфера обмена в ВМР-файл

// Программа читает буфер обмена, и если данные в нем представлены

// в формате растровой графики, то записывает их в ВМР-файл

using System;

using System.Drawing;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace БуферОбменаSaveBMP

{

public partial class Form1:Form

{

public Form1()

{

InitializeComponent();

this.Text = "Сохраняю копию БО в ВМР-файл";

button1.Text = "Сохранить";

}

private void button1_Click(object sender, EventArgs e)

{ // Объявление объекта-получателя из буфера обмена

IDataObject Получатель = Clipboard.GetDataObjectО;

Bitmap Растр;

// Если данные в буфере обмена представлены в формате Bitmap...

if (Получатель.GetDataPresent(DataFormats.Bitmap) == true)

{ //то записать их из БО в переменную Растр в формате Bitmap

Растр = (Bitmap)Получатель .GetData (DataFormats .Bitmap)

// Сохранить изображение в файле Clip.bmp

Растр.Save(@"С:\Clip.BMP");

//this.Text = @"Сохранено в файле C:\Clip.BMP";

//button1.Text = "Еще записать?";

MessageBox.Show (@"Изображение из БО записано в файл C:\Clip.BMP", "Успех");

}

else

// В БО нет данных в формате изображений

MessageBox.Show("В буфере обмена нет данных в формате Bitmap",

"Запишите какое-либо изображение в БО");

}

}

}



Рис. 6.3. Запись изображения из буфера обмена в файл

Впрограммном коде при обработке события "щелчок на кнопке" Сохранить объявляем объектную переменную Получатель. Это объект-получатель из буфера обмена. Далее следует проверка: записаны ли данные, представленные в буфере обмена, в формате растровой графики Bitmap. Если да, то записать данные из буфера обмена в переменную Растр в формате Bitmap с помощью объектной переменной Получатель, используя неявное преобразование в переменную типа Bitmap. Сохранить изображение Растр на винчестер очень просто, воспользовавшись методом Save(). Чтобы не запутать читателя и упростить программу, автор не стал организовывать запись файла в диалоге. При необходимости читатель сделает э самостоятельно, воспользовавшись элементом управления SaveFileDialog. Фрагмент работы данной программы представлен на рис. 6.3.

Убедиться в работоспособности программы можно, открыв решение БуферОбменаSaveBMP.sln в папке БуферОбменаSaveBMP.

Пример 42. Использование таймера Timer

Автор несколько раз встречал задачу записи моментальных снимков экрана (screen shot) в растровые файлы с некоторым промежутком времени, например пять секунд. Кстати, такая задача была выставлена на тендер на сайте оффшорного программирования (www.rentacoder.com). За ее решение указывалось вознаграждение 100 долларов США. Конечно, сразу появляется очень много желающих эту задачу решить, но попробуйте выиграть тендер.

Следующая задача является частью упомянутой задачи, ее сформулируем таким образом: после запуска программы должна отображаться форма с элементом управления ListBox, а через две секунды в список добавляется запись "Прошло две секунды", далее через каждые две секунды в список добавляется аналогична запись. На этой задаче мы освоим технологию работы с таймером.

Для реализации программы в форму из панели элементов Toolbox перетащим элемент управления Timer и список ListBox. Программный код приведен в листинге 6.5.

Листинг 6.5. Использование таймера

// Демонстрация использования таймера Timer. После запуска программы

// показываются форма и элемент управления список элементов ListBox.

// Через 2 секунды в списке элементов появляется запись "Прошло две секунды",

// и через каждые последующие 2 секунды в список добавляется аналогичная запись

using System;

using System.Windows. Forms ;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace ПростоТаймер

{

public partial class Form1:Form

{

public Form1()

{

InitializeComponent();

this.Text = "Timer";

timer1.Interval = 2000; // - 2 секунды

// Старт отчета времени

Timer1.Enabled = true; // - время пошло

}
private void timer1_Tick(object sender, EventArgs e)

{

listBox1.Items.Add("Прошло две секунды");

}

}

}

Экземпляр класса Timer — это невидимый во время работы программы элемент управления, предназначенный для периодического генерирования события Tick. В программном коде сразу после инициализации конструктором компонентов программы задаем интервал времени (interval), равный 2000 миллисекунд (две секунды). Каждые две секунды будет возникать событие Tick, при этом в список элементов listBox1 будет добавляться запись "Прошло две секунды ". Этот текст будет выводиться каждые две секунды до тех пор, пока пользователь программы не щелкнет на кнопке формы Закрыть. На рис. 6.4 показан фрагмент работы про­граммы.



Рис. 6.4. Вывод сообщения

Убедиться в работоспособности программы можно, открыв решение ПростоТаймер.sln в папке ПростоТаймер.

Пример 43. Запись в файлы текущих состояний экрана каждые пять секунд

Как уже говорилось в предыдущем разделе, работа с таймером — довольно распространенная задача. Напишем очередную программу в следующей постановке. После запуска программы через каждые пять секунд снимается текущее состояние экрана и записывается в файлы Pic1.BMP,… Pic5.BMP.

Для решения данной задачи мы имеем уже весь инструментарий, он был рассмотрен в предыдущих задачах. А именно, задание интервала времени в пять секунд с помощью элемента управления Timer, эмуляция нажатия клавиш <Alt>+<PrintScreen> для записи текущего состояния экрана в буфер обмена и, наконец, чтение буфера обмена в формате изображения и запись этого изображени файл BMP.

Для решения задачи перетаскиваем в форму элементы управления Timer и Вutton. Текст программы приведен в листинге 6.6.

Листинг 6.6. Запись в файлы текущих состояний экрана с интервалом 5 секунд

// Программа после запуска каждые пять секунд делает снимок текущего

// состояния экрана и записывает эти снимки в файлы Pic1.BMP, Pic2.BMP

// и т. д. Количество таких записей в файл — пять

using System;

using System. Drawing;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace SaveCкpиншoтKaждыe5ceк

{

public partial class Form1 : Form

{

int i = 0; // счет секунд

public Form1 ()

{

InitializeComponent();

this.Text = "Запись каждые 5 секунд в файл";

button1.Text = "Пуск";

}

private void timer1_Tick(object sender, EventArgs e)

{

i = i + 1;

this.Text = string.Format("Прошло {0} секунд", i);

if (i >= 28) { timer1.Enabled = false; this.Close(); }

if (i % 5 != 0) return;

// Имитируем нажатие клавиш +
SendKeys.Send("%{PRTSC}");

// Объявление объекта-получателя из буфера обмена

IDataObject Получатель = Clipboard.GetDataObject ();

Bitmap Растр;

// Если данные в буфере обмена представлены в формате Bitmap, то записать

if (Получатель.GetDataPresent(DataFormats.Bitmap) == true)

{ // эти данные из буфера обмена в переменную Растр в формате Bitmap

Растр = (Bitmap)Получатель.GetData(DataFormats.Bitmap);

// Сохранить изображение из переменной Растр

// в файл C:\Picl, C:\Pic2, C:\Pic3, ...

string ИмяФайла = string.Format(@"С:\Pic{0}.BMP", i / 5);
Растр. Save (ИмяФайла) ;

}

}

private void button1_Click(object sender, EventArgs e)

{

this.Text = string.Format("Прошло 0 секунд");

timer1.Interval = 1000; // равно 1 секунде

timer1.Enabled = true; // время пошло

}

}

}

Как видно, структура программы включает в себя обработку события "щелчок на кнопке" button1_Сlick и обработку события Timer1_Tick. В начале программы задаем переменную i, которая считает, сколько раз программа сделает запись в бу­фер обмена, а из буфера обмена — в файл. При щелчке на кнопке Пуск задаем ин­тервал времени interval, равный 1000 миллисекунд, т. е. одной секунде. Далее даем команду таймеру начать отсчет времени timer1.Enabled = true и через каж­дую секунду наступает событие timer1_Tick(), т.е. управление переходит этой процедуре.

При обработке события timer1_Tick наращиваем значение переменной i, кото­рая ведет счет секунд после старта таймера. Выражение i % 5 вычисляет целочис­ленный остаток после деления первого числового выражения на второе. Понятно, что если число i будет кратно пяти, то этот остаток будет равен нулю, и только в этом случае будет происходить имитация нажатия клавиш <Alt>+<PrintScreen> и запись содержимого буфера обмена в файл.

Убедиться в работоспособности программы можно, открыв соответствующее pешение в папке SavеСкриншотКаждые5сек.

1   ...   5   6   7   8   9   10   11   12   ...   31


написать администратору сайта