Input plugin: Start to scan keyboard

This commit is contained in:
zilmar 2020-06-23 17:17:46 +09:30
parent be939dca65
commit f78e292796
13 changed files with 730 additions and 19 deletions

View File

@ -0,0 +1,27 @@
#pragma once
#include <Common\stdtypes.h>
enum BtnType
{
BTNTYPE_UNASSIGNED = 0,
// Joystick
BTNTYPE_JOYBUTTON = 1,
BTNTYPE_JOYAXE = 2,
BTNTYPE_JOYPOV = 3,
BTNTYPE_JOYSLIDER = 4,
// Keyboard
BTNTYPE_KEYBUTTON = 5,
// Mouse
BTNTYPE_MOUSEBUTTON = 6,
BTNTYPE_MOUSEAXE = 7,
};
typedef struct
{
uint8_t Offset;
uint8_t AxisID;
BtnType BtnType;
} BUTTON;

View File

@ -0,0 +1,55 @@
#include "CProject64Input.h"
CProject64Input * g_InputPlugin = nullptr;
CProject64Input::CProject64Input(HINSTANCE hinst) :
m_hinst(hinst),
m_Scanning(false),
m_DisplayCtrlId(0)
{
memset(m_Controllers, 0, sizeof(m_Controllers));
}
CProject64Input::~CProject64Input()
{
}
void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo)
{
if (m_DirectInput.get() == NULL)
{
m_DirectInput.reset(new CDirectInput(m_hinst));
}
m_DirectInput->Initiate(ControlInfo);
}
void CProject64Input::StartScanDevices(int32_t DisplayCtrlId)
{
m_Scanning = true;
m_DisplayCtrlId = DisplayCtrlId;
}
void CProject64Input::EndScanDevices(void)
{
m_Scanning = false;
m_DisplayCtrlId = 0;
}
CDirectInput::ScanResult CProject64Input::ScanDevices(BUTTON & Button)
{
CDirectInput::ScanResult Result = CDirectInput::SCAN_FAILED;
if (m_DirectInput.get() != NULL)
{
Result = m_DirectInput->ScanDevices(Button);
}
return Result;
}
std::wstring CProject64Input::ButtonAssignment(BUTTON & Button)
{
if (m_DirectInput.get() != NULL)
{
return m_DirectInput->ButtonAssignment(Button);
}
return L"Unknown";
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "ControllerSpec1.1.h"
#include "DirectInput.h"
#include "N64Controller.h"
#include <memory>
class CProject64Input
{
public:
CProject64Input(HINSTANCE hinst);
~CProject64Input();
void InitiateControllers(CONTROL_INFO * ControlInfo);
void StartScanDevices(int32_t DisplayCtrlId);
void EndScanDevices(void);
CDirectInput::ScanResult ScanDevices(BUTTON & Button);
std::wstring ButtonAssignment(BUTTON & Button);
inline HINSTANCE hInst(void) const { return m_hinst; }
inline bool IsScanning(void) const { return m_Scanning; }
inline int32_t DisplayCtrlId(void) const { return m_DisplayCtrlId; }
inline N64CONTROLLER & Controllers(int32_t Controller) { return m_Controllers[Controller]; }
private:
CProject64Input();
CProject64Input(const CProject64Input&);
CProject64Input& operator=(const CProject64Input&);
N64CONTROLLER m_Controllers[4];
std::unique_ptr<CDirectInput> m_DirectInput;
HINSTANCE m_hinst;
bool m_Scanning;
int32_t m_DisplayCtrlId;
};
extern CProject64Input * g_InputPlugin;

View File

@ -0,0 +1,215 @@
#include "DirectInput.h"
#include <Common\StdString.h>
CDirectInput::CDirectInput(HINSTANCE hinst) :
m_hDirectInputDLL(nullptr),
m_pDIHandle(nullptr),
m_hinst(hinst),
m_hWnd(nullptr)
{
LoadConfig();
if (m_hDirectInputDLL == nullptr)
{
m_hDirectInputDLL = LoadLibrary(L"dinput8.dll");
}
if (m_hDirectInputDLL != nullptr)
{
typedef HRESULT(WINAPI *tylpGetDIHandle)(HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN);
tylpGetDIHandle lpGetDIHandle = (tylpGetDIHandle)GetProcAddress(m_hDirectInputDLL, "DirectInput8Create");
if (lpGetDIHandle != NULL)
{
HRESULT hr = lpGetDIHandle(m_hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_pDIHandle, NULL);
if (FAILED(hr))
{
return;
}
}
if (m_pDIHandle != nullptr)
{
m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY);
}
}
}
CDirectInput::~CDirectInput()
{
for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++)
{
if (itr->second.didHandle != nullptr)
{
itr->second.didHandle->Release();
itr->second.didHandle = NULL;
}
}
}
void CDirectInput::Initiate(CONTROL_INFO * ControlInfo)
{
m_hWnd = (HWND)ControlInfo->hwnd;
}
BOOL CDirectInput::stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
return ((CDirectInput *)pvRef)->EnumMakeDeviceList(lpddi);
}
BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi)
{
uint32_t DeviceType = GET_DIDEVICE_TYPE(lpddi->dwDevType);
if (DeviceType == DI8DEVTYPE_DEVICE)
{
// ignore generic devices
return DIENUM_CONTINUE;
}
DEVICE Device;
Device.didHandle = nullptr;
Device.dwDevType = lpddi->dwDevType;
Device.ProductName = stdstr().FromUTF16(lpddi->tszProductName);
Device.InstanceName = stdstr().FromUTF16(lpddi->tszInstanceName);
HRESULT hResult = m_pDIHandle->CreateDevice(lpddi->guidInstance, &Device.didHandle, NULL);
if (!SUCCEEDED(hResult))
{
return DIENUM_CONTINUE;
}
LPCDIDATAFORMAT ppDiDataFormat = NULL;
if (DeviceType == DI8DEVTYPE_KEYBOARD)
{
ppDiDataFormat = &c_dfDIKeyboard;
}
else if (DeviceType == DI8DEVTYPE_MOUSE)
{
ppDiDataFormat = &c_dfDIMouse2;
}
else
{
ppDiDataFormat = &c_dfDIJoystick;
}
hResult = Device.didHandle->SetDataFormat(ppDiDataFormat);
if (!SUCCEEDED(hResult))
{
Device.didHandle->Release();
return DIENUM_CONTINUE;
}
hResult = Device.didHandle->SetCooperativeLevel(m_hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
if (!SUCCEEDED(hResult))
{
Device.didHandle->Release();
return DIENUM_CONTINUE;
}
std::pair<DEVICE_MAP::iterator, bool> res = m_Devices.insert(DEVICE_MAP::value_type(lpddi->guidInstance, Device));
if (!res.second)
{
Device.didHandle->Release();
}
return DIENUM_CONTINUE;
}
CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button)
{
ScanResult Result = SCAN_FAILED;
for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++)
{
DEVICE &device = itr->second;
if (device.didHandle == nullptr)
{
continue;
}
if (FAILED(device.didHandle->Poll()))
{
device.didHandle->Acquire();
}
}
for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++)
{
DEVICE &device = itr->second;
if (device.didHandle == nullptr)
{
continue;
}
uint8_t DeviceType = LOBYTE(device.dwDevType);
if (DeviceType == DI8DEVTYPE_KEYBOARD)
{
Result = ScanKeyboard(device.didHandle, Button);
}
else if (DeviceType == DI8DEVTYPE_MOUSE)
{
//dwReturn = ScanMouse(&g_devList[i], lpdwCounter, pButton);
}
else
{
// dwReturn = ScanGamePad(&g_devList[i], lpdwCounter, pButton, i);
}
if (Result != SCAN_FAILED)
{
return Result;
}
}
return Result;
}
std::wstring CDirectInput::ButtonAssignment(BUTTON & Button)
{
if (Button.BtnType == BTNTYPE_KEYBUTTON)
{
DEVICE_MAP::iterator itr = m_Devices.find(GUID_SysKeyboard);
if (itr != m_Devices.end())
{
DIDEVICEOBJECTINSTANCE didoi;
didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
if (itr->second.didHandle->GetObjectInfo(&didoi, Button.Offset, DIPH_BYOFFSET) == DI_OK)
{
return didoi.tszName;
}
return L"Keyboard: ???";
}
}
else if (Button.BtnType == BTNTYPE_UNASSIGNED)
{
return L"";
}
return L"Unknown";
}
CDirectInput::ScanResult CDirectInput::ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton)
{
if (didHandle == nullptr)
{
return SCAN_FAILED;
}
uint8_t cKeys[256];
HRESULT hr = didHandle->GetDeviceState(sizeof(cKeys), cKeys);
if (FAILED(hr))
{
didHandle->Acquire();
return SCAN_FAILED;
}
for (size_t i = 0, n = sizeof(cKeys) / sizeof(cKeys[0]); i < n; i++)
{
if ((cKeys[i] & 0x80) == 0)
{
continue;
}
if (i == DIK_ESCAPE)
{
return SCAN_ESCAPE;
}
pButton.Offset = (uint8_t)i;
pButton.AxisID = 0;
pButton.BtnType = BTNTYPE_KEYBUTTON;
return SCAN_SUCCEED;
}
return SCAN_FAILED;
}
void CDirectInput::LoadConfig(void)
{
}

