home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: configwnd.cpp
- //
- // Desc: CConfigWnd is derived from CFlexWnd. It implements the top-level
- // UI window which all other windows are descendents of.
- //
- // Functionalities handled by CConfigWnd are device tabs, Reset, Ok,
- // and Cancel buttons.
- //
- // Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
-
- #include "common.hpp"
-
-
- LPCTSTR g_tszAppWindowName = _T("DINPUT Default Mapper UI");
-
- const int WINDOW_WIDTH = 640;
- const int WINDOW_HEIGHT = 480;
- const int TABTEXTMARGINLEFT = 7;
- const int TABTEXTMARGINTOP = 3;
- const int TABTEXTMARGINRIGHT = 7;
- const int TABTEXTMARGINBOTTOM = 4;
- const int BUTTONTEXTMARGINLEFT = 7;
- const int BUTTONTEXTMARGINTOP = 3;
- const int BUTTONTEXTMARGINRIGHT = 7;
- const int BUTTONTEXTMARGINBOTTOM = 4;
- const int BARBUTTONMARGINLEFT = 9;
- const int BARBUTTONMARGINTOP = 4;
- const int BARBUTTONMARGINRIGHT = 9;
- const int BARBUTTONMARGINBOTTOM = 5;
- const int BARBUTTONSPACING = 4;
-
- //#define WM_QUERYACTIONASSIGNEDANYWHERE (WM_USER + 4)
-
-
- CConfigWnd::CConfigWnd(CUIGlobals &uig) :
- m_uig(uig),
- m_bCreated(FALSE),
- m_pPageFactory(NULL),
- m_hPageFactoryInst(NULL),
- m_pSurface(NULL),
- m_pSurface3D(NULL),
- m_CurSel(-1),
- m_nCurGenre(0),
- m_pbmTopGradient(NULL),
- m_pbmBottomGradient(NULL),
- m_pbmPointerEraser(NULL),
- m_pbm3D(NULL),
- m_p3DBits(NULL),
- m_SurfFormat(D3DFMT_UNKNOWN),
- m_uiPixelSize(4),
- m_bBitmapsMapped(FALSE),
- m_lpDI(NULL),
- m_bScrollTabs(FALSE),
- m_bScrollTabsLeft(FALSE),
- m_bScrollTabsRight(FALSE),
- m_nLeftTab(0),
- m_dwInitFlags(0),
- m_bHourGlass(FALSE),
- m_bNeedRedraw(FALSE)
- {
- tracescope(__ts, _T("CConfigWnd::CConfigWnd()\n"));
- m_lpDI = m_uig.GetDI();
-
- m_pSurface = m_uig.GetSurface();
- m_pSurface3D = m_uig.GetSurface3D();
-
- if (m_pSurface != NULL || m_pSurface3D != NULL)
- {
- if (m_pSurface != NULL && m_pSurface3D != NULL)
- {
- etrace(_T("Both Surface and Surface3D are non-NULL, will use only Surface3D\n"));
-
- m_pSurface->Release();
- m_pSurface = NULL;
-
- assert(m_pSurface3D != NULL);
- assert(m_pSurface == NULL);
- }
-
- assert(m_pSurface != NULL || m_pSurface3D != NULL);
- assert(!(m_pSurface != NULL && m_pSurface3D != NULL));
-
- m_bRender3D = (m_pSurface3D != NULL);
-
- SetRenderMode();
- trace(_T("RenderMode set\n"));
- traceBOOL(m_bRender3D);
-
- if (m_bRender3D)
- Create3DBitmap();
-
- HDC hDC = GetRenderDC();
- if (hDC != NULL)
- {
- m_pbmPointerEraser = CBitmap::Create(
- GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
- hDC);
-
- ReleaseRenderDC(hDC);
- }
- else
- etrace(_T("Failed to get Render DC"));
- }
- }
-
- CConfigWnd::~CConfigWnd()
- {
- tracescope(__ts, _T("CConfigWnd::~CConfigWnd()\n"));
- ClearList();
-
- if (m_lpDI != NULL)
- m_lpDI->Release();
- m_lpDI = NULL;
-
- if (m_pSurface != NULL)
- m_pSurface->Release();
- m_pSurface = NULL;
-
- if (m_pSurface3D != NULL)
- m_pSurface3D->Release();
- m_pSurface3D = NULL;
-
- if (m_pPageFactory != NULL)
- m_pPageFactory->Release();
- m_pPageFactory = NULL;
-
- if (m_hPageFactoryInst != NULL)
- FreeLibrary(m_hPageFactoryInst);
- m_hPageFactoryInst = NULL;
-
- if (m_pbmPointerEraser != NULL)
- delete m_pbmPointerEraser;
- m_pbmPointerEraser = NULL;
-
- if (m_pbm3D != NULL)
- delete m_pbm3D;
- m_pbm3D = NULL;
-
- if (m_pbmTopGradient != NULL)
- delete m_pbmTopGradient;
- m_pbmTopGradient = NULL;
-
- if (m_pbmBottomGradient != NULL)
- delete m_pbmBottomGradient;
- m_pbmBottomGradient = NULL;
- }
-
- HWND CMouseTrap::Create(HWND hParent, BOOL bInRenderMode)
- {
- if (m_hWnd)
- return m_hWnd;
-
- m_hParent = hParent;
- int sx = GetSystemMetrics(SM_CXSCREEN);
- int sy = GetSystemMetrics(SM_CYSCREEN);
- RECT rect = {0, 0, sx, sy};
-
- // If we are not in render mode, the trap window is exactly the same as the parent window
- if (!bInRenderMode)
- GetWindowRect(hParent, &rect);
-
- return CFlexWnd::Create(
- hParent,
- NULL,
- WS_EX_TOPMOST,
- WS_POPUP | WS_VISIBLE,
- rect);
- }
-
- BOOL CConfigWnd::Create(HWND hParent)
- {
- tracescope(__ts, _T("CConfigWnd::Create()\n"));
- traceHEX(hParent);
-
- HRESULT hresult = PrivGetClassObject(CLSID_CDIDeviceActionConfigPage, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (LPVOID*) &m_pPageFactory, &m_hPageFactoryInst);
- if (FAILED(hresult))
- {
- // TODO: indicate failure to create page factory
- m_pPageFactory = NULL;
- m_hPageFactoryInst = NULL;
- etrace1(_T("Failed to create page classfactory, PrivGetClassObject() returned 0x%08x\n"), hresult);
- return FALSE;
- }
-
- int sx = GetSystemMetrics(SM_CXSCREEN);
- int sy = GetSystemMetrics(SM_CYSCREEN);
- int w = WINDOW_WIDTH;
- int h = WINDOW_HEIGHT;
- int rx = sx - w;
- int ry = sy - h;
- RECT rect = {rx / 2, ry / 2, 0, 0};
- rect.right = rect.left + w;
- rect.bottom = rect.top + h;
-
- HWND hConfigParent = hParent;
-
- if (InRenderMode())
- {
- hConfigParent = m_MouseTrap.Create(hParent, InRenderMode());
- if (hConfigParent == NULL)
- hConfigParent = hParent;
- }
-
- HWND hRet = CFlexWnd::Create(
- hConfigParent,
- g_tszAppWindowName,
- 0,
- WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN,
- rect);
-
- if (hRet == NULL)
- etrace(_T("CFlexWnd::Create() failed!\n"));
-
- // Set the cursor extent to this window if we are in render mode (full-screen)
- if (InRenderMode())
- {
- RECT rc;
- GetWindowRect(m_hWnd, &rc);
- ClipCursor(&rc);
- }
-
- return NULL != hRet;
- }
-
- void CConfigWnd::SetForegroundWindow()
- {
- // find the window
- HWND hWnd = FindWindow(GetDefaultClassName(), g_tszAppWindowName);
-
- // activate it if found
- if (NULL != hWnd)
- ::SetForegroundWindow(hWnd);
- }
-
- void CConfigWnd::OnPaint(HDC hDC)
- {
- if (hDC == NULL)
- return;
-
- SIZE topsize = GetRectSize(m_rectTopGradient);
- SIZE bottomsize = GetRectSize(m_rectBottomGradient);
- SIZE bsize = {max(topsize.cx, bottomsize.cx),
- max(topsize.cy, bottomsize.cy)};
- CBitmap *pbm = CBitmap::Create(bsize, hDC);
- if (pbm == NULL)
- return;
- HDC hBDC = NULL, hODC = hDC;
- if (m_bHourGlass)
- {
- if (!InRenderMode())
- {
- // If not in fullscreen mode, change cursor to hourglass
- HCURSOR hCursor;
- hCursor = LoadCursor(NULL, IDC_WAIT);
- SetCursor(hCursor);
- } else
- {
- // If in fullscreen mode, hide the cursor during reset process.
- SetCursor(NULL);
- }
- }
-
- hBDC = pbm->BeginPaintInto(hDC);
- if (hBDC == NULL)
- {
- delete pbm;
- return;
- }
- hDC = hBDC;
-
- if (m_pbmTopGradient != NULL)
- m_pbmTopGradient->Draw(hDC);
-
- {
- CPaintHelper ph(m_uig, hDC);
-
- ph.SetElement(UIE_BORDER);
-
- ph.MoveTo(0, m_rectTopGradient.bottom - 1);
- ph.LineTo(WINDOW_WIDTH, m_rectTopGradient.bottom - 1);
-
- int i;
- for (i = 0; i < GetNumElements(); i++)
- {
- const ELEMENT &e = GetElement(i);
- BOOL bSel = i == m_CurSel;
-
- ph.SetElement(bSel ? UIE_SELTAB : UIE_TAB);
-
- ph.Rectangle(e.rect);
- RECT trect = e.textrect;
- DrawText(hDC, e.tszCaption, -1, &trect, DT_NOCLIP | DT_NOPREFIX);
-
- if (bSel)
- {
- ph.SetPen(UIP_BLACK);
-
- ph.MoveTo(e.rect.left + 1, e.rect.bottom - 1);
- ph.LineTo(e.rect.right - 1, e.rect.bottom - 1);
- }
- }
-
- if (m_bScrollTabs && GetNumElements() > 0)
- {
- ph.SetElement(UIE_TABARROW);
-
- const ELEMENT &e = GetElement(0);
- int h = e.rect.bottom - e.rect.top;
-
- for (i = 0; i < 2; i++)
- {
- RECT &rect = i == 0 ? m_rectSTRight : m_rectSTLeft;
- BOOL bDraw = i ? m_bScrollTabsLeft : m_bScrollTabsRight;
- ph.Rectangle(rect);
-
- if (!bDraw)
- continue;
-
- int d,l,r,m,t,b, f = !i, w;
- w = rect.right - rect.left;
-
- l = f ? w / 4 : 3 * w / 8;
- r = f ? 5 * w / 8 : 3 * w / 4;
- d = r - l;
- m = w / 2;
- t = m - d;
- b = m + d;
-
- l += rect.left;
- r += rect.left;
-
- POINT p[4];
- p[3].x = p[0].x = f ? l : r;
- p[2].x = p[1].x = f ? r : l;
- p[3].y = p[0].y = m;
- p[1].y = t;
- p[2].y = b;
-
- Polyline(hDC, p, 4);
- }
- }
- }
-
- pbm->Draw(hODC, topsize);
- m_pbmBottomGradient->Draw(hDC);
-
- {
- CPaintHelper ph(m_uig, hDC);
-
- ph.SetElement(UIE_BORDER);
-
- Rectangle(hDC, 0, -1, WINDOW_WIDTH,
- GetRectSize(m_rectBottomGradient).cy);
-
- for (int i = 0; i < NUMBUTTONS; i++)
- {
- BOOL bOkOnly = !m_uig.InEditMode();
- const BUTTON &b = m_Button[i];
-
-
- if ( bOkOnly && i != BUTTON_CANCEL
- )
- continue;
-
- if ( (i == BUTTON_OK || bOkOnly)
- )
- ph.SetElement(UIE_DEFBUTTON);
- else
- ph.SetElement(UIE_BUTTON);
-
- int ay = m_rectBottomGradient.top;
- ph.Rectangle(b.rect.left, b.rect.top - ay, b.rect.right, b.rect.bottom - ay);
- RECT trect = b.textrect;
- OffsetRect(&trect, 0, -ay);
- DrawText(hDC, b.tszCaption, -1, &trect, DT_NOCLIP | DT_NOPREFIX);
- }
- }
-
- pbm->Draw(hODC, m_rectBottomGradient.left, m_rectBottomGradient.top, bottomsize);
-
- pbm->EndPaintInto(hBDC);
- delete pbm;
-
- hDC = hODC;
-
- {
- CPaintHelper ph(m_uig, hDC);
-
- ph.SetElement(UIE_BORDER);
-
- ph.MoveTo(0, m_rectTopGradient.bottom);
- ph.LineTo(0, m_rectBottomGradient.top);
-
- ph.MoveTo(WINDOW_WIDTH - 1, m_rectTopGradient.bottom);
- ph.LineTo(WINDOW_WIDTH - 1, m_rectBottomGradient.top);
- }
- }
-
- void CConfigWnd::OnClick(POINT point, WPARAM fwKeys, BOOL bLeft)
- {
- int i;
-
- // Un-highlight the current callout
- SendMessage(CFlexWnd::s_CurrPageHwnd, WM_UNHIGHLIGHT, 0, 0);
-
- // check scroll tab buttons
- if (m_bScrollTabs)
- for (i = 0; i < 2; i++)
- {
- RECT &r = !i ? m_rectSTRight : m_rectSTLeft;
- BOOL b = !i ? m_bScrollTabsRight : m_bScrollTabsLeft;
- if (PtInRect(&r, point))
- {
- if (b)
- ScrollTabs(!i ? -1 : 1);
- return;
- }
- }
-
- // check tabs
- for (i = 0; i < GetNumElements(); i++)
- if (PtInRect(&(GetElement(i).rect), point))
- {
- // Check if the tab is partially obscured. If so we scroll the tab so it becomes completely visible.
- POINT pt = {m_rectSTLeft.left, m_rectSTLeft.top};
- if (m_bScrollTabsRight || m_bScrollTabsLeft)
- {
- while (PtInRect(&(GetElement(i).rect), pt))
- ScrollTabs(1);
- }
- SelTab(i);
- return;
- }
-
- // check buttons
- for (i = 0; i < NUMBUTTONS; i++)
- if (PtInRect(&(m_Button[i].rect), point))
- {
- FireButton(i);
- return;
- }
- }
-
- void CConfigWnd::ScrollTabs(int by)
- {
- m_nLeftTab += by;
- if (m_nLeftTab < 0)
- m_nLeftTab = 0;
- if (m_nLeftTab >= GetNumElements())
- m_nLeftTab = GetNumElements() - 1;
- CalcTabs();
- Invalidate();
- }
-
- void CConfigWnd::OnDestroy()
- {
- tracescope(__ts, _T("CConfigWnd::OnDestroy()\n"));
- ClipCursor(NULL); // Set cursor extent to entire desktop.
- if (m_bCreated)
- PostQuitMessage(EXIT_SUCCESS);
- }
-
- LRESULT CConfigWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- tracescope(__ts, _T("CConfigWnd::OnCreate()\n"));
-
- if (!Init())
- {
- etrace(_T("CConfigWnd::Init() failed\n"));
- return -1;
- }
- else
- m_bCreated = TRUE;
-
- return 0;
- }
-
- BOOL CALLBACK EnumDeviceCallback(const DIDEVICEINSTANCEW *lpdidi, LPDIRECTINPUTDEVICE8W pdiDev8W, DWORD dwFlags, DWORD dwDeviceRemaining, LPVOID pvRef)
- {
- if (pvRef != NULL)
- return ((CConfigWnd *)pvRef)->EnumDeviceCallback(lpdidi);
- else
- return DIENUM_STOP;
- }
-
- BOOL CConfigWnd::EnumDeviceCallback(const DIDEVICEINSTANCEW *lpdidi)
- {
- DIDEVICEINSTANCEW didi;
- didi.dwSize = sizeof(DIDEVICEINSTANCEW);
- didi.guidInstance = lpdidi->guidInstance;
- didi.guidProduct = lpdidi->guidProduct;
- didi.dwDevType = lpdidi->dwDevType;
- CopyStr(didi.tszInstanceName, lpdidi->tszInstanceName, MAX_PATH);
- CopyStr(didi.tszProductName, lpdidi->tszProductName, MAX_PATH);
- didi.guidFFDriver = lpdidi->guidFFDriver;
- didi.wUsagePage = lpdidi->wUsagePage;
- didi.wUsage = lpdidi->wUsage;
-
- AddToList(&didi);
-
- return DIENUM_CONTINUE;
- }
-
- // show any error message here if returning false
- BOOL CConfigWnd::Init(DWORD dwInitFlags)
- {
- tracescope(__ts, _T("CConfigWnd::Init()\n"));
-
- HRESULT hr = S_OK;
- BOOL bReInit = !!(dwInitFlags & CFGWND_INIT_REINIT);
-
- m_dwInitFlags = dwInitFlags;
- SetOnFunctionExit<DWORD> _set_m_dwInitFlags(m_dwInitFlags, 0);
-
- // make sure we have DI
- assert(m_lpDI != NULL);
- if (m_lpDI == NULL)
- {
- etrace(_T("NULL m_lpDI\n"));
- return FALSE;
- }
-
- if (!(dwInitFlags & CFGWND_INIT_RESET))
- {
- // If we are not doing reset, clear device list then re-enumerate and rebuild.
-
- // clear list
- ClearList();
-
- // enum devices
- {
- tracescope(ts, _T("Enumerating Devices...\n\n"));
-
- DWORD dwFlags = DIEDBSFL_ATTACHEDONLY;
- hr = m_lpDI->EnumDevicesBySemantics(NULL, (LPDIACTIONFORMATW)&m_uig.RefMasterAcFor(m_nCurGenre), ::EnumDeviceCallback, (LPVOID)this, dwFlags);
-
- trace(_T("\n"));
- }
- } else
- {
- DIDEVICEINSTANCEW didiCopy;
- // Saves a copy of device instance as the current ELEMENT will be freed by AddToList().
- CopyMemory(&didiCopy, &GetElement(m_CurSel).didi, sizeof(didiCopy));
- // If resetting, call AddToList with bReset as TRUE to just get default mappings.
- AddToList(&didiCopy, TRUE);
- }
-
- // handle potential enum failure
- if (FAILED(hr))
- {
- etrace1(_T("EnumDevicesBySemantics() failed, returning 0x%08x\n"), hr);
- return FALSE;
- }
-
- // if there are no elements, fail
- if (GetNumElements() < 1)
- {
- etrace(_T("No devices\n"));
- return FALSE;
- }
-
- // calculate tabs, buttons, init gradients
- CalcTabs();
- if (!bReInit)
- {
- CalcButtons();
- InitGradients();
-
- // set the timer
- if (InRenderMode())
- {
- if (g_fptimeSetEvent)
- g_fptimeSetEvent(20, 20, CConfigWnd::TimerProc,
- (DWORD_PTR)m_hWnd, TIME_ONESHOT);
- Render();
- }
- }
-
- // make sure all the pages are in the right place
- PlacePages();
-
- // show the first page if we are not resetting. Show current page if we are.
- int CurSel = (dwInitFlags & CFGWND_INIT_RESET) ? m_CurSel : 0;
- m_CurSel = -1;
- SelTab(CurSel);
-
- // if we're already editting the layout, set it.
- // KLUDGE, set false and toggle to set
- if (m_bEditLayout)
- {
- m_bEditLayout = FALSE;
- ToggleLayoutEditting();
- }
-
- trace(_T("\n"));
-
- return TRUE;
- }
-
- // This is called once for each device that will get configured.
- int CConfigWnd::AddToList(const DIDEVICEINSTANCEW *lpdidi, BOOL bReset)
- {
- if (lpdidi == NULL)
- {
- etrace(_T("NULL lpdidi"));
- assert(0);
- return GetNumElements();
- }
-
- int i;
-
- tracescope(ts, _T("Adding Device "));
- trace(QSAFESTR(lpdidi->tszInstanceName));
- trace(_T("\n\n"));
-
- // add an element and get it if we are not doing reset (adding new device)
- if (!bReset)
- {
- i = GetNumElements();
- m_Element.SetSize(i + 1);
- }
- else
- {
- i = m_CurSel;
- ClearElement(m_CurSel, bReset); // If resetting, clear the current ELEMENT as we will populate it below.
- }
-
- // If we are doing reset, then we use the existing ELEMENT that this device is already using.
- ELEMENT &e = bReset ? GetElement(m_CurSel) : GetElement(i);
-
- // set various needed variables
- e.didi = *lpdidi;
- e.bCalc = FALSE;
- e.pUIGlobals = &m_uig;
-
- // create and set the device
- if (m_lpDI == NULL)
- {
- e.lpDID = NULL;
- etrace(_T("m_lpDI NULL! Can't create this device.\n"));
- }
- else
- {
- e.lpDID = CreateDevice(e.didi.guidInstance);
- if (!e.lpDID)
- etrace(_T("Failed to create device!\n"));
- }
-
- if (!bReset)
- {
- // Find owner of device only if we are not doing reset.
- // set starting current user index
- DIPROPSTRING dips;
- dips.diph.dwSize = sizeof(DIPROPSTRING);
- dips.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dips.diph.dwObj = DIPH_DEVICE;
- dips.diph.dwHow = 0;
- CopyStr(dips.wsz, "", MAX_PATH);
- if (!e.lpDID)
- {
- etrace(_T("no lpDID, assuming device unassigned\n"));
- e.nCurUser = -1;
- }
- else
- {
- HRESULT hr = e.lpDID->GetProperty(DIPROP_USERNAME, (LPDIPROPHEADER)&dips);
- e.nCurUser = -1; // unassigned unless getusernameindex below works
- if (FAILED(hr))
- etrace(_T("GetProperty(DIPROP_USERNAME,...) failed\n"));
- else if (hr == S_FALSE)
- trace(_T("GetProperty(DIPROP_USERNAME,...) returned S_FALSE\n"));
- else if (StrLen(dips.wsz) < 1)
- trace(_T("GetProperty(DIPROP_USERNAME,...) returned empty string\n"));
- else
- {
- trace(_T("Getting user name index for "));
- traceWSTR(dips.wsz);
- e.nCurUser = m_uig.GetUserNameIndex(dips.wsz);
- trace(_T("Result: "));
- traceLONG(e.nCurUser);
- if (e.nCurUser == -1)
- etrace(_T("Device assigned to user not passed to ConfigureDevices()\nConsidering unassigned now\n"));
- }
- }
- }
-
- // create and set the page object
- HWND hwndChild = NULL;
- e.pPage = CreatePageObject(i, e, hwndChild);
- if (e.pPage == NULL)
- etrace(_T("Failed to create page object!\n"));
- e.hWnd = hwndChild;
- if (e.hWnd == NULL)
- etrace(_T("CreatePageObject() returned NULL hwnd!\n"));
-
- // create/test the first acfor for this device with cur genre/user
- traceLONG(m_nCurGenre);
- traceLONG(e.nCurUser);
- LPDIACTIONFORMATW lpAcFor = NULL;
- if (e.nCurUser != -1)
- {
- lpAcFor = e.GetAcFor(m_nCurGenre, e.nCurUser, bReset);
- if (lpAcFor != NULL)
- TraceActionFormat(_T("Starting Device ActionFormat:"), *lpAcFor);
- else
- etrace(_T("Failed to create starting ActionFormat\n"));
- }
- else
- trace(_T("Device unassigned\n"));
-
- // check if anything was unsuccessful
- if ((lpAcFor == NULL && e.nCurUser != -1) || e.lpDID == NULL || e.pPage == NULL || e.hWnd == NULL)
- {
- // clear what was successful, set the size back (remove element),
- // and indicate error
- ClearElement(e);
- m_Element.SetSize(i);
- etrace(_T("Can't add this device - Element removed\n"));
- }
-
- trace(_T("\n"));
-
- return GetNumElements();
- }
-
- LPDIRECTINPUTDEVICE8W CConfigWnd::CreateDevice(GUID &guid)
- {
- LPDIRECTINPUTDEVICE8W lpDID;
-
- HRESULT hr = m_lpDI->CreateDevice(guid, &lpDID, NULL);
- if (FAILED(hr) || lpDID == NULL)
- {
- etrace2(_T("Could not create device (guid %s), CreateDevice() returned 0x%08x\n"), GUIDSTR(guid), hr);
- return NULL;
- }
-
- return lpDID;
- }
-
- void CConfigWnd::ClearElement(int i, BOOL bReset)
- {
- ELEMENT &e = GetElement(i);
- ClearElement(e, bReset);
- }
-
- void CConfigWnd::ClearElement(ELEMENT &e, BOOL bReset)
- {
- if (e.pPage != NULL)
- DestroyPageObject(e.pPage);
- if (e.lpDID != NULL)
- {
- e.lpDID->Release();
- e.lpDID = NULL;
- }
- e.pPage = NULL;
- e.lpDID = NULL;
- e.hWnd = NULL;
- e.pUIGlobals = NULL; // not freed
- if (!bReset) // Free map only if we are not resetting (delete permanently).
- e.FreeMap();
- }
-
- void CConfigWnd::ClearList()
- {
- int i;
- for (i = 0; i < GetNumElements(); i++)
- ClearElement(i);
- m_Element.RemoveAll();
- assert(!GetNumElements());
- }
-
- void CConfigWnd::PlacePages()
- {
- RECT rect;
- GetPageRect(rect);
-
- for (int i = 0; i < GetNumElements(); i++)
- {
- DWORD flags = SWP_NOZORDER | SWP_NOACTIVATE;
- SetWindowPos(GetElement(i).hWnd, NULL,
- rect.left, rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top, flags);
- }
- }
-
- SIZE CConfigWnd::GetTextSize(LPCTSTR tszText)
- {
- RECT trect = {0, 0, 1, 1};
- HDC hDC = CreateCompatibleDC(NULL);
- if (hDC != NULL)
- {
- {
- CPaintHelper ph(m_uig, hDC);
- ph.SetFont(UIF_FRAME);
- DrawText(hDC, tszText, -1, &trect, DT_CALCRECT | DT_NOPREFIX);
- }
- DeleteDC(hDC);
- }
- SIZE size = {trect.right - trect.left, trect.bottom - trect.top};
- return size;
- }
-
- void CConfigWnd::InitGradients()
- {
- if (m_pbmTopGradient == NULL)
- m_pbmTopGradient = CBitmap::CreateHorzGradient(m_rectTopGradient, m_uig.GetColor(UIC_CONTROLFILL), m_uig.GetColor(UIC_CONTROLFILL));
- if (m_pbmBottomGradient == NULL)
- m_pbmBottomGradient = CBitmap::CreateHorzGradient(m_rectBottomGradient, m_uig.GetColor(UIC_CONTROLFILL), m_uig.GetColor(UIC_CONTROLFILL));
- }
-
- void CConfigWnd::CalcTabs()
- {
- int i, maxh = 0, lastx = 0;
- for (i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
- CopyStr(e.tszCaption, e.didi.tszInstanceName, MAX_PATH);
- e.rect.left = i > 0 ? GetElement(i - 1).rect.right - 1 : 0;
- e.rect.top = 0;
- SIZE tsize = GetTextSize(e.tszCaption);
- e.textrect.left = e.textrect.top = 0;
- e.textrect.right = tsize.cx;
- e.textrect.bottom = tsize.cy;
- OffsetRect(&e.textrect, e.rect.left + TABTEXTMARGINLEFT, e.rect.top + TABTEXTMARGINTOP);
- int w = tsize.cx;
- int h = tsize.cy;
- e.rect.right = e.rect.left + TABTEXTMARGINLEFT + w + TABTEXTMARGINRIGHT + 1;
- e.rect.bottom = e.rect.top + TABTEXTMARGINTOP + h + TABTEXTMARGINBOTTOM;
- h = e.rect.bottom - e.rect.top;
- if (h > maxh) maxh = h;
- e.bCalc = TRUE;
- }
-
- for (i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
- e.rect.bottom = e.rect.top + maxh;
- lastx = e.rect.right;
- }
-
- if (lastx > WINDOW_WIDTH)
- {
- if (!m_bScrollTabs)
- m_nLeftTab = 0;
- m_bScrollTabs = TRUE;
- }
- else
- {
- m_bScrollTabs = FALSE;
- m_nLeftTab = 0;
- }
-
- int cutoff = WINDOW_WIDTH;
- if (m_bScrollTabs)
- {
- cutoff = WINDOW_WIDTH - maxh * 2;
- RECT r = {WINDOW_WIDTH - maxh, 0, WINDOW_WIDTH, maxh};
- m_rectSTLeft = r;
- OffsetRect(&r, -(maxh - 1), 0);
- m_rectSTRight = r;
- }
-
- if (m_bScrollTabs && m_nLeftTab > 0)
- {
- int left = GetElement(m_nLeftTab).rect.left, right = 0;
- for (i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
- OffsetRect(&e.rect, -left, 0);
- OffsetRect(&e.textrect, -left, 0);
- if (e.rect.right > right)
- right = e.rect.right;
- }
- lastx = right;
- }
-
- if (m_bScrollTabs)
- {
- m_bScrollTabsLeft = lastx > cutoff && m_nLeftTab < GetNumElements() - 1;
- m_bScrollTabsRight = m_nLeftTab > 0;
- }
-
- RECT t = {0/*lastx*/, 0, WINDOW_WIDTH, maxh};
- m_rectTopGradient = t;
- }
-
- void CConfigWnd::CalcButtons()
- {
- SIZE max = {0, 0};
- int i;
- for (i = 0; i < NUMBUTTONS; i++)
- {
- BUTTON &b = m_Button[i];
-
- if (!StrLen(b.tszCaption))
- {
- switch (i)
- {
- case BUTTON_RESET:
- LoadString(g_hModule, IDS_BUTTON_RESET, b.tszCaption, MAX_PATH);
- break;
-
-
- case BUTTON_CANCEL:
- if (m_uig.InEditMode())
- {
- LoadString(g_hModule, IDS_BUTTON_CANCEL, b.tszCaption, MAX_PATH);
- break;
- }
- // else, intentional fallthrough
-
- case BUTTON_OK:
- LoadString(g_hModule, IDS_BUTTON_OK, b.tszCaption, MAX_PATH);
- break;
- }
- }
-
- b.textsize = GetTextSize(b.tszCaption);
-
- if (b.textsize.cx > max.cx)
- max.cx = b.textsize.cx;
- if (b.textsize.cy > max.cy)
- max.cy = b.textsize.cy;
- }
-
- max.cx += BUTTONTEXTMARGINLEFT + BUTTONTEXTMARGINRIGHT;
- max.cy += BUTTONTEXTMARGINTOP + BUTTONTEXTMARGINBOTTOM;
-
- m_rectBottomGradient.bottom = WINDOW_HEIGHT;
- m_rectBottomGradient.top = m_rectBottomGradient.bottom - max.cy - BARBUTTONMARGINTOP - BARBUTTONMARGINBOTTOM;
- m_rectBottomGradient.left = 0;
- m_rectBottomGradient.right = WINDOW_WIDTH;
-
- for (i = 0; i < NUMBUTTONS; i++)
- {
- BUTTON &b = m_Button[i];
-
- RECT z = {0,0,0,0};
-
- b.rect = z;
- b.rect.right = max.cx;
- b.rect.bottom = max.cy;
-
- int by = m_rectBottomGradient.top + BARBUTTONMARGINTOP;
-
- switch (i)
- {
- case BUTTON_RESET:
- OffsetRect(&b.rect, BARBUTTONMARGINLEFT, by);
- break;
-
-
- case BUTTON_CANCEL:
- OffsetRect(&b.rect,
- m_rectBottomGradient.right - BARBUTTONMARGINRIGHT - max.cx, by);
- break;
-
- case BUTTON_OK:
- OffsetRect(&b.rect,
- m_rectBottomGradient.right - BARBUTTONMARGINRIGHT - max.cx - max.cx - BARBUTTONSPACING, by);
- break;
- }
-
- POINT m = {(b.rect.right + b.rect.left) / 2, (b.rect.bottom + b.rect.top) / 2};
- b.textrect.left = m.x - b.textsize.cx / 2;
- b.textrect.top = m.y - b.textsize.cy / 2;
- b.textrect.right = b.textrect.left + b.textsize.cx;
- b.textrect.bottom = b.textrect.top + b.textsize.cy;
- }
- }
-
- void CConfigWnd::GetPageRect(RECT &rect, BOOL bTemp)
- {
- if (bTemp)
- {
- rect.left = 1;
- rect.right = WINDOW_WIDTH - 1;
- rect.top = 40;
- rect.bottom = WINDOW_HEIGHT - 40;
- }
- else
- {
- rect.left = 1;
- rect.right = WINDOW_WIDTH - 1;
- rect.top = m_rectTopGradient.bottom;
- rect.bottom = m_rectBottomGradient.top;
- }
- }
-
- void CConfigWnd::ToggleLayoutEditting()
- {
- m_bEditLayout = !m_bEditLayout;
-
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
- if (e.pPage)
- e.pPage->SetEditLayout(m_bEditLayout);
- }
- }
-
- void CConfigWnd::FireButton(int b)
- {
- switch(b)
- {
- case BUTTON_OK:
- if (!m_uig.InEditMode())
- break; // If not in edit mode, Ok button doesn't not exist so we shouldn't do anything.
- Apply(); // If we are in Edit Layout mode, do not call Apply() to save to user setting.
- // intentional fallthrough
-
- case BUTTON_CANCEL:
- Destroy();
- break;
-
- case BUTTON_RESET:
- if (m_uig.InEditMode()) // Only reset if in edit mode. Do nothing in view mode.
- Reset();
- break;
-
-
- default:
- assert(0);
- break;
- }
- }
-
- void CConfigWnd::SelTab(int i)
- {
- if (i >= 0 && i < GetNumElements())
- {
- if (i == m_CurSel)
- return;
- ShowPage(i);
- HidePage(m_CurSel);
- m_CurSel = i;
- Invalidate();
- }
- }
-
- PAGETYPE *CConfigWnd::CreatePageObject(int nPage, const ELEMENT &e, HWND &refhChildWnd)
- {
- if (m_pPageFactory == NULL)
- return NULL;
-
- PAGETYPE *pPage = NULL;
- HRESULT hresult = m_pPageFactory->CreateInstance(NULL, IID_IDIDeviceActionConfigPage, (LPVOID*) &pPage);
- if (FAILED(hresult) || pPage == NULL)
- return NULL;
-
- DICFGPAGECREATESTRUCT cs;
- cs.dwSize = sizeof(DICFGPAGECREATESTRUCT);
- cs.nPage = nPage;
- cs.hParentWnd = m_hWnd;
- GetPageRect(cs.rect, TRUE);
- cs.hPageWnd = NULL;
- cs.didi = e.didi;
- cs.lpDID = e.lpDID;
- cs.pUIGlobals = &m_uig;
- cs.pUIFrame = dynamic_cast<IDIConfigUIFrameWindow *>(this);
-
- hresult = pPage->Create(&cs);
- if (FAILED(hresult))
- {
- etrace1(_T("pPage->Create() failed, returning 0x%08x\n"), hresult);
- pPage->Release();
- return NULL;
- }
-
- refhChildWnd = cs.hPageWnd;
-
- return pPage;
- }
-
- void CConfigWnd::DestroyPageObject(PAGETYPE *&pPage)
- {
- if (pPage != NULL)
- pPage->Release();
- pPage = NULL;
- }
-
- void CConfigWnd::ShowPage(int i)
- {
- if (i == -1)
- return;
-
- if (i < 0 || i >= GetNumElements())
- {
- assert(0);
- return;
- }
-
- ELEMENT &e = GetElement(i);
-
- PAGETYPE *pPage = e.pPage;
- if (pPage == NULL)
- {
- assert(0);
- return;
- }
-
- pPage->Show(e.GetAcFor(m_nCurGenre, e.nCurUser));
- }
-
- void CConfigWnd::HidePage(int i)
- {
- if (i == -1)
- return;
-
- if (i < 0 || i >= GetNumElements())
- {
- assert(0);
- return;
- }
-
- PAGETYPE *pPage = GetElement(i).pPage;
- if (pPage == NULL)
- {
- assert(0);
- return;
- }
-
- pPage->Hide();
- }
-
- void CConfigWnd::OnMouseOver(POINT point, WPARAM fwKeys)
- {
- int i;
-
- CFlexWnd::s_ToolTip.SetEnable(FALSE);
-
- // check scroll tab buttons
- if (m_bScrollTabs)
- for (i = 0; i < 2; i++)
- {
- RECT &r = !i ? m_rectSTRight : m_rectSTLeft;
- BOOL b = !i ? m_bScrollTabsRight : m_bScrollTabsLeft;
- if (PtInRect(&r, point))
- {
- if (b)
- GetElement(m_CurSel).pPage->SetInfoText(m_uig.InEditMode() ? IDS_INFOMSG_EDIT_TABSCROLL : IDS_INFOMSG_VIEW_TABSCROLL);
- return;
- }
- }
-
- // check tabs
- for (i = 0; i < GetNumElements(); i++)
- if (PtInRect(&(GetElement(i).rect), point))
- {
- GetElement(m_CurSel).pPage->SetInfoText(m_uig.InEditMode() ? IDS_INFOMSG_EDIT_TAB : IDS_INFOMSG_VIEW_TAB);
- return;
- }
-
- // check buttons
- for (i = 0; i < NUMBUTTONS; i++)
- if (PtInRect(&(m_Button[i].rect), point))
- {
- switch(i)
- {
- case BUTTON_OK:
- if (m_uig.InEditMode())
- GetElement(m_CurSel).pPage->SetInfoText(IDS_INFOMSG_EDIT_OK);
- break;
-
- case BUTTON_CANCEL:
- if (m_uig.InEditMode())
- GetElement(m_CurSel).pPage->SetInfoText(IDS_INFOMSG_EDIT_CANCEL);
- else
- GetElement(m_CurSel).pPage->SetInfoText(IDS_INFOMSG_VIEW_OK);
- break;
-
- case BUTTON_RESET:
- if (m_uig.InEditMode()) // Only reset if in edit mode. Do nothing in view mode.
- GetElement(m_CurSel).pPage->SetInfoText(IDS_INFOMSG_EDIT_RESET);
- break;
- }
- return;
- }
-
- GetElement(m_CurSel).pPage->SetInfoText(-1);
- }
-
- void CALLBACK CConfigWnd::TimerProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
- {
- if (!IsWindow((HWND)dwUser)) return; // Verify that dwUser is a valid window handle
- CConfigWnd *pCfgWnd = (CConfigWnd *)GetFlexWnd((HWND)dwUser); // Get flex object
-
- // We use PostMessage instead of calling Render() so we stay synchronized.
- PostMessage((HWND)dwUser, WM_DIRENDER, 0, 0);
- }
-
- void CConfigWnd::MapBitmaps(HDC hDC)
- {
- if (m_bBitmapsMapped)
- return;
-
- if (m_pbmTopGradient)
- m_pbmTopGradient->MapToDC(hDC);
- if (m_pbmBottomGradient)
- m_pbmBottomGradient->MapToDC(hDC);
-
- m_bBitmapsMapped = TRUE;
- }
-
- LPDIACTIONFORMATW CConfigWnd::GetCurAcFor(ELEMENT &e)
- {
- return e.GetAcFor(m_nCurGenre, e.nCurUser);
- }
-
- BOOL CConfigWnd::IsActionAssignedAnywhere(GUID GuidInstance, int nActionIndex)
- {
- // Find out which user owns the device in question first.
- int nUser = 0;
- for (int ii = 0; ii < GetNumElements(); ii++)
- {
- ELEMENT &e = GetElement(ii);
- if (IsEqualGUID(e.didi.guidInstance, GuidInstance))
- {
- nUser = e.nCurUser;
- break;
- }
- }
-
- // Now we check the actions against this user.
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
- const LPDIACTIONFORMATW &lpAcFor = e.GetAcFor(m_nCurGenre, nUser);
-
- if (lpAcFor == NULL)
- continue;
-
- if (nActionIndex < 0 || nActionIndex > int(lpAcFor->dwNumActions))
- continue;
-
- // If this device is not owned by this user, don't need to check.
- if (e.nCurUser != nUser)
- continue;
-
- const DIACTIONW &a = lpAcFor->rgoAction[nActionIndex];
-
- if (!IsEqualGUID(a.guidInstance, GUID_NULL))
- return TRUE;
- }
-
- return FALSE;
- }
-
- LRESULT CConfigWnd::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch (msg)
- {
- case WM_ACTIVATE:
- switch(wParam)
- {
- case WA_ACTIVE:
- case WA_CLICKACTIVE:
- // Set the cursor extent to this window if we are in render mode because the
- // cursor can't be drawn by us when it's not above us.
- if (InRenderMode())
- {
- RECT rc;
- GetWindowRect(m_hWnd, &rc);
- ClipCursor(&rc);
- }
- // Reacquire current device
- if (GetNumElements() && m_CurSel >= 0)
- GetElement(m_CurSel).pPage->Reacquire();
- break;
- case WA_INACTIVE:
- // Unacquire current device
- if (GetNumElements() && m_CurSel >= 0)
- GetElement(m_CurSel).pPage->Unacquire();
- break;
- }
- break;
-
- case WM_DIRENDER:
- // Render message, sent by TimerProc() earlier.
- // The timer proc has request a render operation.
- Render(m_bNeedRedraw);
-
- // Set the next timer event.
- if (g_fptimeSetEvent)
- g_fptimeSetEvent(20, 20, CConfigWnd::TimerProc,
- (DWORD_PTR)m_hWnd, TIME_ONESHOT);
- return 0;
-
- case WM_SETFOCUS:
- // Set the keyboard focus to the current page window.
- ShowPage(m_CurSel); // Call Show() on current page so it can get keyboard focus.
- return 0;
-
- // WM_NCHITTEST handler is added to support moving window when in GDI mode.
- case WM_NCHITTEST:
- {
- if (InRenderMode()) break;
-
- BOOL bHitCaption = TRUE;
- POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)};
- int i;
-
- ScreenToClient(m_hWnd, &point);
- // check scroll tab buttons
- if (m_bScrollTabs)
- for (i = 0; i < 2; i++)
- {
- RECT &r = !i ? m_rectSTRight : m_rectSTLeft;
- BOOL b = !i ? m_bScrollTabsRight : m_bScrollTabsLeft;
- if (PtInRect(&r, point))
- {
- if (b)
- bHitCaption = FALSE;
- break;
- }
- }
-
- // check tabs
- for (i = 0; i < GetNumElements(); i++)
- if (PtInRect(&(GetElement(i).rect), point))
- {
- bHitCaption = FALSE;
- break;
- }
-
- // check buttons
- for (i = 0; i < NUMBUTTONS; i++)
- if (PtInRect(&(m_Button[i].rect), point))
- {
- if ((i == BUTTON_RESET || i == BUTTON_OK) && !m_uig.InEditMode()) continue;
- bHitCaption = FALSE;
- break;
- }
-
- // Check Y coordinate to see if it is within the caption bar.
- if ((point.y < GetElement(0).rect.top || point.y > GetElement(0).rect.bottom) &&
- (point.y < m_rectBottomGradient.top || point.y > m_rectBottomGradient.bottom))
- bHitCaption = FALSE;
-
- if (bHitCaption)
- {
- // If we are returning HTCAPTION, clear the page's info box.
- GetElement(m_CurSel).pPage->SetInfoText(-1);
- return HTCAPTION;
- }
- break;
- }
-
- case WM_CFGUIRESET:
- {
- CFlexWnd::s_ToolTip.SetEnable(FALSE);
- m_bHourGlass = TRUE; // Set the flag so Render() will draw hourglass instead of arrow
- Invalidate();
- SendMessage(this->m_hWnd, WM_PAINT, 0, 0);
- if (InRenderMode()) // If in render mode, need to specifically call OnRender as sending WM_PAINT merely changes flag.
- Render(TRUE);
- if (!Init(CFGWND_INIT_REINIT | CFGWND_INIT_RESET))
- {
- m_uig.SetFinalResult(E_FAIL);
- Destroy();
- }
- m_bHourGlass = FALSE; // Change cursor back to arrow
- m_MsgBox.Destroy();
- Invalidate();
- return TRUE;
- }
-
- case WM_SETCURSOR:
- {
- static HCURSOR hCursor = LoadCursor(NULL, IDC_ARROW);
- ::SetCursor(InRenderMode() ? NULL : hCursor);
- }
- return TRUE;
-
- // case WM_QUERYACTIONASSIGNEDANYWHERE:
- // return IsActionAssignedAnywhere(int(wParam), int(lParam));
- }
-
- return CFlexWnd::WndProc(hWnd, msg, wParam, lParam);
- }
-
- HRESULT CConfigWnd::Apply()
- {
- tracescope(ts, _T("\n\nApplying Changes to All Devices...\n"));
-
- // Devices need to be in the unaquired state when SetActionMap is called.
- Unacquire();
-
- for (int i = 0; i < GetNumElements(); i++)
- GetElement(i).Apply();
-
- Reacquire();
-
- trace(_T("\n\n"));
-
- return S_OK;
- }
-
- int CConfigWnd::GetNumElements()
- {
- return m_Element.GetSize();
- }
-
- ELEMENT &CConfigWnd::GetElement(int i)
- {
- if (i < 0 || i >= GetNumElements())
- {
- assert(0);
- etrace1(_T("Tried to get invalid element %d\n"), i);
- return m_InvalidElement;
- }
-
- return m_Element[i];
- }
-
- // This function returns a pointer to the action format of the device that has the given GUID
- HRESULT CConfigWnd::GetActionFormatFromInstanceGuid(LPDIACTIONFORMATW *lplpAcFor, REFGUID Guid)
- {
- if (!lplpAcFor)
- return E_INVALIDARG;
-
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = m_Element[i];
-
- if (e.didi.guidInstance == Guid)
- {
- *lplpAcFor = GetCurAcFor(e);
- return S_OK;
- }
- }
-
- return E_INVALIDARG;
- }
-
- HDC CConfigWnd::GetRenderDC()
- {
- assert(InRenderMode());
-
- if (m_bRender3D)
- return m_pbm3D == NULL ? NULL : m_pbm3D->BeginPaintInto();
- else
- {
- if (m_pSurface == NULL)
- return NULL;
-
- HDC hDC = NULL;
- HRESULT hr = m_pSurface->GetDC(&hDC);
- if (FAILED(hr))
- if (hr == DDERR_SURFACELOST)
- {
- m_pSurface->Restore(); // Restore the surface
- hr = m_pSurface->GetDC(&hDC); // Retry
- if (FAILED(hr))
- return NULL;
- }
- else
- return NULL;
-
- return hDC;
- }
- }
-
- void CConfigWnd::ReleaseRenderDC(HDC &phDC)
- {
- assert(InRenderMode());
-
- HDC hDC = phDC;
- phDC = NULL;
-
- if (m_bRender3D)
- {
- if (m_pbm3D == NULL)
- return;
-
- m_pbm3D->EndPaintInto(hDC);
- }
- else
- {
- if (m_pSurface == NULL)
- return;
-
- m_pSurface->ReleaseDC(hDC);
- }
- }
-
- struct BITMAPINFO_3MASKS
- {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[3];
- };
-
- void CConfigWnd::Create3DBitmap()
- {
- HDC hDC = CreateCompatibleDC(NULL);
-
- BITMAPINFO_3MASKS bmi3mask; // BITMAPINFO with 3 DWORDs for bmiColors
- BITMAPINFO *pbmi = (BITMAPINFO*)&bmi3mask;
-
- BITMAPINFOHEADER &h = pbmi->bmiHeader;
- h.biSize = sizeof(BITMAPINFOHEADER);
- h.biWidth = WINDOW_WIDTH;
- h.biHeight = -WINDOW_HEIGHT;
- h.biPlanes = 1;
- h.biSizeImage = 0;
- h.biXPelsPerMeter = 100;
- h.biYPelsPerMeter = 100;
- h.biClrImportant = 0;
-
- // Get the surface's pixel format
- D3DSURFACE_DESC d3dsd;
- ZeroMemory(&d3dsd, sizeof(d3dsd));
- m_pSurface3D->GetDesc(&d3dsd);
- m_SurfFormat = d3dsd.Format;
- switch(d3dsd.Format)
- {
- case D3DFMT_R5G6B5:
- h.biClrUsed = 3;
- h.biBitCount = 16;
- m_uiPixelSize = 2;
- h.biCompression = BI_BITFIELDS;
- *((LPDWORD)pbmi->bmiColors) = 0xF800;
- *((LPDWORD)pbmi->bmiColors+1) = 0x07E0;
- *((LPDWORD)pbmi->bmiColors+2) = 0x001F;
- break;
-
- case D3DFMT_X1R5G5B5:
- case D3DFMT_A1R5G5B5:
- h.biClrUsed = 3;
- h.biBitCount = 16;
- m_uiPixelSize = 2;
- h.biCompression = BI_BITFIELDS;
- *((LPDWORD)pbmi->bmiColors) = 0x7C00;
- *((LPDWORD)pbmi->bmiColors+1) = 0x03E0;
- *((LPDWORD)pbmi->bmiColors+2) = 0x001F;
- break;
-
- case D3DFMT_R8G8B8:
- h.biClrUsed = 0;
- h.biBitCount = 24;
- m_uiPixelSize = 3;
- h.biCompression = BI_RGB;
- break;
-
- case D3DFMT_A8R8G8B8:
- case D3DFMT_X8R8G8B8:
- default:
- // Use 32 bits for all other formats
- h.biClrUsed = 0;
- h.biBitCount = 32;
- m_uiPixelSize = 4;
- h.biCompression = BI_RGB;
- break;
- }
-
- HBITMAP hbm = CreateDIBSection(
- hDC,
- pbmi,
- DIB_RGB_COLORS,
- &m_p3DBits,
- NULL,
- 0);
-
- DeleteDC(hDC);
- hDC = NULL;
-
- if (hbm != NULL)
- m_pbm3D = CBitmap::StealToCreate(hbm);
-
- if (hbm != NULL)
- DeleteObject((HGDIOBJ)hbm);
- hbm = NULL;
- }
-
- void CConfigWnd::Copy3DBitmapToSurface3D()
- {
- assert(m_bRender3D);
-
- if (m_p3DBits == NULL || m_pbm3D == NULL || m_pSurface3D == NULL)
- {
- etrace(_T("One or more of the vars required for Copy3DBitmapToSurface() was NULL!\n"));
- return;
- }
-
- RECT rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
-
- HRESULT hr = D3DXLoadSurfaceFromMemory(
- m_pSurface3D,
- NULL,
- NULL,//&rect,
- m_p3DBits,
- m_SurfFormat,
- WINDOW_WIDTH * m_uiPixelSize,
- NULL,
- &rect,
- D3DX_FILTER_POINT,
- 0); // Disable Color Key
- }
-
- void CConfigWnd::CallRenderCallback()
- {
- LPDICONFIGUREDEVICESCALLBACK pCallback = m_uig.GetCallback();
- LPVOID pvRefData = m_uig.GetRefData();
-
- if (pCallback == NULL)
- return;
-
- if (m_bRender3D)
- {
- Copy3DBitmapToSurface3D();
- pCallback(m_pSurface3D, pvRefData);
- }
- else
- {
- pCallback(m_pSurface, pvRefData);
- }
- }
-
- void CConfigWnd::OnRender(BOOL bInternalCall)
- {
- m_bNeedRedraw = TRUE;
- }
-
- void CConfigWnd::Render(BOOL bInternalCall)
- {
- tracescope(__ts, _T("CConfigWnd::Render() "));
- traceBOOL(bInternalCall);
-
- m_bNeedRedraw = FALSE;
-
- ValidateRect(m_hWnd, NULL);
-
- if (m_hWnd == NULL)
- return;
-
- HDC hDC = GetRenderDC();
- if (hDC == NULL)
- return;
-
- if (bInternalCall)
- RenderInto(hDC);
-
- static ICONINFO IconInfo;
- static HCURSOR hOldCursor = NULL;
- static HCURSOR hCursor;
- if (m_bHourGlass)
- hCursor = LoadCursor(NULL, IDC_WAIT);
- else
- hCursor = LoadCursor(NULL, IDC_ARROW);
- if (hCursor == NULL)
- return;
-
- if (hOldCursor != hCursor)
- {
- hOldCursor = hCursor;
- GetIconInfo(hCursor, &IconInfo);
-
- if (IconInfo.hbmMask)
- DeleteObject(IconInfo.hbmMask);
-
- if (IconInfo.hbmColor)
- DeleteObject(IconInfo.hbmColor);
- }
-
- POINT pt;
- GetCursorPos(&pt);
-
- ScreenToClient(m_hWnd, &pt);
-
- pt.x -= IconInfo.xHotspot;
- pt.y -= IconInfo.yHotspot;
-
- if (m_pbmPointerEraser)
- m_pbmPointerEraser->Get(hDC, pt);
-
- // If m_bHourGlass is true, we are resetting, so we don't draw mouse cursor.
- if (hCursor && !m_bHourGlass)
- DrawIcon(hDC, pt.x, pt.y, hCursor);
-
- ReleaseRenderDC(hDC);
-
- CallRenderCallback();
-
- hDC = GetRenderDC();
- if (hDC == NULL)
- return;
-
- if (m_pbmPointerEraser)
- m_pbmPointerEraser->Draw(hDC, pt);
-
- ReleaseRenderDC(hDC);
- }
-
- void CConfigWnd::Unacquire()
- {
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = m_Element[i];
- if (e.pPage != NULL)
- e.pPage->Unacquire();
- }
- }
-
- void CConfigWnd::Reacquire()
- {
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = m_Element[i];
- if (e.pPage != NULL)
- e.pPage->Reacquire();
- }
- }
-
- HRESULT CConfigWnd::Reset()
- {
- RECT rect;
- int iCenterX, iCenterY;
-
- GetClientRect(&rect);
- iCenterX = (rect.left + rect.right) >> 1;
- iCenterY = (rect.top + rect.bottom) >> 1;
- rect.left = rect.right = iCenterX;
- rect.top = rect.bottom = iCenterY;
- InflateRect(&rect, g_iResetMsgBoxWidth >> 1, g_iResetMsgBoxHeight >> 1);
-
- m_MsgBox.Create(m_hWnd, rect, FALSE);
- m_MsgBox.SetNotify(m_hWnd);
- m_MsgBox.SetFont((HFONT)m_uig.GetFont(UIE_USERNAMES));
- m_MsgBox.SetColors(m_uig.GetTextColor(UIE_USERNAMES),
- m_uig.GetBkColor(UIE_USERNAMES),
- m_uig.GetTextColor(UIE_USERNAMESEL),
- m_uig.GetBkColor(UIE_USERNAMESEL),
- m_uig.GetBrushColor(UIE_USERNAMES),
- m_uig.GetPenColor(UIE_USERNAMES));
-
- TCHAR tszResourceString[MAX_PATH];
- LoadString(g_hModule, IDS_RESETMSG, tszResourceString, MAX_PATH);
- m_MsgBox.SetText(tszResourceString);
- ::ShowWindow(m_MsgBox.m_hWnd, SW_SHOW);
- ::SetWindowPos(m_MsgBox.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
- m_MsgBox.Invalidate();
- return S_OK;
- }
-
- HRESULT CConfigWnd::QueryActionAssignedAnywhere(GUID GuidInstance, int i)
- {
- return IsActionAssignedAnywhere(GuidInstance, i) ? S_OK : S_FALSE;
- }
-
- int CConfigWnd::GetNumGenres()
- {
- return m_uig.GetNumMasterAcFors();
- }
-
- HRESULT CConfigWnd::SetCurUser(int nPage, int nUser)
- {
- // make sure we're using a valid element index
- if (nPage < 0 || nPage >= GetNumElements())
- {
- assert(0);
- return E_FAIL;
- }
-
- // get the element
- ELEMENT &e = GetElement(nPage);
-
- // don't do anything if we're already set to this user
- if (e.nCurUser == nUser)
- return S_OK;
-
- // store new curuser
- e.nCurUser = nUser;
-
- // if this page isn't the one currently shown, do nothing
- // (it'll get the new acfor when it's shown)
- if (m_CurSel != nPage)
- return S_OK;
-
- // otherwised, cycle the page to reflect change
- if (e.pPage)
- e.pPage->Unacquire();
- HidePage(nPage);
- ShowPage(nPage);
- if (e.pPage)
- e.pPage->Reacquire();
-
- return S_OK;
- }
-
- HRESULT CConfigWnd::SetCurGenre(int NewGenre)
- {
- // if no change, do nothing
- if (NewGenre == m_nCurGenre)
- return S_OK;
-
- // make sure genre index is in range
- if (NewGenre < 0 || NewGenre >= GetNumGenres())
- return E_INVALIDARG;
-
- // set genre
- m_nCurGenre = NewGenre;
-
- // store which page is currently up
- int iOldPage = m_CurSel;
-
- // for each page...
- BOOL bShown = FALSE;
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
-
- // hide the page and unacquire its device
- if (e.pPage)
- {
- e.pPage->Unacquire();
- HidePage(i);
- }
-
- // show page if it was the old cur page
- if (i == iOldPage && e.pPage && GetCurAcFor(e))
- {
- ShowPage(i);
- bShown = TRUE;
- }
-
- // reacquire device
- if (e.pPage)
- e.pPage->Reacquire();
- }
-
- // if nothing was shown, show something
- if (!bShown && GetNumElements() > 0)
- {
- m_CurSel = -1;
- SelTab(0);
- }
-
- // if we showed the one we expected to show, we succeeded
- return bShown ? S_OK : E_FAIL;
- }
-
- int CConfigWnd::GetCurGenre()
- {
- return m_nCurGenre;
- }
-
- HWND CConfigWnd::GetMainHWND()
- {
- return m_hWnd;
- }
-
- // This is called by CDIDeviceActionConfigPage::DeviceUINotify.
- // We scan the ELEMENT array and when we find a match, destroy and recreate the device
- // object, then return it back to CDIDeviceActionConfigPage so it can update its pointer.
- LPDIRECTINPUTDEVICE8W CConfigWnd::RenewDevice(GUID &GuidInstance)
- {
- for (int i = 0; i < GetNumElements(); i++)
- {
- ELEMENT &e = GetElement(i);
-
- if (e.didi.guidInstance == GuidInstance)
- {
- // Releaes the instance we have
- if (e.lpDID)
- {
- e.lpDID->Release();
- e.lpDID = NULL;
- }
- // Recreate the device
- e.lpDID = CreateDevice(e.didi.guidInstance);
- return e.lpDID;
- }
- }
- return NULL;
- }
-
- LPDIACTIONFORMATW ELEMENT::GetAcFor(int nGenre, int nUser, BOOL bHwDefault)
- {
- // return null if requesting for unassigned user
- if (nUser == -1)
- return NULL;
-
- // validate params
- if (!lpDID || !pUIGlobals || nGenre < 0 ||
- nGenre >= pUIGlobals->GetNumMasterAcFors() ||
- nUser < 0 || nUser >= pUIGlobals->GetNumUserNames())
- {
- etrace(_T("ELEMENT::GetAcFor(): Invalid params\n"));
- return NULL;
- }
-
- // generate dword id for map entry
- DWORD dwMap = GENREUSER2MAP(nGenre, nUser);
-
- // try to get that acfor
- LPDIACTIONFORMATW lpAcFor = NULL;
- BOOL bFound = AcForMap.Lookup(dwMap, lpAcFor);
-
- // if we found it and its not null and we are asked for hardware default setting, return it
- if (bFound && lpAcFor && !bHwDefault)
- return lpAcFor;
-
- // otherwise... we gotta make it
- tracescope(__ts, _T("ELEMENT::GetAcFor"));
- trace2(_T("(%d, %d)\n"), nGenre, nUser);
- trace1(_T("Building map entry 0x%08x...\n"), dwMap);
-
- // copy it from the masteracfor for the genre
- lpAcFor = DupActionFormat(&(pUIGlobals->RefMasterAcFor(nGenre)));
- if (!lpAcFor)
- {
- etrace(_T("DupActionFormat() failed\n"));
- return NULL;
- }
-
- // build it for the user
- DWORD dwFlags = 0;
- if (bHwDefault
- )
- dwFlags |= DIDBAM_HWDEFAULTS;
- LPCWSTR wszUserName = pUIGlobals->GetUserName(nUser);
- HRESULT hr = lpDID->BuildActionMap(lpAcFor, wszUserName, dwFlags);
- if (FAILED(hr))
- {
- etrace4(_T("BuildActionMap(0x%p, %s, 0x%08x) failed, returning 0x%08x\n"), lpAcFor, QSAFESTR(wszUserName), dwFlags, hr);
- FreeActionFormatDup(lpAcFor);
- lpAcFor = NULL;
- return NULL;
- }
- else
- {
- trace3(_T("BuildActionMap(0x%p, %s, 0x%08x) succeeded\n"), lpAcFor, QSAFESTR(wszUserName), dwFlags);
- // Now we check if the return code is DI_WRITEPROTECT. If so, device can't be remapped.
- if (hr == DI_WRITEPROTECT)
- {
- // The way we disable mapping is to add DIA_APPFIXED flag to all actions.
- for (DWORD i = 0; i < lpAcFor->dwNumActions; ++i)
- lpAcFor->rgoAction[i].dwFlags |= DIA_APPFIXED;
- }
- }
-
- // Here we copy the DIA_APPFIXED flag back to our action format for all DIACTION that had this.
- const DIACTIONFORMATW &MasterAcFor = pUIGlobals->RefMasterAcFor(nGenre);
- for (DWORD i = 0; i < MasterAcFor.dwNumActions; ++i)
- if (MasterAcFor.rgoAction[i].dwFlags & DIA_APPFIXED)
- lpAcFor->rgoAction[i].dwFlags |= DIA_APPFIXED;
- // set it in the map
- assert(lpAcFor != NULL);
- AcForMap.SetAt(dwMap, lpAcFor);
-
- // return it
- return lpAcFor;
- }
-
- void ELEMENT::FreeMap()
- {
- POSITION pos = AcForMap.GetStartPosition();
- while (pos != NULL)
- {
- DWORD dwMap = (DWORD)-1;
- LPDIACTIONFORMATW lpAcFor = NULL;
- AcForMap.GetNextAssoc(pos, dwMap, lpAcFor);
-
- if (lpAcFor)
- FreeActionFormatDup(lpAcFor);
- }
- AcForMap.RemoveAll();
- }
-
- void ELEMENT::Apply()
- {
- tracescope(tsa, _T("\nELEMENT::Apply()\n"));
- trace1(_T("Applying Changes to Device %s\n"), QSAFESTR(didi.tszInstanceName));
-
- if (lpDID == NULL)
- {
- etrace(_T("NULL lpDID, can't apply\n"));
- return;
- }
-
- if (pUIGlobals == NULL)
- {
- etrace(_T("NULL pUIGlobals, can't apply\n"));
- return;
- }
-
- LPDIACTIONFORMATW lpAcFor = NULL;
-
- // go through the map and add the map keys to last if the user
- // is the current user assignment, or to first if not
- CList<DWORD, DWORD &> first, last;
- POSITION pos = AcForMap.GetStartPosition();
- while (pos != NULL)
- {
- DWORD dwMap = (DWORD)-1;
- lpAcFor = NULL;
- AcForMap.GetNextAssoc(pos, dwMap, lpAcFor);
-
- if (MAP2USER(dwMap) == nCurUser)
- last.AddTail(dwMap);
- else
- first.AddTail(dwMap);
- }
-
- // concatenate lists
- first.AddTail(&last);
-
- // now go through the resulting list (so that the current
- // assignments are set last) if this device is assigned.
- if (nCurUser != -1)
- {
- pos = first.GetHeadPosition();
- while (pos != NULL)
- {
- DWORD dwMap = first.GetNext(pos);
- lpAcFor = AcForMap[dwMap];
-
- tracescope(tsa2, _T("Applying lpAcFor at AcForMap["));
- trace1(_T("0x%08x]...\n"), dwMap);
-
- if (lpAcFor == NULL)
- {
- etrace(_T("NULL lpAcFor, can't apply\n"));
- continue;
- }
-
- int nGenre = MAP2GENRE(dwMap);
- int nUser = MAP2USER(dwMap);
- LPCWSTR wszUserName = pUIGlobals->GetUserName(nUser);
-
- traceLONG(nGenre);
- traceLONG(nUser);
- traceWSTR(wszUserName);
-
- TraceActionFormat(_T("Final Device ActionFormat:"), *lpAcFor);
-
- for (DWORD j = 0; j < lpAcFor->dwNumActions; ++j)
- {
- if( lpAcFor->rgoAction[j].dwObjID == (DWORD)-1 || IsEqualGUID(lpAcFor->rgoAction[j].guidInstance, GUID_NULL))
- {
- lpAcFor->rgoAction[j].dwHow = DIAH_UNMAPPED;
- }
- else if( lpAcFor->rgoAction[j].dwHow &
- ( DIAH_USERCONFIG | DIAH_APPREQUESTED | DIAH_HWAPP | DIAH_HWDEFAULT | DIAH_DEFAULT ) )
- {
- lpAcFor->rgoAction[j].dwHow = DIAH_USERCONFIG;
- }
- else if(IsEqualGUID(didi.guidInstance,lpAcFor->rgoAction[j].guidInstance))
- {
- lpAcFor->rgoAction[j].dwHow = DIAH_USERCONFIG;
- }
- }
-
- HRESULT hr;
- hr = lpDID->SetActionMap(lpAcFor, wszUserName, DIDSAM_FORCESAVE|DIDSAM_DEFAULT);
-
- if (FAILED(hr))
- etrace1(_T("SetActionMap() failed, returning 0x%08x\n"), hr);
- else
- trace(_T("SetActionMap() succeeded\n"));
- }
- } // if (nCurUser != -1)
- else
- {
- // we're unassigned, set null
- trace(_T("Unassigning...\n"));
-
- // we need an acfor to unassign, so get one if don't have
- // one left over from what we just did
- if (!lpAcFor)
- lpAcFor = GetAcFor(0, 0);
-
- if (!lpAcFor)
- etrace(_T("Couldn't get an acfor for unassignment\n"));
-
- HRESULT hr;
- hr = lpDID->SetActionMap(lpAcFor, NULL, DIDSAM_NOUSER);
-
- if (FAILED(hr))
- etrace1(_T("SetActionMap() failed, returning 0x%08x\n"), hr);
- else
- trace(_T("SetActionMap() succeeded\n"));
- }
- }
-
- int CConfigWnd::GetNumUsers()
- {
- return m_uig.GetNumUserNames();
- }
-
- int CConfigWnd::GetCurUser(int nPage)
- {
- return GetElement(nPage).nCurUser;
- }
-