windows-nt/Source/XPSP1/NT/multimedia/dshow/mfvideo/mswebdvd/monitor.cpp
2020-09-26 16:20:57 +08:00

633 lines
16 KiB
C++

/*************************************************************************/
/* 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 <multimon.h>
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 */
/*************************************************************************/