View File

@ -0,0 +1,59 @@
#pragma once
#include "ControllerSpec1.1.h"
#include "Button.h"
#define DIRECTINPUT_VERSION 0x0800
#include <Windows.h>
#include <dinput.h>
#include <string>
#include <map>
class CDirectInput
{
public:
enum ScanResult
{
SCAN_FAILED = 0x00,
SCAN_SUCCEED = 0x01,
SCAN_ESCAPE = 0x10,
};
CDirectInput(HINSTANCE hinst);
~CDirectInput();
void Initiate(CONTROL_INFO * ControlInfo);
ScanResult ScanDevices(BUTTON & Button);
std::wstring ButtonAssignment(BUTTON & Button);
private:
CDirectInput();
CDirectInput(const CDirectInput&);
CDirectInput& operator=(const CDirectInput&);
static BOOL CALLBACK stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi);
ScanResult ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton);
void LoadConfig(void);
typedef struct
{
LPDIRECTINPUTDEVICE8 didHandle;
uint32_t dwDevType;
std::string InstanceName;
std::string ProductName;
} DEVICE;
struct GUIDComparer
{
bool operator()(const GUID & Left, const GUID & Right) const
{
return memcmp(&Left, &Right, sizeof(Right)) < 0;
}
};
typedef std::map<GUID, DEVICE, GUIDComparer> DEVICE_MAP;
DEVICE_MAP m_Devices;
HMODULE m_hDirectInputDLL;
LPDIRECTINPUT8 m_pDIHandle;
HINSTANCE m_hinst;
HWND m_hWnd;
};

