前回はフォームバージョンにしてみました。
実行してみると分かりますが、音を鳴らしている間は、フォームが動きません。これは、フォームの処理と音を鳴らす処理が片方ずつ処理されているからです。
というわけで、今回は、マルチスレッド化して、音を鳴らしている間もフォームが動かせるようにしてみます。マルチスレッドについては、適当にインターネットで調べてみてください。
マルチスレッドのやり方も複数あるみたいですが、今回はスタンダードっぽいやり方をしてみました。本当はもっといいやり方があるかもしれません。そこは趣味のプログラムということで、ご勘弁。
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
class Program
{
[STAThread]
static void Main()
{
Application.Run( new FormMidi());
}
}
class FormMidi : Form
{
/*--------------------------------------------------*/
[DllImport( "Winmm.dll")]
extern static uint midiOutGetNumDevs();
[DllImport( "Winmm.dll")]
extern static uint midiOutOpen( ref long lphmo, uint uDeviceID, uint dwCallback, uint dwCallbackInstance, uint dwFlags);
[DllImport( "Winmm.dll")]
extern static uint midiOutClose( long hmo);
[DllImport( "Winmm.dll")]
extern static uint midiOutShortMsg( long hmo, uint dwMsg);
[DllImport( "Winmm.dll")]
extern static uint midiOutReset( long hmo);
private const uint MMSYSERR_NOERROR = 0;
private const uint MMSYSERR_BADDEVICEID = 2;
private const uint MMSYSERR_ALLOCATED = 4;
private const uint MMSYSERR_NOMEM = 7;
private const uint MMSYSERR_INVALPARAM = 11;
private const uint MMSYSERR_NODEVICE = 68;
private const uint MMSYSERR_INVALHANDLE = 5;
private const uint MIDIERR_STILLPLAYING = 65;
private const uint MIDI_MAPPER = 0xffffffff;
/*--------------------------------------------------*/
Thread thread;
long hMidi;
Button btn_play;
Button btn_stop;
public FormMidi()
{
this.ClientSize = new Size( 240, 120);
this.Text = "Midi";
this.Load += new EventHandler( this.FormMidi_Load);
this.Closed += new EventHandler( this.FormMidi_Closed);
this.btn_play = new Button();
this.btn_play.SetBounds( 20, 40, 90, 40);
this.btn_play.Font = new Font( "Arial", 12);
this.btn_play.Text = "Play";
this.btn_play.Click += new EventHandler( this.btn_play_Click);
this.Controls.Add( this.btn_play);
this.btn_stop = new Button();
this.btn_stop.SetBounds( 130, 40, 90, 40);
this.btn_stop.Font = new Font( "Arial", 12);
this.btn_stop.Text = "Stop";
this.btn_stop.Click += new EventHandler( this.btn_stop_Click);
this.Controls.Add( this.btn_stop);
}
/*--------------------------------------------------*/
/* Load */
/*--------------------------------------------------*/
private void FormMidi_Load( object sender, EventArgs e)
{
Console.WriteLine( "FormMidi_Load");
ThreadStart ts = new ThreadStart( this.Play);
this.thread = new Thread( ts);
}
/*--------------------------------------------------*/
/* Closed */
/*--------------------------------------------------*/
private void FormMidi_Closed( object sender, EventArgs e)
{
Console.WriteLine( "FormMidi_Closed");
if( this.thread.IsAlive == true)
{
this.PlayStop();
}
}
/*--------------------------------------------------*/
/* Clicked */
/*--------------------------------------------------*/
private void btn_play_Click( object sender, EventArgs e)
{
Console.WriteLine( "btn_play_Click");
if( this.thread.IsAlive == false)
{
this.PlayStart();
}
}
private void btn_stop_Click( object sender, EventArgs e)
{
Console.WriteLine( "btn_stop_Click");
if( this.thread.IsAlive == true)
{
this.PlayStop();
}
}
/*--------------------------------------------------*/
/* PlayStart */
/*--------------------------------------------------*/
private void PlayStart()
{
if( midiOutOpen( ref this.hMidi, MIDI_MAPPER, 0, 0, 0) != MMSYSERR_NOERROR)
{
MessageBox.Show( "midiOutOpen error");
return;
}
ThreadStart ts = new ThreadStart( this.Play);
this.thread = new Thread( ts);
this.thread.IsBackground = true;
this.thread.Start();
}
/*--------------------------------------------------*/
/* Play */
/*--------------------------------------------------*/
private void Play()
{
uint msg;
byte[] keys = new byte[8];
keys[0] = (byte) 60;
keys[1] = (byte) 62;
keys[2] = (byte) 64;
keys[3] = (byte) 65;
keys[4] = (byte) 67;
keys[5] = (byte) 69;
keys[6] = (byte) 71;
keys[7] = (byte) 72;
for( int i = 0; i < keys.Length; i++)
{
Console.WriteLine( "note on " + "\t" + keys[i]);
msg = (uint) ( ( 0x7f << 16) + ( keys[i] << 8) + 0x90);
midiOutShortMsg( this.hMidi, msg);
Thread.Sleep( 500);
Console.WriteLine( "note off" + "\t" + keys[i]);
msg = (uint) ( ( 0x7f << 16) + ( keys[i] << 8) + 0x80);
midiOutShortMsg( this.hMidi, msg);
}
midiOutReset( this.hMidi);
midiOutClose( this.hMidi);
}
/*--------------------------------------------------*/
/* PlayStop */
/*--------------------------------------------------*/
private void PlayStop()
{
this.thread.Abort();
midiOutReset( this.hMidi);
midiOutClose( this.hMidi);
}
}
0 件のコメント:
コメントを投稿