none
請問使用Windows Callback function的問題? RRS feed

  • 問題

  • 各位好:
    我在微軟的網站上捉到一個example,功能為播放wave檔,
    以win32的api去實作,程式將wave檔分成很多個block,
    然後create兩個buffer,將block的資料輪流放到兩個buffer當中,
    再寫入到audio device。
    http://msdn2.microsoft.com/en-us/library/aa446573.aspx

    而其中有一段code是利用windows Callback function的方式,
    在一個block播放完畢之後,利用Callback function將下一個block的資料載入另一個buffer,
    不過我trace下面這段code,都不會跑進case MM_WOM_DONE裡頭,
    可是我加入MessageBox.Show(msg.Msg.ToString());,每當我按下訊息方塊的OK之後,
    才會跑進case MM_WOM_DONE裡,block的資料才會順利載入,
    所以搞不太懂Windows Callback function如何使用,找了以下這篇文章來看,
    不過還是不知道怎麼讓wave順利播放,麻煩各位先進指點一下。
    http://www.microsoft.com/taiwan/msdn/columns/DoNet/MessageLoop.htm
       
    Thanks for any message.
    Josh

      
    Code Snippet

            // <summary>
            // Defines the MessageWindow used to receive messages from the audio
            // system.
            // </summary>

            public class SoundMessageWindow : MessageWindow
            {
                public const int MM_WOM_OPEN  = 0x03BB;
                public const int MM_WOM_CLOSE = 0x03BC;
                public const int MM_WOM_DONE  = 0x03BD;  //當資料播放完畢的代碼

                // Instance of a playback interface
                protected WaveOut m_wo = null;

                public SoundMessageWindow(WaveOut wo)
                {
                    m_wo = wo;
                }

                protected override void WndProc(ref Message msg)
                {
                    MessageBox.Show(msg.Msg.ToString());
                    switch (msg.Msg)
                    {
                        case MM_WOM_DONE:
                            m_wo.BlockDone(msg.WParam); //將下一個block的資料載入
                            break;
                    }
                    base.WndProc(ref msg);
                }
            }

    2008年4月7日 下午 06:08

解答

所有回覆

  • Hi,
    You can use delegate to solve the problem.
    There's a sample code from http://www.codeproject.com/KB/mobile/cfgamenerdkill.aspx?display=Print
    private class RWaveOutMsgWindow: MessageWindow
    {
      public delegate void Callback(IntPtr waveHdrPtr);
    
      public void SetBufferDoneCallback(Callback cb)
      {
        mBufferDoneCallback = cb;
      }
    
      protected override void WndProc(ref Message m)
      {
        if (m.Msg == RWaveOut.MM_WOM_DONE && mBufferDoneCallback != null)
          mBufferDoneCallback(m.LParam);
        base.WndProc(ref m);
      }
    
      private Callback mBufferDoneCallback = null;
    }
    
    public RSoundPlayer()
    {
      ...
      mWceMessageWindow = new RWaveOutMsgWindow();
      mWceMessageWindow.SetBufferDoneCallback(
        new RWaveOutMsgWindow.Callback(this.waveOutBufferDone));
      ...
    }
    
    Hope it's useful!!!
    Blake
    

     

    2008年4月8日 上午 08:54
  • 您好:

    我按照你的方法,利用delegate去做,
    還是無法進入下面這個判斷式,
    if (m.Msg == RWaveOut.MM_WOM_DONE && mBufferDoneCallback != null)
    如果在判斷之前加了一個Messagebox.Show()就可以,
    跟之前的情況一樣,請再指點一下,謝謝。

    Thanks for any message.
    Josh
    2008年4月8日 下午 05:04
  • 各位好:

    後來我有找到一個完整的範例,不過是for PC使用的,
    修改一下就可以放在Pocket PC上,
    而這個範例跟微軟提供的範例不同之處在於,
    這個是使用Callback_FUNCTION,而微軟是使用Callback_WINDOW,
    以下為範例網址,提供給大家參考。
    http://www.codeproject.com/KB/audio-video/cswavplay.aspx

    Josh
    2008年4月10日 上午 12:13