проблемы с IVideoWindow
От: squid  
Дата: 15.07.07 04:59
Оценка:
пишу ActiveX control (MFC C++) для проигрывания видео. сразу столкнулся с проблемой...

для отображения я использую фильтр Video Renderer и Panel для отображения (демка на C#).
если кликнуть на этой панели во время проигрывания основное окно становиться неактивным а панелька для отображения (или сам контрол если отображать на нем) — активными. как это побороть?

вот код установки параметром IVideoWindow

FullScreen = false
OwnerHWND — панелька
AppHWND — основное окно

void ChangeVideoMode(bool FullScreen, OAHWND OwnerHWND, OAHWND AppHWND, int Width, int Height, IVideoWindow * pVideoWindow, IGraphBuilder * pGraphBuilder)
{
    try
    {
        long StyleEX;
        long OldStyle, OldStyleEx;
        HDC DC;
        IBasicVideo2 * pBasicVideo = NULL;

        long VideoScreenWidth, VideoScreenHeight, ClipWidth, ClipHeight, NewImageWidth, NewImageHeight, NewImageLeft, NewImageTop;

        if((pVideoWindow != NULL) &&  (pGraphBuilder != NULL))
            if(FullScreen)
            { 
                pVideoWindow->put_Owner(0);

                pVideoWindow->get_WindowStyle(&OldStyle);
                pVideoWindow->put_WindowStyle(OldStyle && !(WS_BORDER || WS_CAPTION || WS_THICKFRAME));
                pVideoWindow->get_WindowStyleEx(&OldStyleEx);

                StyleEX =  OldStyleEx && !(WS_EX_CLIENTEDGE || WS_EX_STATICEDGE || WS_EX_WINDOWEDGE || WS_EX_DLGMODALFRAME);
                pVideoWindow->put_WindowStyleEx(StyleEX);

                DC =  CreateDC(L"DISPLAY", NULL, NULL, NULL);
                Width = GetDeviceCaps(DC, HORZRES);
                Height = GetDeviceCaps(DC, VERTRES);
                DeleteDC(DC);
            } 
            else
            { 
                pVideoWindow->put_MessageDrain(AppHWND);
                
                pVideoWindow->put_Owner(OwnerHWND);
                pVideoWindow->put_Visible(OATRUE);

                pVideoWindow->put_WindowStyle(WS_CHILD || WS_CLIPSIBLINGS);
            } 

            VideoScreenWidth =  Width;
            VideoScreenHeight =  Height;

            
            if((pGraphBuilder->QueryInterface(IID_IBasicVideo2, (void**)&pBasicVideo) == S_OK))
            {
                pBasicVideo->get_VideoWidth(&ClipWidth);
                pBasicVideo->get_VideoHeight(&ClipHeight);

                if((VideoScreenWidth > 0) &&  (VideoScreenHeight > 0)   )
                { 
                    if((ClipWidth / ClipHeight) > (VideoScreenWidth / VideoScreenHeight)   )
                    { 
                        NewImageWidth =  VideoScreenWidth;
                        NewImageHeight =  (long)VF_Round((float)ClipHeight / (float)ClipWidth * (float)VideoScreenWidth);
                    }  
                    else
                    { 
                        NewImageWidth =  (long)VF_Round((float)ClipWidth / (float)ClipHeight * (float)VideoScreenHeight);
                        NewImageHeight =  VideoScreenHeight;
                    } 
                } 

                NewImageLeft = (VideoScreenWidth / 2) - (NewImageWidth / 2);
                NewImageTop = (VideoScreenHeight / 2) - (NewImageHeight / 2);

                pVideoWindow->put_Left(NewImageLeft);
                pVideoWindow->put_Top(NewImageTop);
                pVideoWindow->put_Width(NewImageWidth);
                pVideoWindow->put_Width(NewImageHeight);

                pVideoWindow->SetWindowPosition(NewImageLeft, NewImageTop, NewImageWidth, NewImageHeight);
            };

            //pVideoWindow->SetWindowForeground(OAFALSE);

            SAFE_RELEASE(pBasicVideo);
            
    }
    catch(...)
    {

    }
}


вторая проблема — сделал pVideoWindow->put_MessageDrain(AppHWND) но тоже не работает (сообщения не приходят)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: проблемы с IVideoWindow
От: Аноним  
Дата: 15.07.07 09:56
Оценка:
Здравствуйте, squid, Вы писали:

S>вторая проблема — сделал pVideoWindow->put_MessageDrain(AppHWND) но тоже не работает (сообщения не приходят)


Я у себя эту траблу решил так:
// доступ к окну видео
pVideoHWnd = pDSUtilFunc.GetHwndVideoWindow(piGraphBuilder);
if(pVideoHWnd != NULL)
{ // устанавливаем свою оконную процедуру
oldprocVideoWnd = (WNDPROC) SetWindowLong(pVideoHWnd, GWL_WNDPROC, (LONG) SubclassVideoWndProc);
}
т.е. идея такова — получаю доступ к видео-окну, затем устанавливаю для него свою оконную процедуру.

Кстати, проблема с получением оконных сообщений возникает только при работе с обычными видео-файлами, а вот при построении графа для воспр. DVD-видео с исп. DVD-навигатора такой проблемы почему-то нет, т.е. сообщения от видео-окна отлавливаются в WindowProc к примеру.
Че за фигня, кто знает ?
Re[2]: проблемы с IVideoWindow
От: squid  
Дата: 17.07.07 05:29
Оценка:
Здравствуйте, <Аноним>, Вы писали:


S>>вторая проблема — сделал pVideoWindow->put_MessageDrain(AppHWND) но тоже не работает (сообщения не приходят)


А>Я у себя эту траблу решил так:

А>// доступ к окну видео
А>pVideoHWnd = pDSUtilFunc.GetHwndVideoWindow(piGraphBuilder);
А>if(pVideoHWnd != NULL)
А>{ // устанавливаем свою оконную процедуру
А> oldprocVideoWnd = (WNDPROC) SetWindowLong(pVideoHWnd, GWL_WNDPROC, (LONG) SubclassVideoWndProc);
А>}
А>т.е. идея такова — получаю доступ к видео-окну, затем устанавливаю для него свою оконную процедуру.

спасибо но я не понял как вы хэндл окна получили...

pVideoHWnd = pDSUtilFunc.GetHwndVideoWindow(piGraphBuilder);


это вообще что?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: проблемы с IVideoWindow
От: squid  
Дата: 18.07.07 05:51
Оценка:
Здравствуйте, squid, Вы писали:

S>пишу ActiveX control (MFC C++) для проигрывания видео. сразу столкнулся с проблемой...


S>для отображения я использую фильтр Video Renderer и Panel для отображения (демка на C#).

S>если кликнуть на этой панели во время проигрывания основное окно становиться неактивным а панелька для отображения (или сам контрол если отображать на нем) — активными. как это побороть?

проблема решена.

просто заменил

pVideoWindow->put_WindowStyle(WS_CHILD || WS_CLIPSIBLINGS);


на

pVideoWindow->put_WindowStyle(WS_CHILD);


S>вторая проблема — сделал pVideoWindow->put_MessageDrain(AppHWND) но тоже не работает (сообщения не приходят)


а тут по прежднему глухо
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: проблемы с IVideoWindow
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 18.07.07 09:30
Оценка:
А какие сообщения не приходят? Там не все пересылаются.
Re[3]: проблемы с IVideoWindow
От: squid  
Дата: 19.07.07 06:10
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>А какие сообщения не приходят? Там не все пересылаются.


да любые вроде. хоть нашатие клавишъ хоть мыша.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: проблемы с IVideoWindow
От: Аноним  
Дата: 20.07.07 03:09
Оценка:
Здравствуйте, squid, Вы писали:

S>спасибо но я не понял как вы хэндл окна получили...


S>
S>pVideoHWnd = pDSUtilFunc.GetHwndVideoWindow(piGraphBuilder); 
S>


S>это вообще что?


pDSUtilFunc — это указатель на вспомогательный класс, в котором есть метод GetHwndVideoWindow. Вот реализация:

HWND CDSUtilFunc::GetHwndVideoWindow(IGraphBuilder *pGB)
{
HWND hwndReturn = NULL;
HRESULT hr;

// подключаем интерфейс IOverlay
IBaseFilter *pRenderFilter = NULL;
IPin *pRenderPin = NULL;
IOverlay* pOverlay = NULL;
IOverlayNotify* pOverlayNotify = NULL;

if(FindRenderer(pGB, &MEDIATYPE_Video, &pRenderFilter) == S_OK)
{ // получаем входной пин
if(GetPin(pRenderFilter, PINDIR_INPUT, MEDIASUBTYPE_None, &pRenderPin) == S_OK)
{
if(pRenderPin->QueryInterface(IID_IOverlay, (void **)&pOverlay) == S_OK)
{
pOverlay->Release();
pRenderPin->Release();
pRenderPin = NULL;

// получаем хендл окна
hr = pOverlay->GetWindowHandle(&hwndReturn);
if(hr != S_OK)
ShowErrorMessage(hr);
}
}

if(pRenderFilter != NULL)
{
if(pRenderFilter)
pRenderFilter->Release();
}
}

return hwndReturn;
}

здесь используется еще один метод этого вспомогательного класса — GetPin. Даю сразу и его реализацию:

HRESULT CDSUtilFunc::GetPin(IBaseFilter *pFilter, PIN_DIRECTION dirRequired, GUID majortype, IPin **ppPin)
{
HRESULT hr = S_FALSE;

IEnumPins* pEnum;
*ppPin = NULL;

if(!pFilter)
return E_POINTER;

hr = pFilter->EnumPins(&pEnum);
if(hr != S_OK)
return hr;

ULONG ulFound;
IPin* pPin;
hr = E_FAIL;

while(pEnum->Next(1, &pPin, &ulFound) == S_OK)
{
PIN_DIRECTION pindir = (PIN_DIRECTION)3;

pPin->QueryDirection(&pindir);

if(pindir == dirRequired)
{ // если указан — проверяем тип данных пина
if(majortype != MEDIASUBTYPE_None)
{
// получаем медиа-тип исходного сигнала
AM_MEDIA_TYPE *pMediaType;
IEnumMediaTypes *pEnumType;

if(pPin->EnumMediaTypes(&pEnumType) == S_OK)
{
ULONG ulFoundTypes;
while(pEnumType->Next(1, &pMediaType, &ulFoundTypes) == S_OK)
{
if(pMediaType->majortype == majortype)//MEDIATYPE_Audio
{
*ppPin = pPin;
hr = S_OK;
break;
}
// очищаем структуру
DeleteMediaType(pMediaType);
}
}
pEnumType->Release();
}
else
{
*ppPin = pPin;
hr = S_OK;
break;
}
}
pPin->Release();
}
pEnum->Release();

return hr;
}
Re[4]: проблемы с IVideoWindow
От: squid  
Дата: 20.07.07 05:01
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, squid, Вы писали:


S>>спасибо но я не понял как вы хэндл окна получили...


S>>
S>>pVideoHWnd = pDSUtilFunc.GetHwndVideoWindow(piGraphBuilder); 
S>>


S>>это вообще что?


А>pDSUtilFunc — это указатель на вспомогательный класс, в котором есть метод GetHwndVideoWindow. Вот реализация:


большое спасибо буду разбираться
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: look in winctrl.cpp
От: chygyrynsky Германия  
Дата: 20.07.07 08:41
Оценка:
// This checks to see whether the window has a drain. An application can in
// most environments set the owner/parent of windows so that they appear in
// a compound document context (for example). In this case, the application
// would probably like to be told of any keyboard/mouse messages. Therefore
// we pass these messages on untranslated, returning TRUE if we're successful

BOOL WINAPI PossiblyEatMessage(HWND hwndDrain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (hwndDrain != NULL && !InSendMessage())
    {
        switch (uMsg)
        {
            case WM_CHAR:
            case WM_DEADCHAR:
            case WM_KEYDOWN:
            case WM_KEYUP:
            case WM_LBUTTONDBLCLK:
            case WM_LBUTTONDOWN:
            case WM_LBUTTONUP:
            case WM_MBUTTONDBLCLK:
            case WM_MBUTTONDOWN:
            case WM_MBUTTONUP:
            case WM_MOUSEACTIVATE:
            case WM_MOUSEMOVE:
            // If we pass this on we don't get any mouse clicks
            //case WM_NCHITTEST:
            case WM_NCLBUTTONDBLCLK:
            case WM_NCLBUTTONDOWN:
            case WM_NCLBUTTONUP:
            case WM_NCMBUTTONDBLCLK:
            case WM_NCMBUTTONDOWN:
            case WM_NCMBUTTONUP:
            case WM_NCMOUSEMOVE:
            case WM_NCRBUTTONDBLCLK:
            case WM_NCRBUTTONDOWN:
            case WM_NCRBUTTONUP:
            case WM_RBUTTONDBLCLK:
            case WM_RBUTTONDOWN:
            case WM_RBUTTONUP:
            case WM_SYSCHAR:
            case WM_SYSDEADCHAR:
            case WM_SYSKEYDOWN:
            case WM_SYSKEYUP:

                DbgLog((LOG_TRACE, 2, TEXT("Forwarding %x to drain")));
                PostMessage(hwndDrain, uMsg, wParam, lParam);

                return TRUE;
        }
    }
    return FALSE;
}
Re[2]: проблемы с IVideoWindow
От: demm45  
Дата: 10.06.08 09:20
Оценка:
Решется проще чем тут писали.

У меня IVideoWindow клент пнели которая лежит на главном окне. Естественно возникло желание таскать окно программы за любую точку.
В итоге в процедре главного окна:
case uMsg of
..........
WM_NCHITTEST: Result:=HTCAPTION;
..........
else
Result:=DefWindowProc(hwnd,uMsg,wParam,lParam);
end;

В процедуре панели на которой лужит IVideoWindow
case uMsg of
WM_NCHITTEST: Result:=HTTRANSPARENT;
..................
WM_MOUSEFIRST..WM_MOUSELAST:
begin
Cp:=Point($FFFF and LPARAM,LPARAM shr 16);
ClientToScreen(hFrameWnd,Cp);
with Cp do
PostMessage(hMainWnd,(uMsg and $F) or $A0,HTCAPTION,MakeLParam(X,Y)); ///hMainWnd — хэндл главного окна
Result:=0;
end;
.....................
else
Result:=DefWindowProc(hwnd,uMsg,wParam,lParam);
end;

Ну и само собой, при настройке вдеоокна:
FVideoWindow.put_Owner(hPanelWnd);
FVideoWindow.put_MessageDrain(hPanelWnd);

И все работает. Сообщения мышки насквозь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.