В этом упражнении мы построим новое расширение библиотечной кнопки с возможностью проигрывания мелодий. Наша кнопка при щелчке на ней будет воспроизводить не простой сигнал, как в предыдущем упражнении, а полноценный wav -файл. Усовершенствование библиотечной кнопки мы получим за счет добавления новых свойств, обеспечивающих кнопку музыкальностью.
using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Media; // Для проигрывателя wav-файлов SoundPlayer // и системного звука SystemSounds namespace MyCompany.UserControls { public partial class SoundButton : Button { public SoundButton() { InitializeComponent(); } public SoundButton(IContainer container) { container.Add(this); InitializeComponent(); } } }Листинг 19.6. Откорректированная заготовка файла SoundButton.cs
Добавим в класс музыкальной кнопки два свойства WaveFile и WaveStream, через которые будем указывать в клиенте кнопки загружаемый файл для проигрывания.
// Создаем объект-проигрыватель как // поле класса для управления звуком SoundPlayer soundPlayer = new SoundPlayer(); // Свойство подключения звука к проигрывателю из файла public string WaveFile { get { // Что загружено для проигрывания return soundPlayer.SoundLocation; } set { // Подключить файл с диска или URL soundPlayer.SoundLocation = value; } } // Свойство подключения звука к проигрывателю из потока public System.IO.Stream WaveStream { get { // Вернуть ссылку на загруженный в поток файл return soundPlayer.Stream; } set { // Подключить файл к потоку soundPlayer.Stream = value; // Загрузить асинхронно (в фоновом режиме) soundPlayer.LoadAsync(); } }Листинг 19.7. Код свойств загрузки звука в файле SoundButton.cs
В классе расширения кнопки мы создали объект класса SoundPlayer как поле, чтобы он был виден в членах этого класса - в свойствах и переопределенном методе. Свойства WaveFile и WaveStream настраивают объект проигрывания звука и загружают в него указанный в вызывающем коде звук для выполнения в асинхронном (фоновом) режиме в отдельном потоке. Для синхронного проигрывания звука нужно использовать метод Load(), который будет держать приложение, пока звук полностью не проиграется. Свойство WaveFile используется для проигрывания звука из отдельного файла, хранящегося на диске или в Web по URL -адресу.
Как и в случае с кнопкой BeepButton, перехватим событие щелчка на кнопке SoundButton в переопределенном виртуальном методе диспетчеризации библиотечного класса Control и запустим в нем проигрывание адресуемого в свойствах файла
// Переопределяем виртуальный метод класса Control, // чтобы начать проигрывание по щелчку на кнопке protected override void OnClick(EventArgs e) { // Если имя экземпляра кнопки - "Web", // то вместо адресации к удаленному звуку // в Internet проигрываем стандартный звуковой // файл локального компьютера, встроенный // в класс SystemSounds библиотеки .NET Framework if (this.Name.ToUpper() == "Web".ToUpper()) { SystemSounds.Asterisk.Play(); return; } // Загрузить асинхронно - в фоновом режиме. // Поток для кнопки Stream открывается // один раз в конструкторе клиента if (this.Name.ToUpper() != "Stream".ToUpper()) soundPlayer.LoadAsync(); // Если загрузка закончена, то начинаем проигрывание if (soundPlayer.IsLoadCompleted) soundPlayer.Play(); else MessageBox.Show("Проигрыватель пока не готов!"); // Подняться до класса Control, // чтобы сгенерировать событие Click. // Но в этом упражнении не нужно, // поскольку не планируем создавать обработчики // (хотя можно и оставить незакомментированной) // base.OnClick(e); }Листинг 19.8. Код переопределенного метода диспетчеризации в файле SoundButton.cs
Все! Музыкальная кнопка готова. Теперь осталось упаковать ее экземпляры в блок, жестко подключающий проигрываемые файлы, а также поместить его в тестирующее приложение.