随笔-89  评论-944  文章-0  trackbacks-0

上一篇中,我们实现了COM_INTERFACE宏,并且重新写了一个含有WebBrowser的窗口。在那里我们留了中间层OleContainer。为了验证OleContainer的可用性,现在来写一个含有Windows Media Player(下文简称“WMP”)控件的窗口。

 

WMP控件的容器类除了IOleClientSiteIOleInPlaceSiteIOleInPlaceFrame外,还要实现IDispatch,这些接口的 IXXXImpl 都已经有了,所以做起来就比较方便了:

 

http://xllib.codeplex.com/SourceControl/changeset/view/19631#315488

#include <wmp.h>

#include <xl/Win32/COM/Objects/xlOleContainer.h>

#include <xl/Win32/COM/InterfaceHelper/xlIDispatchImpl.h>

 

namespace xl

{

    class MediaPlayerImpl : public OleContainerImpl,

                            public IDispatchImpl<>

    {

    public:

        MediaPlayerImpl() : m_pWMPPlayer(nullptr)

        {

 

        }

 

        ~MediaPlayerImpl()

        {

            DestroyMediaPlayer();

        }

 

    public:

        bool CreateMediaPlayer(HWND hWnd, LPCRECT lpRect = nullptr)

        {

            DestroyMediaPlayer();

 

            if (!CreateOleObject(__uuidof(WindowsMediaPlayer)))

            {

                return false;

            }

 

            if (!InPlaceActive(hWnd, lpRect))

            {

                return false;

            }

 

            HRESULT hr = m_pOleObj->QueryInterface(__uuidof(IWMPPlayer), (LPVOID *)&m_pWMPPlayer);

 

            if (FAILED(hr))

            {

                return false;

            }

 

            return true;

        }

 

        void DestroyMediaPlayer()

        {

            if (m_pWMPPlayer != NULL)

            {

                m_pWMPPlayer->Release();

                m_pWMPPlayer = nullptr;

            }

 

            DestroyOleObject();

        }

 

    protected:

        IWMPPlayer *m_pWMPPlayer;

    };

 

    class MediaPlayer : public ComClass<MediaPlayer>,

                        public MediaPlayerImpl

    {

    public:

        MediaPlayer()

        {

 

        }

 

        ~MediaPlayer()

        {

            DestroyMediaPlayer();

        }

 

    public:

        XL_COM_INTERFACE_BEGIN(MediaPlayer)

            XL_COM_INTERFACE(IOleClientSite)

            XL_COM_INTERFACE(IOleInPlaceSite)

            XL_COM_INTERFACE(IOleInPlaceFrame)

            XL_COM_INTERFACE(IDispatch)

        XL_COM_INTERFACE_END()

    };

 

} // namespace xl

 

WindowsMediaPlayer这个coclasswmp.h中定义,OleCreate的时候指定它就可以了。创建好了以后,拿到IWMPPlayer接口,就算完事了,后续的控制可以由该接口完成。

 

然后,仿照前面的样子写个例程:

 

#include <xl/Win32/COM/Objects/xlMediaPlayer.h>

 

class MediaPlayer : public xl::MediaPlayer

{

public:

    void Play(LPCTSTR lpUrl)

    {

        BSTR bstrUrl = SysAllocString(lpUrl);

        m_pWMPPlayer->put_URL(bstrUrl);

        SysFreeString(bstrUrl);

    }

};

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

 

    return 0;

}

 

int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,

                       _In_opt_ HINSTANCE hPrevInstance,

                       _In_ LPTSTR        lpCmdLine,

                       _In_ int           nCmdShow)

{

    UNREFERENCED_PARAMETER(hPrevInstance);

    UNREFERENCED_PARAMETER(lpCmdLine);

 

    const LPCTSTR CLASS_NAME = _T("MediaPlayerContainer");

 

    WNDCLASSEX wcex    = { sizeof(WNDCLASSEX) };

    wcex.style         = CS_HREDRAW | CS_VREDRAW;

    wcex.lpfnWndProc   = WndProc;

    wcex.cbClsExtra    = 0;

    wcex.cbWndExtra    = 0;

    wcex.hInstance     = hInstance;

    wcex.hCursor       = LoadCursor(nullptr, IDC_ARROW);

    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

    wcex.lpszClassName = CLASS_NAME;

 

    RegisterClassEx(&wcex);

 

    HWND hWnd = CreateWindow(CLASS_NAME,

                             _T("MediaPlayer Sample"),

                             WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,

                             CW_USEDEFAULT,

                             0,

                             CW_USEDEFAULT,

                             0,

                             nullptr,

                             nullptr,

                             hInstance,

                             nullptr);

 

    if (hWnd == nullptr)

    {

        return 0;

    }

 

    ShowWindow(hWnd, nCmdShow);

    UpdateWindow(hWnd);

 

    RECT rect = {};

    GetClientRect(hWnd, &rect);

 

    rect.left   += 100;

    rect.top    += 100;

    rect.right  -= 100;

    rect.bottom -= 100;

 

    MediaPlayer mp;

 

    if (!mp.CreateMediaPlayer(hWnd, &rect))

    {

        return 0;

    }

 

    mp.Play(_T("Sample.mid"));

 

    MSG msg = {};

 

    while (GetMessage(&msg, nullptr, 0, 0))

    {

        if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))

        {

            TranslateMessage(&msg);

            DispatchMessage(&msg);

        }

    }

 

    return (int)msg.wParam;

}

 

