[英]DirectShow - convert IGraphBuilder * to double (C++)
我正在使用DLL为GameMaker Studio创建扩展。 GameMaker Studio仅支持void,char *或double的函数返回类型。 至于参数,仅支持char *和double。 这意味着我必须将我需要的所有其他类型转换为这些类型之一。
问题是,我不确定是否要以最佳方式进行处理。 当试图通过标题栏拖动DirectShow所有者窗口时,会发生非常奇怪的行为。 嵌入式视频不会随父窗口移动; 它保持在相同的位置。
仅当窗口暂停或停止时这才是问题。 当前正在播放视频时,DirectShow窗口将与其父窗口一起移动。 但我希望用户能够暂停和停止视频,因此需要修复此问题。 这是我的DLL的代码:
#include <windows.h>
#include <DShow.h>
#define DLL extern "C" _declspec(dllexport)
using namespace std;
wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
DLL double video_init() {
if(FAILED(CoInitialize(NULL))){
MessageBox(NULL,L"Failed to initialize COM library.",L"ERROR", MB_ICONERROR | MB_OK);
return false;
}
return true;
}
DLL void video_uninit() {
CoUninitialize();
}
DLL double video_add(HWND window, char *fname) {
IGraphBuilder *pGraph = NULL;
HRESULT hr = S_OK;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);
if(FAILED(hr)) return NULL;
IVideoWindow *pVidWin = NULL;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
hr = pVidWin->put_Owner((OAHWND)window);
hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
pVidWin->Release();
IMediaControl *pControl = NULL;
hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
hr = pControl->Run();
hr = pControl->Pause();
pControl->Release();
return (double)(DWORD)(void *)pGraph;
}
DLL void video_start(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IMediaControl *pControl = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pControl->Run();
pControl->Release();
}
DLL void video_stop(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IMediaControl *pControl = NULL;
IMediaSeeking *pSeek = NULL;
REFERENCE_TIME stoptime = 0;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
OAFilterState fs;
hr = pControl->GetState(100,&fs);
switch(fs){
case State_Running:
hr = pControl->Pause();
case State_Paused:
pGraph->QueryInterface(IID_IMediaSeeking,(void**)&pSeek);
hr = pSeek->SetPositions(&stoptime,AM_SEEKING_AbsolutePositioning,0,AM_SEEKING_NoPositioning);
}
pControl->Release();
pSeek->Release();
}
DLL void video_pause(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IMediaControl *pControl = NULL;
HRESULT hr = S_OK;
pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
hr = pControl->Pause();
pControl->Release();
}
DLL void video_delete(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
pGraph->Release();
}
DLL void video_set_rectangle(double video,double x,double y,double w,double h) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IVideoWindow *pVidWin = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IVideoWindow,(void**)&pVidWin);
hr = pVidWin->SetWindowPosition((long)x, (long)y, (long)w, (long)h);
pVidWin->Release();
}
DLL double video_is_playing(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IMediaControl *pControl = NULL;
IMediaPosition *pPos = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
OAFilterState fs;
hr = pControl->GetState(100, &fs);
switch (fs){
case State_Running:
pGraph->QueryInterface(IID_IMediaPosition, (void**)&pPos);
REFTIME currentPos;
hr = pPos->get_CurrentPosition(¤tPos);
REFTIME duration;
hr = pPos->get_Duration(&duration);
if (currentPos < duration) {
return true;
}
else {
video_stop(video);
return false;
}
case State_Paused:
return false;
case State_Stopped:
return false;
}
pControl->Release();
pPos->Release();
return false;
}
DLL double video_is_cursor_hidden(double video) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IVideoWindow *pVidWin = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
long hidden;
hr = pVidWin->IsCursorHidden(&hidden);
if (hidden == OATRUE) {
return true;
} else {
return false;
}
pVidWin->Release();
}
DLL void video_hide_cursor(double video, double hide) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IVideoWindow *pVidWin = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (hide == (double)true) {
hr = pVidWin->HideCursor(OATRUE);
}
else {
hr = pVidWin->HideCursor(OAFALSE);
}
pVidWin->Release();
}
DLL void video_set_foreground(double video, double focus) {
IGraphBuilder *pGraph = (IGraphBuilder *)(DWORD)video;
IVideoWindow *pVidWin = NULL;
HRESULT hr = S_OK;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (focus == (double)true) {
hr = pVidWin->SetWindowForeground(OATRUE);
}
else {
hr = pVidWin->SetWindowForeground(OAFALSE);
}
pVidWin->Release();
}
DLL void video_update(HWND window) {
if (!(GetWindowLong(window, GWL_STYLE) & WS_CLIPCHILDREN)) {
SetWindowLong(window, GWL_STYLE,
GetWindowLong(window, GWL_STYLE) | WS_CLIPCHILDREN);
}
}
我会提供调用DLL以及所有其他内容的GameMaker Studio代码,但我严重怀疑我是否会在这里遇到GameMaker Studio用户。 这是我能做的最好的。 我不知道这是否是导致问题的原因,但是我一直在思考转换类型的方式,这就是为什么它表现得很时髦的原因。 要将IGraphBuilder *转换为双精度值作为返回值,我进行了如下转换:
return (double)(DWORD)(void *)pGraph;
我也尝试过:
return (double)(DWORD)pGraph;
两者都给了我上述相同的问题。
至于论点,我这样投:
(double)(DWORD)pGraph
我应该如何将IGraphBuilder *转换为double? 或者,这不是我的问题吗?
非常感谢所有建议,纠正和帮助。
塞缪尔
切勿将指针转换为(DWORD)
,如果将代码编译为64位,它将截断该指针! 如果需要,请使用指针大小的整数类型,例如SIZE_T,UINT_PTR或DWORD_PTR。
char*
是您可用的最好的类型,并保证与其他指针类型兼容。
double
是有问题的,因为它的大小可能与指针的大小不匹配,并且在64位Windows程序中的另一个CPU寄存器中传递它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.