/*************************************************************************/ /* Copyright (C) 1999 Microsoft Corporation */ /* File: msdvd.cpp */ /* Description: Implementation of CMSWebDVD. */ /* Author: David Janecek */ /*************************************************************************/ #include "stdafx.h" #include "MSDVD.h" #include "ddrawobj.h" #define COMPILE_MULTIMON_STUBS #define HMONITOR_DECLARED // to cover up DDraw Monitor redefinition #include extern GUID IID_IDDrawNonExclModeVideo = { 0xec70205c,0x45a3,0x4400,{0xa3,0x65,0xc4,0x47,0x65,0x78,0x45,0xc7}}; /*****************************Private*Routine******************************\ * UpdateCurrentMonitor * * Updates the "m_lpCurMonitor" global to match the specified DDraw GUID * * History: * Wed 11/17/1999 - StEstrop - Created * \**************************************************************************/ HRESULT CMSWebDVD::UpdateCurrentMonitor( const AMDDRAWGUID* lpguid ) { if (lpguid->lpGUID) { for (AMDDRAWMONITORINFO* lpCurMonitor = &m_lpInfo[0]; lpCurMonitor < &m_lpInfo[m_dwNumDevices]; lpCurMonitor++) { if (lpCurMonitor->guid.lpGUID && *lpCurMonitor->guid.lpGUID == *lpguid->lpGUID) { m_lpCurMonitor = lpCurMonitor; return S_OK; } } } else { for (AMDDRAWMONITORINFO* lpCurMonitor = &m_lpInfo[0]; lpCurMonitor < &m_lpInfo[m_dwNumDevices]; lpCurMonitor++) { if (lpguid->lpGUID == lpCurMonitor->guid.lpGUID) { m_lpCurMonitor = lpCurMonitor; return S_OK; } } } return E_FAIL; } /******************************Public*Routine******************************\ * DisplayChange * * * * History: * Sat 11/27/1999 - StEstrop - Created * \**************************************************************************/ HRESULT CMSWebDVD::DisplayChange( HMONITOR hMon, const AMDDRAWGUID* lpguid ) { HRESULT hr = E_FAIL; if(!m_pDvdGB){ return(E_FAIL); }/* end of if statement */ CDDrawDVD* pDDrawObj = new CDDrawDVD(this); if(NULL == pDDrawObj){ return (E_OUTOFMEMORY); }/* end if statement */ HWND hwnd; hr = GetUsableWindow(&hwnd); if(FAILED(hr)){ delete pDDrawObj; return(hr); }/* end of if statement */ hr = pDDrawObj->SetupDDraw(lpguid, hwnd); if (FAILED(hr)) { delete pDDrawObj; return hr; } IDDrawNonExclModeVideo* pDDXMV; hr = m_pDvdGB->GetDvdInterface(IID_IDDrawNonExclModeVideo, (LPVOID *)&pDDXMV) ; if (FAILED(hr)) { delete pDDrawObj; return hr; } LPDIRECTDRAW pDDObj = pDDrawObj->GetDDrawObj(); LPDIRECTDRAWSURFACE pDDPrimary = pDDrawObj->GetDDrawSurf(); hr = pDDXMV->SetCallbackInterface(NULL, 0) ; if (FAILED(hr)){ pDDXMV->Release() ; // release before returning return hr; }/* end of if statement */ hr = pDDXMV->DisplayModeChanged(hMon, pDDObj, pDDPrimary); if (SUCCEEDED(hr)) { delete m_pDDrawDVD; m_pDDrawDVD = pDDrawObj; hr = UpdateCurrentMonitor(lpguid); } else { delete pDDrawObj; } hr = pDDXMV->SetCallbackInterface(m_pDDrawDVD->GetCallbackInterface(), 0) ; if (SUCCEEDED(hr)) { hr = SetColorKey(DEFAULT_COLOR_KEY); }/* end of it statement */ pDDXMV->Release(); return hr; } /******************************Public*Routine******************************\ * ChangeMonitor * * Tells the OVMixer that we want to change to another monitor. * * History: * Wed 11/17/1999 - StEstrop - Created * \**************************************************************************/ HRESULT CMSWebDVD::ChangeMonitor( HMONITOR hMon, const AMDDRAWGUID* lpguid ) { HRESULT hr = E_FAIL; if(!m_pDvdGB){ return(E_FAIL); }/* end of if statement */ CDDrawDVD* pDDrawObj = new CDDrawDVD(this); if(NULL == pDDrawObj){ return (E_OUTOFMEMORY); }/* end if statement */ HWND hwnd; hr = GetUsableWindow(&hwnd); if(FAILED(hr)){ delete pDDrawObj; return(hr); }/* end of if statement */ hr = pDDrawObj->SetupDDraw(lpguid, hwnd); if (FAILED(hr)) { delete pDDrawObj; return hr; } IDDrawNonExclModeVideo* pDDXMV; hr = m_pDvdGB->GetDvdInterface(IID_IDDrawNonExclModeVideo, (LPVOID *)&pDDXMV) ; if (FAILED(hr)) { delete pDDrawObj; return hr; } LPDIRECTDRAW pDDObj = pDDrawObj->GetDDrawObj(); LPDIRECTDRAWSURFACE pDDPrimary = pDDrawObj->GetDDrawSurf(); hr = pDDXMV->SetCallbackInterface(NULL, 0) ; if (FAILED(hr)){ pDDXMV->Release() ; // release before returning return hr; }/* end of if statement */ hr = pDDXMV->ChangeMonitor(hMon, pDDObj, pDDPrimary); if (SUCCEEDED(hr)) { delete m_pDDrawDVD; m_pDDrawDVD = pDDrawObj; hr = UpdateCurrentMonitor(lpguid); } else { delete pDDrawObj; } hr = pDDXMV->SetCallbackInterface(m_pDDrawDVD->GetCallbackInterface(), 0) ; if (SUCCEEDED(hr)) { hr = SetColorKey(DEFAULT_COLOR_KEY); }/* end of it statement */ pDDXMV->Release(); return hr; } /******************************Public*Routine******************************\ * RestoreSurfaces * * Tells the OVMixer to restore its internal DDraw surfaces * * History: * Wed 11/17/1999 - StEstrop - Created * \**************************************************************************/ HRESULT CMSWebDVD::RestoreSurfaces() { if(!m_pDvdGB){ return(E_FAIL); }/* end of if statement */ IDDrawNonExclModeVideo* pDDXMV; HRESULT hr = m_pDvdGB->GetDvdInterface(IID_IDDrawNonExclModeVideo, (LPVOID *)&pDDXMV) ; if (FAILED(hr)) { return hr; } hr = pDDXMV->RestoreSurfaces(); pDDXMV->Release(); return hr; } /*************************************************************************/ /* Function: RefreshDDrawGuids */ /*************************************************************************/ HRESULT CMSWebDVD::RefreshDDrawGuids() { IDDrawNonExclModeVideo* pDDXMV; if(!m_pDvdGB){ return(E_FAIL); }/* end of if statement */ HRESULT hr = m_pDvdGB->GetDvdInterface(IID_IDDrawNonExclModeVideo, (LPVOID *)&pDDXMV) ; if (FAILED(hr)) { return hr; } GUID IID_IAMSpecifyDDrawConnectionDevice = { 0xc5265dba,0x3de3,0x4919,{0x94,0x0b,0x5a,0xc6,0x61,0xc8,0x2e,0xf4}}; IAMSpecifyDDrawConnectionDevice* pSDDC; hr = pDDXMV->QueryInterface(IID_IAMSpecifyDDrawConnectionDevice, (LPVOID *)&pSDDC); if (FAILED(hr)) { pDDXMV->Release(); return hr; } DWORD dwNumDevices; AMDDRAWMONITORINFO* lpInfo; hr = pSDDC->GetDDrawGUIDs(&dwNumDevices, &lpInfo); if (SUCCEEDED(hr)) { CoTaskMemFree(m_lpInfo); m_lpCurMonitor = NULL; m_lpInfo = lpInfo; m_dwNumDevices = dwNumDevices; } pSDDC->Release(); pDDXMV->Release(); return hr; }/* end of function RefreshDDrawGuids */ /*****************************Private*Routine******************************\ * IsWindowOnWrongMonitor * * Use the same algorithm that the OVMixer uses to determine if we are on * the wrong monitor or not. * * If we are on the wrong monitor *lphMon contains the monitor handle of the * new monitor to use. * * History: * Wed 11/17/1999 - StEstrop - Created * \**************************************************************************/ bool CMSWebDVD::IsWindowOnWrongMonitor( HMONITOR* lphMon) { if (!m_lpCurMonitor) { return false; } HWND hwnd; HRESULT hr = GetUsableWindow(&hwnd); if(FAILED(hr)){ return(false); }/* end of if statement */ RECT rc; hr = GetClientRectInScreen(&rc); if(FAILED(hr)){ return(false); }/* end of if statement */ *lphMon = m_lpCurMonitor->hMon; if (GetSystemMetrics(SM_CMONITORS) > 1 && !::IsIconic(hwnd)) { LPRECT lprcMonitor = &m_lpCurMonitor->rcMonitor; if (rc.left < lprcMonitor->left || rc.right > lprcMonitor->right || rc.top < lprcMonitor->top || rc.bottom > lprcMonitor->bottom) { HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); if (*lphMon != hMon) { *lphMon = hMon; return true; } } } return false; } /*****************************Private*Routine******************************\ * DDrawGuidFromHMonitor * * Return the DDraw guid from the specified hMonitor handle. * * History: * Wed 11/17/1999 - StEstrop - Created * \**************************************************************************/ HRESULT CMSWebDVD::DDrawGuidFromHMonitor( HMONITOR hMon, AMDDRAWGUID* lpGUID ) { AMDDRAWMONITORINFO* lpCurMonitor = &m_lpInfo[0]; #if 1 if (m_dwNumDevices == 1) { *lpGUID = lpCurMonitor->guid; return S_OK; } #endif for (; lpCurMonitor < &m_lpInfo[m_dwNumDevices]; lpCurMonitor++) { if (lpCurMonitor->hMon == hMon) { *lpGUID = lpCurMonitor->guid; return S_OK; } } return E_FAIL; } struct MONITORDATA { HMONITOR hMonPB; BOOL fMsgShouldBeDrawn; }; /*****************************Private*Routine******************************\ * MonitorEnumProc * * On Multi-Monitor systems make sure that the part of the window that is not * on the primary monitor is black. * * History: * Thu 06/03/1999 - StEstrop - Created * \**************************************************************************/ BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, // handle to display monitor HDC hdc, // handle to monitor-appropriate device context LPRECT lprcMonitor, // pointer to monitor intersection rectangle LPARAM dwData // data passed from EnumDisplayMonitors ) { MONITORDATA* lpmd = (MONITORDATA*)dwData; //COLORREF clrOld = GetBkColor(hdc); if (lpmd->hMonPB != hMonitor) { //SetBkColor(hdc, RGB(0,0,0)); lpmd->fMsgShouldBeDrawn = TRUE; } else { // put your own color key here ;//SetBkColor(hdc, RGB(255,0,255)); } //ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lprcMonitor, NULL, 0, NULL); //SetBkColor(hdc, clrOld); return TRUE; } /*************************************************************************/ /* Function: OnDispChange */ /*************************************************************************/ LRESULT CMSWebDVD::OnDispChange(UINT /* uMsg */, WPARAM wParam, LPARAM lParam, BOOL& bHandled){ if(::IsWindow(m_hWnd)){ bHandled = FALSE; return(0); //do not handle this in windowed mode }/* end of if statement */ RECT rc; HRESULT hr = GetClientRectInScreen(&rc); if(FAILED(hr)){ return(-1); }/* end of if statement */ HMONITOR hMon = ::MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); AMDDRAWGUID guid; hr = RefreshDDrawGuids(); if(FAILED(hr)){ return -1; }/* end of if statement */ hr = DDrawGuidFromHMonitor(hMon, &guid); if(FAILED(hr)){ return -1; }/* end of if statement */ hr = DisplayChange(hMon, &guid); if(FAILED(hr)){ return -1; }/* end of if statement */ return 0; }/* end of function OnDispChange */ /*************************************************************************/ /* Function: HandleMultiMonMove */ /* Description: Moves the playback to another monitor when needed. */ /*************************************************************************/ HRESULT CMSWebDVD::HandleMultiMonMove(){ HRESULT hr = S_FALSE; if (::GetSystemMetrics(SM_CMONITORS) > 1){ HMONITOR hMon; if (IsWindowOnWrongMonitor(&hMon)) { AMDDRAWGUID guid; hr = DDrawGuidFromHMonitor(hMon, &guid); if(FAILED(hr)){ return(hr); }/* end of if statement */ hr = ChangeMonitor(hMon, &guid); if(FAILED(hr)){ m_MonitorWarn = TRUE; InvalidateRgn(); return(hr); }/* end of if statement */ }/* end of if statement */ // // We always have to invalidate the windows client area, otherwise // we handle the Multi-Mon case very badly. // //::InvalidateRect(hWnd, NULL, FALSE); InvalidateRgn(); return(hr); }/* end of if statement */ return(hr); }/* end of function HandleMultiMonMove */ /*************************************************************************/ /* Function: HandleMultiMonPaint */ /*************************************************************************/ HRESULT CMSWebDVD::HandleMultiMonPaint(HDC hDC){ if (::GetSystemMetrics(SM_CMONITORS) > 1){ MONITORDATA md; md.hMonPB = m_lpCurMonitor ? m_lpCurMonitor->hMon : (HMONITOR)NULL; md.fMsgShouldBeDrawn = FALSE; RECT rc; HRESULT hr = GetClientRectInScreen(&rc); if(FAILED(hr)){ return(hr); }/* end of if statement */ //EnumDisplayMonitors(hDC, NULL, MonitorEnumProc, (LPARAM)&md); EnumDisplayMonitors(NULL, &rc, MonitorEnumProc, (LPARAM)&md); if (m_MonitorWarn && md.fMsgShouldBeDrawn){ TCHAR strBuffer[MAX_PATH]; if(!::LoadString(_Module.m_hInstResource, IDS_MOVE_TO_OTHER_MON, strBuffer, MAX_PATH)){ return(E_UNEXPECTED); }/* end of if statement */ SetBkColor(hDC, RGB(0,0,0)); SetTextColor(hDC, RGB(255,255,0)); if(FAILED(hr)){ return(hr); }/* end of if statement */ DrawText(hDC, strBuffer, -1, &m_rcPos, DT_CENTER | DT_WORDBREAK); }/* end of if statement */ return(S_OK); }/* end of if statement */ return(S_FALSE); }/* end of function HandleMultiMonPaint */ /*************************************************************************/ /* Function: InvalidateRgn */ /* Description: Invalidates the whole rect in case we need to repaint it.*/ /*************************************************************************/ HRESULT CMSWebDVD::InvalidateRgn(bool fErase){ HRESULT hr = S_OK; if(m_bWndLess){ m_spInPlaceSite->InvalidateRgn(NULL ,fErase ? TRUE: FALSE); } else { if(NULL == m_hWnd){ hr = E_FAIL; return(hr); }/* end of if statement */ if(::IsWindow(m_hWnd)){ ::InvalidateRgn(m_hWnd, NULL, fErase ? TRUE: FALSE); // see if we can get by by not erasing.. } else { hr = E_UNEXPECTED; }/* end of if statement */ }/* end of if statement */ return(hr); }/* end of function InvalidateRgn */ /*************************************************************************/ /* End of file: monitor.cpp */ /*************************************************************************/