View File

@ -1,6 +1,8 @@
#include "InputConfigUI.h"
#include "CProject64Input.h"
#include "wtl.h"
#include "wtl-BitmapPicture.h"
#include "wtl-ScanButton.h"
#include <Common\stdtypes.h>
#include <Common\StdString.h>
#include "resource.h"
@ -8,43 +10,81 @@
class CControllerSettings :
public CPropertyPageImpl<CControllerSettings>
{
enum
{
DETECT_KEY_TIMER = 1
};
public:
enum { IDD = IDD_Controller };
BEGIN_MSG_MAP(CDebugSettings)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic)
CHAIN_MSG_MAP(CPropertyPageImpl<CControllerSettings>)
END_MSG_MAP()
CControllerSettings();
void SetControllerNumber(uint32_t ControllerNumber);
CControllerSettings(uint32_t ControllerNumber);
BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/);
HBRUSH OnCtlColorStatic(CDCHandle dc, CWindow wndStatic);
private:
std::wstring m_Title;
uint32_t m_ControllerNumber;
uint32_t m_ScanCount;
CBitmapPicture m_ControllerImg;
CScanButton ButtonUDPad, ButtonDDPad, ButtonLDPad, ButtonRDPad;
CScanButton ButtonCUp, ButtonCDown, ButtonCLeft, ButtonCRight;
CScanButton ButtonA, ButtonB;
};
CControllerSettings::CControllerSettings() :
m_ControllerNumber((uint32_t)-1)
{
}
void CControllerSettings::SetControllerNumber(uint32_t ControllerNumber)
CControllerSettings::CControllerSettings(uint32_t ControllerNumber) :
m_ControllerNumber(ControllerNumber),
m_ScanCount(0),
ButtonUDPad(g_InputPlugin->Controllers(ControllerNumber).U_DPAD, IDC_EDIT_DIGITIAL_UP, IDC_BTN_DIGITIAL_UP),
ButtonDDPad(g_InputPlugin->Controllers(ControllerNumber).D_DPAD, IDC_EDIT_DIGITIAL_DOWN, IDC_BTN_DIGITIAL_DOWN),
ButtonLDPad(g_InputPlugin->Controllers(ControllerNumber).L_DPAD, IDC_EDIT_DIGITIAL_LEFT, IDC_BTN_DIGITIAL_LEFT),
ButtonRDPad(g_InputPlugin->Controllers(ControllerNumber).R_DPAD, IDC_EDIT_DIGITIAL_RIGHT, IDC_BTN_DIGITIAL_RIGHT),
ButtonA(g_InputPlugin->Controllers(ControllerNumber).A_BUTTON, IDC_EDIT_BUTTON_A, IDC_BTN_BUTTON_A),
ButtonB(g_InputPlugin->Controllers(ControllerNumber).B_BUTTON, IDC_EDIT_BUTTON_B, IDC_BTN_BUTTON_B),
ButtonCUp(g_InputPlugin->Controllers(ControllerNumber).U_CBUTTON, IDC_EDIT_CBUTTON_UP, IDC_BTN_CBUTTON_UP),
ButtonCDown(g_InputPlugin->Controllers(ControllerNumber).D_CBUTTON, IDC_EDIT_CBUTTON_DOWN, IDC_BTN_CBUTTON_DOWN),
ButtonCLeft(g_InputPlugin->Controllers(ControllerNumber).L_CBUTTON, IDC_EDIT_CBUTTON_LEFT, IDC_BTN_CBUTTON_LEFT),
ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT)
{
m_Title = stdstr_f("Player %d", ControllerNumber + 1).ToUTF16();
SetTitle(m_Title.c_str());
m_ControllerNumber = ControllerNumber;
}
BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/)
{
m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER));
m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER));
ButtonUDPad.SubclassWindow(m_hWnd);
ButtonDDPad.SubclassWindow(m_hWnd);
ButtonLDPad.SubclassWindow(m_hWnd);
ButtonRDPad.SubclassWindow(m_hWnd);
ButtonA.SubclassWindow(m_hWnd);
ButtonB.SubclassWindow(m_hWnd);
ButtonCUp.SubclassWindow(m_hWnd);
ButtonCDown.SubclassWindow(m_hWnd);
ButtonCLeft.SubclassWindow(m_hWnd);
ButtonCRight.SubclassWindow(m_hWnd);
return TRUE;
}
HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic)
{
if (g_InputPlugin->IsScanning() && wndStatic.GetDlgCtrlID() == g_InputPlugin->DisplayCtrlId())
{
dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
return ::GetSysColorBrush(COLOR_HIGHLIGHT);
}
dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkColor(GetSysColor(COLOR_WINDOW));
return ::GetSysColorBrush(COLOR_WINDOW);
}
class CInputConfigUI:
public CPropertySheetImpl<CInputConfigUI>
{
@ -55,7 +95,7 @@ public:
void OnSheetInitialized();
private:
CControllerSettings m_pgController[4];
CControllerSettings m_pgController0, m_pgController1, m_pgController2, m_pgController3;
};
void ConfigInput(void * hParent)
@ -63,14 +103,17 @@ void ConfigInput(void * hParent)
CInputConfigUI().DoModal((HWND)hParent);
}
CInputConfigUI::CInputConfigUI()
CInputConfigUI::CInputConfigUI() :
m_pgController0(0),
m_pgController1(1),
m_pgController2(2),
m_pgController3(3)
{
m_psh.pszCaption = L"Configure Input";
for (size_t i = 0, n = sizeof(m_pgController) / sizeof(m_pgController[0]); i < n; i++)
{
m_pgController[i].SetControllerNumber(i);
AddPage(&m_pgController[i].m_psp);
}
AddPage(&m_pgController0.m_psp);
AddPage(&m_pgController1.m_psp);
AddPage(&m_pgController2.m_psp);
AddPage(&m_pgController3.m_psp);
}
CInputConfigUI::~CInputConfigUI()

