视频定位控件数据可分为两部分:
可见部分:播放按钮、加载按钮、视频第一帧图片、视频时长
不可见部分:视频URL
以下为VideoOle控件头文件部分:
extern "C" const GUID IID_VideoOleCtrl;
class RichEditVideoOle :public RichEditOleBase
{
DECLARE_REOBJ(RichEditVideoOle, L"video")
public:
enum ReVideoState
{
REVIDEO_STATE_NORMAL,
REVIDEO_STATE_LOADING,
};
RichEditVideoOle();
~RichEditVideoOle();
BOOL InitOleWindow(IRichEditObjHost* pHost);
int GetVideoState(){return _state;}
SStringW GetVideoUrl(){return _video_url;}
SStringW GetVideoDuration(){return _video_duration;}
SStringW GetVideoId(){return GetId();}
void SetVideoPlayState(ReVideoState state);
protected:
void UpdatePosition();
bool OnBnClickPlay(SOUI::EventArgs* pEvt);
protected:
SOUI_ATTRS_BEGIN()
ATTR_STRINGW(L"video_duration", _video_duration, FALSE)
ATTR_STRINGW(L"video_url", _video_url, FALSE)
ATTR_STRINGW(L"video_cover_path", _video_cover_path, FALSE)
SOUI_ATTRS_END()
private:
int _state;
SStringW _video_duration; //视频时长
SStringW _video_url; //视频文件路径
SStringW _video_cover_path; //视频第一帧图片路径
};
以下为VideoOle控件的源文件部分代码:
//
// ------------------------------------------------------------------------------
// impl RichEditVideoOle
//
// {FAB32B7E-AC02-468c-A615-1E730243B62E}
static const GUID IID_VideoOleCtrl =
{ 0xfab32b7e, 0xac02, 0x468c, { 0xa6, 0x15, 0x1e, 0x73, 0x2, 0x43, 0xb6, 0x2e } };
RichEditVideoOle::RichEditVideoOle()
{
_oleGuid = IID_VideoOleCtrl;
_sizeNatural.cx = 300;
_sizeNatural.cy = 160;
_state = REVIDEO_STATE_NORMAL;
_canBeSelect = FALSE;
_xmlLayout = L"LAYOUT:VideoOleLayout";
}
RichEditVideoOle::~RichEditVideoOle()
{
}
BOOL RichEditVideoOle::InitOleWindow(IRichEditObjHost* pHost)
{
BOOL ret = RichEditOleBase::InitOleWindow(pHost);
SWindow* pVideoWnd = _oleView.FindChildByName2<SWindow>(L"video_frame");
if (pVideoWnd)
{
SImageWnd* pVideoCoverWnd = pVideoWnd->FindChildByName2<SImageWnd>(L"video_cover_img");
IBitmap* pFrameImg = SResLoadFromFile::LoadImage(_video_cover_path);
if (pVideoCoverWnd && pFrameImg)
{
pVideoCoverWnd->SetImage(pFrameImg);
UpdateWindowLayout(pVideoCoverWnd);
}
}
SImageView* pPlay = _oleView.FindChildByName2<SImageView>(L"play");
ISkinObj* pPlaySkin = GETSKIN(L"skin.richvideo_play", 100);
if (pPlay && pPlaySkin)
{
pPlay->SetSkin(pPlaySkin);
pPlay->SetVisible(TRUE, TRUE);
pPlay->Resume();
SUBSCRIBE(pPlay, EVT_CMD, RichEditVideoOle::OnBnClickPlay);
}
SImageView* pLoading = _oleView.FindChildByName2<SImageView>(L"loading");
ISkinObj* pLoadingSkin = GETSKIN(L"skin.richvideo_loading", 100);
if (pLoading && pLoadingSkin)
{
pLoading->SetSkin(pLoadingSkin);
pLoading->SetVisible(FALSE, TRUE);
pLoading->Resume();
}
SStatic* pVideoDuration = _oleView.FindChildByName2<SStatic>(L"video_duration");
if (pVideoDuration)
{
pVideoDuration->SetWindowText(L"00:30");
}
return ret;
}
bool RichEditVideoOle::OnBnClickPlay(SOUI::EventArgs* pEvt)
{
_state = REVIDEO_STATE_LOADING;
SWindow* pVideoWnd = _oleView.FindChildByName2<SWindow>(L"video_frame");
if (pVideoWnd)
{
SImageWnd* pVideoCoverWnd = pVideoWnd->FindChildByName2<SImageWnd>(L"video_cover_img");
IBitmap* pFrameImg = SResLoadFromFile::LoadImage(_video_cover_path);
if (pVideoCoverWnd && pFrameImg)
{
pVideoCoverWnd->SetImage(pFrameImg);
UpdateWindowLayout(pVideoCoverWnd);
}
}
SImageView* pPlay = _oleView.FindChildByName2<SImageView>(L"play");
ISkinObj* pPlaySkin = GETSKIN(L"skin.richvideo_play", 100);
if (pPlay && pPlaySkin)
{
pPlay->SetSkin(pPlaySkin);
pPlay->SetVisible(FALSE, TRUE);
pPlay->Resume();
}
SImageView* pLoading = _oleView.FindChildByName2<SImageView>(L"loading");
ISkinObj* pLoadingSkin = GETSKIN(L"skin.richvideo_loading", 100);
if (pLoading && pLoadingSkin)
{
pLoading->SetSkin(pLoadingSkin);
pLoading->SetVisible(TRUE, TRUE);
pLoading->Resume();
}
SStatic* pVideoDuration = _oleView.FindChildByName2<SStatic>(L"video_duration");
if (pVideoDuration)
{
pVideoDuration->SetWindowText(L"00:30");
}
_pObjHost->NotifyRichObjEvent(this, CLICK_VIDEOPLAY, 0, 0);
return true;
}
void RichEditVideoOle::SetVideoPlayState(ReVideoState state)
{
_state = state;
if (REVIDEO_STATE_NORMAL == state)
{
SWindow* pVideoWnd = _oleView.FindChildByName2<SWindow>(L"video_frame");
if (pVideoWnd)
{
SImageWnd* pVideoCoverWnd = pVideoWnd->FindChildByName2<SImageWnd>(L"video_cover_img");
IBitmap* pFrameImg = SResLoadFromFile::LoadImage(_video_cover_path);
if (pVideoCoverWnd && pFrameImg)
{
pVideoCoverWnd->SetImage(pFrameImg);
UpdateWindowLayout(pVideoCoverWnd);
}
}
SImageView* pPlay = _oleView.FindChildByName2<SImageView>(L"play");
ISkinObj* pPlaySkin = GETSKIN(L"skin.richvideo_play", 100);
if (pPlay && pPlaySkin)
{
pPlay->SetSkin(pPlaySkin);
pPlay->SetVisible(TRUE, TRUE);
pPlay->Resume();
}
SImageView* pLoading = _oleView.FindChildByName2<SImageView>(L"loading");
ISkinObj* pLoadingSkin = GETSKIN(L"skin.richvideo_loading", 100);
if (pLoading && pLoadingSkin)
{
pLoading->SetSkin(pLoadingSkin);
pLoading->SetVisible(FALSE, TRUE);
pLoading->Resume();
}
SStatic* pVideoDuration = _oleView.FindChildByName2<SStatic>(L"video_duration");
if (pVideoDuration)
{
pVideoDuration->SetWindowText(L"00:30");
}
}
}
void RichEditVideoOle::UpdatePosition()
{
if (_spAdviseSink)
{
_oleView.SetOleWindowRect(CRect(0, 0, 0, 0)); // 已经失效
_oleView.Move(0, 0, _sizeNatural.cx, _sizeNatural.cy);
CalculateExtentSize(_sizeNatural);
_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
}
}
IID_VideoOleCtrl为控件GUID,可以自己生成。
接口说明:
InitOleWindow:初始化Ole窗口
GetVideoState:获取视频状态
GetVideoUrl:获取视频URL
GetVideoId:获取元素ID
GetVideoDuration:获取视频时长
OnBnClickPlay:播放按钮点击事件
void SetVideoPlayState:设置视频状态,主要是在下载完成后设置控件状态时使用
以下是布局相关xml:
<root>
<window pos="0,0,-0,-0" skin="skin.empty">
<window name="video_frame" pos="0,0,-0,-0">
<img name="video_cover_img" pos="0,0,-0,-0" />
</window>
<image name="play" pos="130,60,-130,-60" cursor="hand" />
<image name="loading" pos="130,60,-130,-60" />
<window name="durationWnd" pos="0,-20,-0,-0" skin="skin.richvideo_timebg">
<text name="video_duration" pos="-40,3,@40,@13" align="center" colorText="#FFFFFF" font="size:12" />
</window>
</window>
</root>
控件需要在uires.idx文件中添加相关映射关系
注意事项跟《拓展SOUI中SImRichEdit控件的语音OLE控件(AudioOle)》中一样;
以下为使用示例代码:
SStringW strVideo;
std::string strVideoId = KfUtility::GenerateUUID();
std::wstring wstrVideoId;
KfUtility::ConvertUtf8ToUtf16(strVideoId, wstrVideoId);
strVideo.Format(L"<video id=\"%s\" video_duration=\"120\" video_url=\"\" video_cover_path=\"D:\\imrepose\\trunk\\KFClient6\\output\\Debug_Unicode\\default_res\\location.jpg\" />", wstrAudioId.c_str());
SStringW strContentVideo;
strContentVideo.Format(
L"<RichEditContent type=\"ContentRight\" align=\"right\" auto-layout=\"1\">"
L"<para break=\"1\" align=\"left\" />"
L"<bkele data=\"avatar\" id=\"%s\" skin=\"%s\" left-pos=\"0,]-6,@40,@40\" right-pos=\"-50,]-10,@40,@40\" cursor=\"hand\" interactive=\"1\"/>"
L"<para id=\"msgbody\" margin=\"65,0,45,0\" break=\"1\" simulate-align=\"1\">"
L"%s"
L"</para>"
L"<bkele data=\"bubble\" left-skin=\"skin_left_bubble\" right-skin=\"skin_right_otherbubble\" left-pos=\"50,{-9,[10,[10\" right-pos=\"{-10,{-9,-55,[10\" />"
L"%s"
L"</RichEditContent>",
wstrId.c_str(), wstrFaceId.c_str(), strVideo, pEmpty);
pRecvRichEdit->InsertContent(strContentVideo, RECONTENT_LAST);
控件效果图如下: