windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/diconfig/cfrmwrk.cpp
2020-09-26 16:20:57 +08:00

311 lines
7.5 KiB
C++

//-----------------------------------------------------------------------------
// File: cfrmwrk.cpp
//
// Desc: CDirectInputActionFramework is the outer-most layer of the UI. It
// contains everything else. Its functionality is provided by one
// method: ConfigureDevices.
//
// InternalConfigureDevices is called by the CDirectInputActionFramework
// class. This function actually contains the initialization code and
// the message pump for the UI.
//
// Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
//-----------------------------------------------------------------------------
#include "common.hpp"
//QueryInterface
STDMETHODIMP CDirectInputActionFramework::QueryInterface(REFIID iid, LPVOID* ppv)
{
//null the out param
*ppv = NULL;
if ((iid == IID_IUnknown) || (iid == IID_IDIActionFramework))
{
*ppv = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//AddRef
STDMETHODIMP_(ULONG) CDirectInputActionFramework::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
//Release
STDMETHODIMP_(ULONG) CDirectInputActionFramework::Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
// Manages auto loading/unloading WINMM.DLL
// There will only be one instance of this class: inside InternalConfigureDevicees.
class CWinMmLoader
{
public:
CWinMmLoader()
{
if (!g_hWinMmDLL)
{
g_hWinMmDLL = LoadLibrary(_T("WINMM.DLL"));
if (g_hWinMmDLL)
{
*(FARPROC*)(&g_fptimeSetEvent) = GetProcAddress(g_hWinMmDLL, "timeSetEvent");
}
}
}
~CWinMmLoader()
{
if (g_hWinMmDLL)
{
/*
* Make sure no new callbacks can get scheduled then sleep to
* allow any pending ones to complete.
//@@BEGIN_MSINTERNAL
* Use 40ms as 20ms is the UI refresh interval
*
* ISSUE-2000/11/21-MarcAnd
* Should either have a more robust way to make sure no
* timers are left running or at least use constants to
* to make sure that if any timer interval is increased,
* that this value is still long enough.
//@@END_MSINTERNAL
*/
g_fptimeSetEvent = NULL;
Sleep( 40 );
FreeLibrary(g_hWinMmDLL);
g_hWinMmDLL = NULL;
}
}
};
//@@BEGIN_MSINTERNAL
// Manages auto loading/unloading MSIMG32.DLL
// There will only be one instance of this class: inside InternalConfigureDevicees.
/*
class CMSImgLoader
{
public:
CMSImgLoader()
{
if (!g_MSImg32)
{
g_MSImg32 = LoadLibrary(_T("MSIMG32.DLL"));
if (g_MSImg32)
{
g_AlphaBlend = (ALPHABLEND)GetProcAddress(g_MSImg32, "AlphaBlend");
if (!g_AlphaBlend)
{
FreeLibrary(g_MSImg32);
g_MSImg32 = NULL;
}
}
}
}
~CMSImgLoader()
{
if (g_MSImg32)
{
FreeLibrary(g_MSImg32);
g_MSImg32 = NULL;
g_AlphaBlend = NULL;
}
}
};
*/
//@@END_MSINTERNAL
// internal, which api wraps around
static HRESULT InternalConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
DWORD dwFlags,
LPVOID pvRefData)
{
tracescope(__ts, _T("InternalConfigureDevices()\n"));
//@@BEGIN_MSINTERNAL
// CMSImgLoader g_MSImgLoadingHelper; // Automatically call LoadLibrary and FreeLibrary on MSIMG32.DLL
//@@END_MSINTERNAL
CWinMmLoader g_WinMmLoadingHelper; // Automatically call LoadLibrary and FreeLibrary on WINMM.DLL
// check that we're at least 256 colors
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC == NULL)
{
etrace(_T("Can't get a DC! Exiting.\n"));
return E_FAIL;
}
int bpp = GetDeviceCaps(hMemDC, BITSPIXEL);
DeleteDC(hMemDC);
if (bpp < 8)
{
etrace1(_T("Screen is not at least 8bpp (bpp = %d)\n"), bpp);
return E_FAIL;
}
// do it...
{
// create the globals
CUIGlobals uig(
dwFlags,
lpdiCDParams->lptszUserNames,
lpdiCDParams->dwcFormats,
lpdiCDParams->lprgFormats,
&(lpdiCDParams->dics),
lpdiCDParams->lpUnkDDSTarget,
lpdiCallback,
pvRefData
);
HRESULT hr = uig.GetInitResult();
if (FAILED(hr))
{
etrace(_T("CUIGlobals.Init() failed\n"));
return hr;
}
// make sure the flexwnd window class is registered only during possible use
//@@BEGIN_MSINTERNAL
// TODO: consider doing this wnd class stuff at dll scope, or doing it refcount-ish within flexwnd.cpp
//@@END_MSINTERNAL
{
struct flexwndscope {
flexwndscope(CUIGlobals &uig) : m_uig(uig) {CFlexWnd::RegisterWndClass(m_uig.GetInstance());}
~flexwndscope() {CFlexWnd::UnregisterWndClass(m_uig.GetInstance());}
CUIGlobals &m_uig;
} scope(uig);
// create the main window
CConfigWnd cfgWnd(uig);
if (!cfgWnd.Create(lpdiCDParams->hwnd))
{
etrace(_T("Failed to create main window\n"));
return E_FAIL;
}
// Initialize the shared tooltip object.
RECT rc = {0, 0, 0, 0};
CFlexWnd::s_ToolTip.Create(cfgWnd.m_hWnd, rc, TRUE);
if (!CFlexWnd::s_ToolTip.m_hWnd)
{
etrace(_T("Failed to create tooltip window\n"));
return E_FAIL;
}
::ShowWindow(CFlexWnd::s_ToolTip.m_hWnd, SW_HIDE); // Hide window by default
// enter message loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
// If this is a message for the parent window (game window), only dispatch if it's WM_PAINT.
if (!cfgWnd.InRenderMode() && msg.hwnd == lpdiCDParams->hwnd && msg.message != WM_PAINT)
continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CFlexWnd::s_ToolTip.Destroy();
return uig.GetFinalResult();
}
}
BOOL AreAcForsGood(LPDIACTIONFORMATW lpAcFors, DWORD dwNumAcFors)
{
if (lpAcFors == NULL)
return FALSE;
if (dwNumAcFors < 1)
return FALSE;
if (lpAcFors->dwNumActions == 0)
return FALSE;
return TRUE;
}
//ConfigureDevices
STDMETHODIMP CDirectInputActionFramework::ConfigureDevices(
LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
DWORD dwFlags,
LPVOID pvRefData)
{
tracescope(__ts,_T("CDirectInputActionFramework::ConfigureDevices()\n"));
trace(_T("\nConfigureDevices() called...\n\n"));
// check parameters
if (lpdiCDParams == NULL)
{
etrace(_T("NULL params structure passed to ConfigureDevices()\n"));
return E_INVALIDARG;
}
// save passed params in case we change 'em
LPDIACTIONFORMATW lpAcFors = lpdiCDParams->lprgFormats;
DWORD dwNumAcFors = lpdiCDParams->dwcFormats;
#ifdef CFGUI__FORCE_GOOD_ACFORS
if (!AreAcForsGood(lpdiCDParams->lprgFormats, lpdiCDParams->dwcFormats))
{
etrace(_T("Passed ActionFormats aren't good... Using GetTestActionFormats() (just 2 of them).\n"));
lpdiCDParams->dwcFormats = 2;
lpdiCDParams->lprgFormats = GetTestActionFormats();
}
#endif
HRESULT hr = InternalConfigureDevices(lpdiCallback, lpdiCDParams, dwFlags, pvRefData);
// restore passed params in case changed
lpdiCDParams->lprgFormats = lpAcFors;
lpdiCDParams->dwcFormats = dwNumAcFors;
trace(_T("\n"));
if (FAILED(hr))
etrace1(_T("ConfigureDevices() failed, returning 0x%08x\n"), hr);
else
trace1(_T("ConfigureDevices() suceeded, returning 0x%08x\n"), hr);
trace(_T("\n"));
return hr;
}
//constructor
CDirectInputActionFramework::CDirectInputActionFramework()
{
//set ref count
m_cRef = 1;
}
//destructor
CDirectInputActionFramework::~CDirectInputActionFramework()
{
// not necessary to cleanup action format here
}