View File

@ -11,6 +11,7 @@
#include "ControllerSpec1.1.h"
#include "InputConfigUI.h"
#include "Version.h"
#include "CProject64Input.h"
#include <stdio.h>
/******************************************************************
@ -121,8 +122,12 @@ EXPORT void CALL GetKeys(int32_t /*Control*/, BUTTONS * /*Keys*/)
the emulator to know how to handle each controller.
output: none
*******************************************************************/
EXPORT void CALL InitiateControllers(CONTROL_INFO * /*ControlInfo*/)
EXPORT void CALL InitiateControllers(CONTROL_INFO * ControlInfo)
{
if (g_InputPlugin != nullptr)
{
g_InputPlugin->InitiateControllers(ControlInfo);
}
}
/******************************************************************
@ -185,4 +190,20 @@ EXPORT void CALL WM_KeyUp(uint32_t /*wParam*/, uint32_t /*lParam*/)
EXPORT void CALL PluginLoaded(void)
{
}
#include <Windows.h>
extern "C" int WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID /*lpReserved*/)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
g_InputPlugin = new CProject64Input(hinst);
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
delete g_InputPlugin;
g_InputPlugin = NULL;
}
return TRUE;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "Button.h"
typedef struct
{
BUTTON U_DPAD;
BUTTON D_DPAD;
BUTTON L_DPAD;
BUTTON R_DPAD;
BUTTON A_BUTTON;
BUTTON B_BUTTON;
BUTTON U_CBUTTON;
BUTTON D_CBUTTON;
BUTTON L_CBUTTON;
BUTTON R_CBUTTON;
BUTTON START_BUTTON;
BUTTON Z_TRIG;
BUTTON R_TRIG;
BUTTON L_TRIG;
} N64CONTROLLER;