上面测试了一下创建的时候指定一个矩形区域,看看是否能定位到目标位置。IWMPPlayerURL属性表示要播放的文件路径或网络地址,设上的时候就会开始播放。运行效果:

 

clip_image001[4]

上见MediaPlayerSample.rarhttp://pan.baidu.com/s/1txy2

 

也可以和GUI类一起使用:

 

#include <xl/Win32/GUI/xlWindow.h>

#include <xl/Win32/COM/Objects/xlMediaPlayer.h>

 

class MediaPlayer : public xl::MediaPlayer

{

public:

    void Play(LPCTSTR lpUrl)

    {

        BSTR bstrUrl = SysAllocString(lpUrl);

        m_pWMPPlayer->put_URL(bstrUrl);

        SysFreeString(bstrUrl);

    }

};

 

class MyWindow : public xl::Window

{

public:

    MyWindow()

    {

        AppendMsgHandler(WM_DESTROY, MsgHandler(this, &MyWindow::OnDestroy));

    }

 

    ~MyWindow()

    {

   

    }

 

private:

    LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)

    {

        PostQuitMessage(0);

        return 0;

    }

};

 

int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,

                       _In_opt_ HINSTANCE hPrevInstance,

                       _In_ LPTSTR        lpCmdLine,

                       _In_ int           nCmdShow)

{

    MyWindow wnd;

   

    if (!wnd.Create())

    {

        return 0;

    }

 

    wnd.ShowWindow();

 

    MediaPlayer mp;

 

    if (!mp.CreateMediaPlayer(wnd.GetHWND()))

    {

        return 0;

    }

 

    mp.Play(_T("Sample.mid"));

 

    MSG msg = {};

 

    while (GetMessage(&msg, nullptr, 0, 0))

    {

        if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))

        {

            TranslateMessage(&msg);

            DispatchMessage(&msg);

        }

    }

 

    return (int)msg.wParam;

}

 

以上MediaPlayerSample2.rarhttp://pan.baidu.com/s/1gdd6YXH

 

或者作为GUI类的成员:

 

#include <xl/Win32/GUI/xlDialog.h>

#include <xl/Win32/COM/Objects/xlMediaPlayer.h>

 

class MediaPlayer : public xl::MediaPlayer

{

public:

    void Play(LPCTSTR lpUrl)

    {

        BSTR bstrUrl = SysAllocString(lpUrl);

        m_pWMPPlayer->put_URL(bstrUrl);

        SysFreeString(bstrUrl);

    }

};

 

class MyDialog : public xl::Dialog

{

private:

    bool OnInitDialog()

    {

        if (!m_wmp.CreateMediaPlayer(m_hWnd))

        {

            return false;

        }

 

        m_wmp.Play(_T("Sample.mid"));

 

        return true;

    }

 

private:

    MediaPlayer m_wmp;

};

 

int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,

                       _In_opt_ HINSTANCE hPrevInstance,

                       _In_ LPTSTR        lpCmdLine,

                       _In_ int           nCmdShow)

{

    MyDialog dlg;

 

    if (!dlg.Create(400, 400))

    {

        return 0;

    }

 

    dlg.DoModal();

 

    return 0;

}

 

以上MediaPlayerSample3.rarhttp://pan.baidu.com/s/1gdmuySN

 

也可以让GUI类继承于它(可能的话,可附加实现WMP的别的COM接口或给出别的对外操作方法):

 

#include <xl/Win32/GUI/xlDialog.h>

#include <xl/Win32/COM/Objects/xlMediaPlayer.h>

 

class WMPDialog : public xl::Dialog,

                  public xl::MediaPlayer

{

private:

    bool OnInitDialog()

    {

        if (!CreateMediaPlayer(m_hWnd))

        {

            return false;

        }

 

        return true;

    }

 

public:

    void Play(LPCTSTR lpUrl)

    {

        BSTR bstrUrl = SysAllocString(lpUrl);

        m_pWMPPlayer->put_URL(bstrUrl);

        SysFreeString(bstrUrl);

    }

};

 

int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,

                       _In_opt_ HINSTANCE hPrevInstance,

                       _In_ LPTSTR        lpCmdLine,

                       _In_ int           nCmdShow)

{

    WMPDialog dlg;

 

    if (!dlg.Create(400, 400))

    {

        return 0;

    }

 

    dlg.Play(_T("Sample.mid"));

    dlg.DoModal();

 

    return 0;

}

 

以上MediaPlayerSample4.rarhttp://pan.baidu.com/s/1EoZFK

 

clip_image002[4]

 

示例的MIDI是我早年蛋疼的时候做的哦,希望大家喜欢。

 

posted on 2012-09-04 22:16 溪流 阅读(2974) 评论(2)  编辑 收藏 引用 所属分类: C++WindowsCOM

评论:
# re: 写个含 Windows Media Player 的窗口 2012-12-21 12:39 | Lee Chen
您好,我的一个win32设计中用到了media player 控件,没有采用fmc或wtl。发现了您的这篇文章,我想参考一下,但代码下载不了,能否麻烦您发一份第一个示例的代码到我邮箱,在此多谢了。410711696@qq.com  回复  更多评论
  
# re: 写个含 Windows Media Player 的窗口 2012-12-23 14:01 | 溪流
@Lee Chen
已发。不过可否告知如何下载不了?  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理