WIN32不得不会:视频播放器
我愿分享我所有的技术,你可愿意做我的朋友?
----赵大哥
为何要写这篇博客
纯WIN32API打造,自认为对底层的理解略有帮助,和大家分享成果和知识点。
已经实现功能有:打开、播放、关闭功能。
核心功能讲解:
1.WIN32打开文件对话框
BOOL OpenFileDlg(HWND hWnd, TCHAR* szFileSelect)
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
//需要兼容UNICODE处理
ZeroMemory(szFileSelect, sizeof(TCHAR)*MAX_PATH_LEN);
ofn.Flags = OFN_EXPLORER;
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFileSelect;
ofn.lpstrFile[0] = '\0';
ofn.lpstrFileTitle = szFileFilter;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.nMaxFile = MAX_PATH_LEN;
ofn.nMaxFileTitle = MAX_PATH_LEN;
if(GetOpenFileName(&ofn))
{
//与网上给出的方法不同,实践中只要打开OK,文件路径就保存在ofn.lpstrFile参数中
return TRUE;
}
return FALSE;
}
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
//需要兼容UNICODE处理
ZeroMemory(szFileSelect, sizeof(TCHAR)*MAX_PATH_LEN);
ofn.Flags = OFN_EXPLORER;
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFileSelect;
ofn.lpstrFile[0] = '\0';
ofn.lpstrFileTitle = szFileFilter;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.nMaxFile = MAX_PATH_LEN;
ofn.nMaxFileTitle = MAX_PATH_LEN;
if(GetOpenFileName(&ofn))
{
//与网上给出的方法不同,实践中只要打开OK,文件路径就保存在ofn.lpstrFile参数中
return TRUE;
}
return FALSE;
}
需要注意的是lpstrFile[0]必须设置为'\0'才能弹出对话框。
2.MCI系列API使用
打开视频并预览一下
void OpenVideoFile(HWND hWnd)
{
TCHAR szFileSelect[MAX_PATH_LEN];
if(OpenFileDlg(hWnd, szFileSelect))
{
MCI_DGV_OPEN_PARMS MciOpenParams;
ZeroMemory(&MciOpenParams, sizeof(MciOpenParams));
MciOpenParams.dwCallback = (DWORD)hWnd;
//指定dwStyle为WS_CHILD和mciSendCommand中的MCI_DGV_OPEN_PARENT | MCI_DGV_OPEN_WS,新打开的视频窗口为主窗口的子窗口
MciOpenParams.dwStyle = WS_CHILD;
MciOpenParams.hWndParent = hWnd;
MciOpenParams.lpstrElementName = szFileSelect;
mciSendCommand(MciOpenParams.wDeviceID, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_DGV_OPEN_PARENT | MCI_DGV_OPEN_WS, (DWORD)&MciOpenParams);
g_MciDevId = MciOpenParams.wDeviceID;
//指定MCI_DGV_STATUS_HWND参数以获取视频子窗口的句柄
MCI_DGV_STATUS_PARMS MciStatusParams;
MciStatusParams.dwItem = MCI_DGV_STATUS_HWND;
mciSendCommand(MciOpenParams.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&MciStatusParams);
hVideo = (HWND)MciStatusParams.dwReturn;
//根据主窗体的大小调节视频窗口的大小
GetClientRect(hWnd, &ClientRect);
MoveWindow(hVideo, 5, 5, ClientRect.right - ClientRect.left - 10, ClientRect.bottom - ClientRect.top - 10, TRUE);
//播放视频预览
MCI_DGV_PLAY_PARMS MciPlayParams;
MciPlayParams.dwCallback = (DWORD)PlayWndProc;
MciPlayParams.dwFrom = 0;
MciPlayParams.dwTo = 0;
mciSendCommand(MciOpenParams.wDeviceID, MCI_PLAY, MCI_FROM, (DWORD)&MciPlayParams);
mciSendCommand(MciOpenParams.wDeviceID, MCI_PAUSE, MCI_FROM, (DWORD)&MciPlayParams);
return;
}
return ;
}
{
TCHAR szFileSelect[MAX_PATH_LEN];
if(OpenFileDlg(hWnd, szFileSelect))
{
MCI_DGV_OPEN_PARMS MciOpenParams;
ZeroMemory(&MciOpenParams, sizeof(MciOpenParams));
MciOpenParams.dwCallback = (DWORD)hWnd;
//指定dwStyle为WS_CHILD和mciSendCommand中的MCI_DGV_OPEN_PARENT | MCI_DGV_OPEN_WS,新打开的视频窗口为主窗口的子窗口
MciOpenParams.dwStyle = WS_CHILD;
MciOpenParams.hWndParent = hWnd;
MciOpenParams.lpstrElementName = szFileSelect;
mciSendCommand(MciOpenParams.wDeviceID, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_DGV_OPEN_PARENT | MCI_DGV_OPEN_WS, (DWORD)&MciOpenParams);
g_MciDevId = MciOpenParams.wDeviceID;
//指定MCI_DGV_STATUS_HWND参数以获取视频子窗口的句柄
MCI_DGV_STATUS_PARMS MciStatusParams;
MciStatusParams.dwItem = MCI_DGV_STATUS_HWND;
mciSendCommand(MciOpenParams.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&MciStatusParams);
hVideo = (HWND)MciStatusParams.dwReturn;
//根据主窗体的大小调节视频窗口的大小
GetClientRect(hWnd, &ClientRect);
MoveWindow(hVideo, 5, 5, ClientRect.right - ClientRect.left - 10, ClientRect.bottom - ClientRect.top - 10, TRUE);
//播放视频预览
MCI_DGV_PLAY_PARMS MciPlayParams;
MciPlayParams.dwCallback = (DWORD)PlayWndProc;
MciPlayParams.dwFrom = 0;
MciPlayParams.dwTo = 0;
mciSendCommand(MciOpenParams.wDeviceID, MCI_PLAY, MCI_FROM, (DWORD)&MciPlayParams);
mciSendCommand(MciOpenParams.wDeviceID, MCI_PAUSE, MCI_FROM, (DWORD)&MciPlayParams);
return;
}
return ;
}
播放视频
void PlayVideoFile(int iDevID)
{
MCI_DGV_STATUS_PARMS MciStatusParams;
MciStatusParams.dwItem = MCI_STATUS_POSITION;
mciSendCommand(iDevID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&MciStatusParams);
MCI_DGV_PLAY_PARMS MciPlayParms;
MciPlayParms.dwCallback = NULL;
MciPlayParms.dwFrom = (DWORD)MciStatusParams.dwReturn;
MciPlayParms.dwTo = 0;
mciSendCommand(iDevID, MCI_PLAY, MCI_FROM,(DWORD)&MciPlayParms);
return;
{
MCI_DGV_STATUS_PARMS MciStatusParams;
MciStatusParams.dwItem = MCI_STATUS_POSITION;
mciSendCommand(iDevID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&MciStatusParams);
MCI_DGV_PLAY_PARMS MciPlayParms;
MciPlayParms.dwCallback = NULL;
MciPlayParms.dwFrom = (DWORD)MciStatusParams.dwReturn;
MciPlayParms.dwTo = 0;
mciSendCommand(iDevID, MCI_PLAY, MCI_FROM,(DWORD)&MciPlayParms);
return;
}
暂停视频
void PauseVideoFile(int iDevID)
{
MCI_DGV_PAUSE_PARMS MciPauseParams;
MciPauseParams.dwCallback = NULL;
mciSendCommand(iDevID, MCI_PAUSE, NULL, (DWORD)&MciPauseParams);
}
{
MCI_DGV_PAUSE_PARMS MciPauseParams;
MciPauseParams.dwCallback = NULL;
mciSendCommand(iDevID, MCI_PAUSE, NULL, (DWORD)&MciPauseParams);
}
3.系统菜单栏和下拉菜单栏的使用。
有横向菜单栏和下拉菜单两种用法,看官当心其中的区别咯
HMENU hSYSMenu;
hSYSMenu = CreateMenu();
HMENU hHELPMenu;
hHELPMenu = CreatePopupMenu();
AppendMenu(hHELPMenu, MF_STRING, IDM_SYSMENU_OPERATE, TEXT("操作指引"));
AppendMenu(hHELPMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hHELPMenu, MF_STRING, IDM_SYSMENU_ABOUT, TEXT("关于"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_OPEN, TEXT("打开"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_PLAY, TEXT("播放"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_STOP, TEXT("暂停"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_CLOSE, TEXT("关闭"));
AppendMenu(hSYSMenu, MF_STRING | MF_POPUP, (UINT_PTR)hHELPMenu, TEXT("帮助"));
SetMenu(hWnd, hSYSMenu);
hSYSMenu = CreateMenu();
HMENU hHELPMenu;
hHELPMenu = CreatePopupMenu();
AppendMenu(hHELPMenu, MF_STRING, IDM_SYSMENU_OPERATE, TEXT("操作指引"));
AppendMenu(hHELPMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hHELPMenu, MF_STRING, IDM_SYSMENU_ABOUT, TEXT("关于"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_OPEN, TEXT("打开"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_PLAY, TEXT("播放"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_STOP, TEXT("暂停"));
AppendMenu(hSYSMenu, MF_STRING, IDM_SYSMENU_CLOSE, TEXT("关闭"));
AppendMenu(hSYSMenu, MF_STRING | MF_POPUP, (UINT_PTR)hHELPMenu, TEXT("帮助"));
SetMenu(hWnd, hSYSMenu);
普通菜单用CreateMenu创建,SetMenu生效;下拉菜单用CreatePopupMenu创建,追加菜单项都是用AppendMenu实现,将下拉菜单追加到普通菜单条目下也是用AppendMenu来实现,属性中要指定MF_POPUP和要插入的菜单句柄。
小结
播放的框架算是完成了,可大可小的一个软件,时间允许的话会再增加一些实用功能。