View File

@ -45,17 +45,35 @@
<PreBuildEvent>
<Command>"$(SolutionDir)Source\Script\UpdateVersion.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)Source\Project64-input\Version.h.in" "$(SolutionDir)Source\Project64-input\Version.h"</Command>
</PreBuildEvent>
<Link>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">dinput8.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ImageHasSafeExceptionHandlers>
</Link>
<Link>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">dinput8.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="DirectInput.cpp" />
<ClCompile Include="InputConfigUI.cpp" />
<ClCompile Include="InputMain.cpp" />
<ClCompile Include="CProject64Input.cpp" />
<ClCompile Include="wtl-BitmapPicture.cpp" />
<ClCompile Include="wtl-ScanButton.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Button.h" />
<ClInclude Include="N64Controller.h" />
<ClInclude Include="DirectInput.h" />
<ClInclude Include="InputConfigUI.h" />
<ClInclude Include="ControllerSpec1.1.h" />
<ClInclude Include="CProject64Input.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="wtl-BitmapPicture.h" />
<ClInclude Include="wtl-ScanButton.h" />
<ClInclude Include="wtl.h" />
</ItemGroup>
<ItemGroup>

View File

@ -24,6 +24,15 @@
<ClCompile Include="wtl-BitmapPicture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CProject64Input.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DirectInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wtl-ScanButton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControllerSpec1.1.h">
@ -41,6 +50,21 @@
<ClInclude Include="wtl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CProject64Input.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DirectInput.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wtl-ScanButton.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Button.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="N64Controller.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Version.h.in">

View File

@ -11,8 +11,8 @@
#define STRINGIZE2(s) #s
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_MAJOR 0
#define VERSION_MINOR 1
#define VERSION_REVISION 0
#define VERSION_BUILD 9999
#define GIT_VERSION ""

View File

@ -0,0 +1,156 @@
#include "wtl-ScanButton.h"
#include "CProject64Input.h"
#include <Common\StdString.h>
#include <time.h>
CScanButton::CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId) :
m_Button(Button),
m_DisplayCtrlId(DisplayCtrlId),
m_ScanBtnId(ScanBtnId),
m_ScanBtnProc(nullptr),
m_ScanCount(0),
m_ScanStart(0)
{
}
void CScanButton::SubclassWindow(CWindow Wnd)
{
m_DisplayCtrl = Wnd.GetDlgItem(m_DisplayCtrlId);
m_ScanBtn = Wnd.GetDlgItem(m_ScanBtnId);
m_ScanBtnThunk.Init((WNDPROC)ScanButtonProc, this);
m_ScanBtnProc = (WNDPROC)m_ScanBtn.SetWindowLongPtrW(GWLP_WNDPROC, (LONG_PTR)m_ScanBtnThunk.GetWNDPROC());
DisplayButton();
}
void CScanButton::DisplayButton(void)
{
m_DisplayCtrl.SetWindowText(g_InputPlugin->ButtonAssignment(m_Button).c_str());
}
void CScanButton::OnScan(void)
{
enum
{
SACN_INTERVAL = 20
};
m_ScanCount = 0;
time(&m_ScanStart);
g_InputPlugin->StartScanDevices(m_DisplayCtrlId);
m_DisplayCtrl.Invalidate();
m_ScanBtn.SetTimer(DETECT_KEY_TIMER, SACN_INTERVAL, NULL);
MakeOverlay();
}
void CScanButton::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == DETECT_KEY_TIMER)
{
bool Stop = false;
if (g_InputPlugin)
{
CDirectInput::ScanResult Result = g_InputPlugin->ScanDevices(m_Button);
if (Result == CDirectInput::SCAN_SUCCEED)
{
Stop = true;
DisplayButton();
}
}
if ((m_ScanCount % 30) == 0)
{
CWindow Dialog = m_ScanBtn.GetParent().GetParent();
time_t Now = time(nullptr);
if (10 - (Now - m_ScanStart) > 0)
{
Dialog.SetWindowText(stdstr_f("Configure Input: Press Key ... (%d seconds)", 10 - (Now - m_ScanStart)).ToUTF16().c_str());
}
else
{
Stop = true;
}
}
if (m_ScanCount > 500)
{
Stop = true;
}
else
{
m_ScanCount += 1;
}
if (Stop)
{
m_ScanBtn.KillTimer(DETECT_KEY_TIMER);
CWindow Dialog = m_ScanBtn.GetParent().GetParent();
Dialog.SetWindowText(L"Configure Input");
m_Overlay.DestroyWindow();
m_Overlay = NULL;
g_InputPlugin->EndScanDevices();
m_DisplayCtrl.Invalidate();
}
}
}
void CScanButton::MakeOverlay(void)
{
WNDCLASS wc = { 0 };
wc.lpfnWndProc = (WNDPROC)BlockerProc;
wc.hInstance = g_InputPlugin->hInst();
wc.lpszClassName = L"BlockerClass";
RegisterClass(&wc);
CWindow ControllerDlg = m_ScanBtn.GetParent().GetParent();
CRect size;
ControllerDlg.GetWindowRect(&size);
m_Overlay = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT, L"BlockerClass", L"Blocker", WS_POPUP, size.left, size.top, size.Width(), size.Height(), ControllerDlg, nullptr, g_InputPlugin->hInst(), NULL);
if (m_Overlay == NULL)
{
return;
}
m_Overlay.ShowWindow(SW_SHOWNOACTIVATE);
}
UINT_PTR CALLBACK CScanButton::ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CScanButton * _this = (CScanButton*)hWnd;
UINT_PTR uRet = 0;
if (uMsg == WM_LBUTTONUP)
{
POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
_this->m_ScanBtn.ClientToScreen(&ptCursor);
RECT rect = { 0 };
_this->m_ScanBtn.GetWindowRect(&rect);
if (PtInRect(&rect, ptCursor))
{
_this->OnScan();
}
}
else if (uMsg == WM_TIMER)
{
_this->OnTimer((UINT_PTR)wParam);
}
if (_this->m_ScanBtnProc != nullptr)
{
uRet = _this->m_ScanBtnProc(_this->m_ScanBtn, uMsg, wParam, lParam);
}
return uRet;
}
UINT_PTR CALLBACK CScanButton::BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CREATE)
{
return 0;
}
if (msg == WM_PAINT)
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "wtl.h"
#include "Button.h"
class CScanButton
{
enum
{
DETECT_KEY_TIMER = 1
};
public:
CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId);
void SubclassWindow(CWindow Wnd);
private:
CScanButton(void);
CScanButton(const CScanButton&);
CScanButton& operator=(const CScanButton&);
void DisplayButton(void);
void OnScan(void);
void OnTimer(UINT_PTR nIDEvent);
void MakeOverlay(void);
static UINT_PTR CALLBACK ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static UINT_PTR CALLBACK BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BUTTON & m_Button;
int32_t m_DisplayCtrlId, m_ScanBtnId;
CWindow m_DisplayCtrl, m_ScanBtn;
CWndProcThunk m_ScanBtnThunk;
WNDPROC m_ScanBtnProc;
uint32_t m_ScanCount;
time_t m_ScanStart;
CWindow m_Overlay;
};