mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-11 12:14:53 +08:00
Add drop down key selection support to Keyboard Manager UI (dev/build-features) (#2140)
* Added combobox * Formatted and removed unused code * Added drop down support for Edit Keyboard window * Reordered the displayed key list * Add shortcut stack panels and drop downs linked to detect shortcut * Add more selected item logic * Added complete dropdown support for edit shortcuts window * Added Flyout warning for incorrect drop down input * Tweaked warnings * Removed MainWindow code * Changed SelectedValue toSelectedIndex * Removed unnecessary assignments * Added a warning for two dropdowns and the first one is changed to an action key * Added function comments in cpp file * Fixed some comments * Fixed all allocation and out of scope issues * Fix most issues except reloading shortcuts * Fixed issue while reloading shortcuts * Fixed type cast warnings * Changed delete to delete[] * tweaked
This commit is contained in:
parent
fc7103f56e
commit
0417b6266a
@ -27,6 +27,37 @@ IInspectable getSiblingElement(IInspectable const& element)
|
|||||||
return parentElement.Children().GetAt(index + 1);
|
return parentElement.Children().GetAt(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to check if the key is a modifier key
|
||||||
|
bool IsModifierKey(DWORD key)
|
||||||
|
{
|
||||||
|
return (GetKeyType(key) != KeyType::Action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get the type of the key
|
||||||
|
KeyType GetKeyType(DWORD key)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case VK_LWIN:
|
||||||
|
case VK_RWIN:
|
||||||
|
return KeyType::Win;
|
||||||
|
case VK_CONTROL:
|
||||||
|
case VK_LCONTROL:
|
||||||
|
case VK_RCONTROL:
|
||||||
|
return KeyType::Ctrl;
|
||||||
|
case VK_MENU:
|
||||||
|
case VK_LMENU:
|
||||||
|
case VK_RMENU:
|
||||||
|
return KeyType::Alt;
|
||||||
|
case VK_SHIFT:
|
||||||
|
case VK_LSHIFT:
|
||||||
|
case VK_RSHIFT:
|
||||||
|
return KeyType::Shift;
|
||||||
|
default:
|
||||||
|
return KeyType::Action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function to return if the key is an extended key which requires the use of the extended key flag
|
// Function to return if the key is an extended key which requires the use of the extended key flag
|
||||||
bool isExtendedKey(DWORD key)
|
bool isExtendedKey(DWORD key)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,16 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <winrt/Windows.System.h>
|
#include <winrt/Windows.System.h>
|
||||||
|
|
||||||
|
// Type to distinguish between keys
|
||||||
|
enum class KeyType
|
||||||
|
{
|
||||||
|
Win,
|
||||||
|
Ctrl,
|
||||||
|
Alt,
|
||||||
|
Shift,
|
||||||
|
Action
|
||||||
|
};
|
||||||
|
|
||||||
// Function to split a wstring based on a delimiter and return a vector of split strings
|
// Function to split a wstring based on a delimiter and return a vector of split strings
|
||||||
std::vector<std::wstring> splitwstring(const std::wstring& input, wchar_t delimiter);
|
std::vector<std::wstring> splitwstring(const std::wstring& input, wchar_t delimiter);
|
||||||
|
|
||||||
@ -33,5 +43,11 @@ std::vector<T> convertWStringVectorToIntegerVector(const std::vector<std::wstrin
|
|||||||
return typeVector;
|
return typeVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to check if the key is a modifier key
|
||||||
|
bool IsModifierKey(DWORD key);
|
||||||
|
|
||||||
|
// Function to get the type of the key
|
||||||
|
KeyType GetKeyType(DWORD key);
|
||||||
|
|
||||||
// Function to return if the key is an extended key which requires the use of the extended key flag
|
// Function to return if the key is an extended key which requires the use of the extended key flag
|
||||||
bool isExtendedKey(DWORD key);
|
bool isExtendedKey(DWORD key);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "LayoutMap.h"
|
#include "LayoutMap.h"
|
||||||
|
|
||||||
|
// Function to return the unicode string name of the key
|
||||||
std::wstring LayoutMap::GetKeyName(DWORD key)
|
std::wstring LayoutMap::GetKeyName(DWORD key)
|
||||||
{
|
{
|
||||||
std::wstring result = L"Undefined";
|
std::wstring result = L"Undefined";
|
||||||
@ -15,30 +16,41 @@ std::wstring LayoutMap::GetKeyName(DWORD key)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update Keyboard layout according to input locale identifier
|
||||||
void LayoutMap::UpdateLayout()
|
void LayoutMap::UpdateLayout()
|
||||||
{
|
{
|
||||||
// Get keyboard layout for current thread
|
// Get keyboard layout for current thread
|
||||||
HKL layout = GetKeyboardLayout(0);
|
HKL layout = GetKeyboardLayout(0);
|
||||||
if (layout == previousLayout) {
|
if (layout == previousLayout)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
previousLayout = layout;
|
previousLayout = layout;
|
||||||
|
if (!isKeyCodeListGenerated)
|
||||||
|
{
|
||||||
|
unicodeKeys.clear();
|
||||||
|
unknownKeys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char btKeys[256] = { 0 };
|
unsigned char* btKeys = new unsigned char[256]{ 0 };
|
||||||
GetKeyboardState(btKeys);
|
GetKeyboardState(btKeys);
|
||||||
|
|
||||||
// Iterate over all the virtual key codes
|
// Iterate over all the virtual key codes. virtual key 0 is not used
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 1; i < 256; i++)
|
||||||
{
|
{
|
||||||
// Get the scan code from the virtual key code
|
// Get the scan code from the virtual key code
|
||||||
UINT scanCode = MapVirtualKeyExW(i, MAPVK_VK_TO_VSC, layout);
|
UINT scanCode = MapVirtualKeyExW(i, MAPVK_VK_TO_VSC, layout);
|
||||||
// Get the unicode representation from the virtual key code and scan code pair to
|
// Get the unicode representation from the virtual key code and scan code pair to
|
||||||
wchar_t szBuffer[3] = { 0 };
|
wchar_t szBuffer[3] = { 0 };
|
||||||
int result = ToUnicodeEx(i, scanCode, (BYTE*)btKeys, szBuffer, 3, 0, layout);
|
int result = ToUnicodeEx(i, scanCode, (BYTE*)btKeys, szBuffer, 3, 0, layout);
|
||||||
// If a representation is returned
|
// If a representation is returned
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
keyboardLayoutMap[i] = szBuffer;
|
keyboardLayoutMap[i] = szBuffer;
|
||||||
|
if (!isKeyCodeListGenerated)
|
||||||
|
{
|
||||||
|
unicodeKeys[i] = szBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -46,9 +58,15 @@ void LayoutMap::UpdateLayout()
|
|||||||
std::wstring vk = L"VK ";
|
std::wstring vk = L"VK ";
|
||||||
vk += std::to_wstring(i);
|
vk += std::to_wstring(i);
|
||||||
keyboardLayoutMap[i] = vk;
|
keyboardLayoutMap[i] = vk;
|
||||||
|
if (!isKeyCodeListGenerated)
|
||||||
|
{
|
||||||
|
unknownKeys[i] = vk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete[] btKeys;
|
||||||
|
|
||||||
// Override special key names like Shift, Ctrl etc because they don't have unicode mappings and key names like Enter, Space as they appear as "\r", " "
|
// Override special key names like Shift, Ctrl etc because they don't have unicode mappings and key names like Enter, Space as they appear as "\r", " "
|
||||||
// To do: localization
|
// To do: localization
|
||||||
keyboardLayoutMap[VK_CANCEL] = L"Break";
|
keyboardLayoutMap[VK_CANCEL] = L"Break";
|
||||||
@ -155,3 +173,104 @@ void LayoutMap::UpdateLayout()
|
|||||||
keyboardLayoutMap[0xFF] = L"Undefined";
|
keyboardLayoutMap[0xFF] = L"Undefined";
|
||||||
// To do: Add IME key names
|
// To do: Add IME key names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to return the list of key codes in the order for the drop down. It creates it if it doesn't exist
|
||||||
|
std::vector<DWORD> LayoutMap::GetKeyCodeList(const bool isShortcut)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(keyboardLayoutMap_mutex);
|
||||||
|
UpdateLayout();
|
||||||
|
std::vector<DWORD> keyCodes;
|
||||||
|
if (!isKeyCodeListGenerated)
|
||||||
|
{
|
||||||
|
// Add modifier keys
|
||||||
|
keyCodes.push_back(VK_LWIN);
|
||||||
|
keyCodes.push_back(VK_RWIN);
|
||||||
|
keyCodes.push_back(VK_CONTROL);
|
||||||
|
keyCodes.push_back(VK_LCONTROL);
|
||||||
|
keyCodes.push_back(VK_RCONTROL);
|
||||||
|
keyCodes.push_back(VK_MENU);
|
||||||
|
keyCodes.push_back(VK_LMENU);
|
||||||
|
keyCodes.push_back(VK_RMENU);
|
||||||
|
keyCodes.push_back(VK_SHIFT);
|
||||||
|
keyCodes.push_back(VK_LSHIFT);
|
||||||
|
keyCodes.push_back(VK_RSHIFT);
|
||||||
|
// Add character keys
|
||||||
|
for (auto& it : unicodeKeys)
|
||||||
|
{
|
||||||
|
// If it was not renamed with a special name
|
||||||
|
if (it.second == keyboardLayoutMap[it.first])
|
||||||
|
{
|
||||||
|
keyCodes.push_back(it.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add all other special keys
|
||||||
|
for (int i = 1; i < 256; i++)
|
||||||
|
{
|
||||||
|
// If it is not already been added (i.e. it was either a modifier or had a unicode representation)
|
||||||
|
if (std::find(keyCodes.begin(), keyCodes.end(), i) == keyCodes.end())
|
||||||
|
{
|
||||||
|
// If it is any other key but it is not named as VK #
|
||||||
|
auto it = unknownKeys.find(i);
|
||||||
|
if (it == unknownKeys.end())
|
||||||
|
{
|
||||||
|
keyCodes.push_back(i);
|
||||||
|
}
|
||||||
|
else if (unknownKeys[i] != keyboardLayoutMap[i])
|
||||||
|
{
|
||||||
|
keyCodes.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add unknown keys
|
||||||
|
for (auto& it : unknownKeys)
|
||||||
|
{
|
||||||
|
// If it was not renamed with a special name
|
||||||
|
if (it.second == keyboardLayoutMap[it.first])
|
||||||
|
{
|
||||||
|
keyCodes.push_back(it.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyCodeList = keyCodes;
|
||||||
|
isKeyCodeListGenerated = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keyCodes = keyCodeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is a key list for the shortcut control then we add a "None" key at the start
|
||||||
|
if (isShortcut)
|
||||||
|
{
|
||||||
|
keyCodes.insert(keyCodes.begin(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable> LayoutMap::GetKeyNameList(const bool isShortcut)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(keyboardLayoutMap_mutex);
|
||||||
|
UpdateLayout();
|
||||||
|
lock.unlock();
|
||||||
|
Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable> keyNames = single_threaded_vector<Windows::Foundation::IInspectable>();
|
||||||
|
std::vector<DWORD> keyCodes = GetKeyCodeList(isShortcut);
|
||||||
|
lock.lock();
|
||||||
|
// If it is a key list for the shortcut control then we add a "None" key at the start
|
||||||
|
if (isShortcut)
|
||||||
|
{
|
||||||
|
keyNames.Append(winrt::box_value(L"None"));
|
||||||
|
for (int i = 1; i < keyCodes.size(); i++)
|
||||||
|
{
|
||||||
|
keyNames.Append(winrt::box_value(keyboardLayoutMap[keyCodes[i]].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < keyCodes.size(); i++)
|
||||||
|
{
|
||||||
|
keyNames.Append(winrt::box_value(keyboardLayoutMap[keyCodes[i]].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyNames;
|
||||||
|
}
|
||||||
|
@ -5,16 +5,33 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
|
||||||
// Wrapper class to handle keyboard layout
|
// Wrapper class to handle keyboard layout
|
||||||
class LayoutMap
|
class LayoutMap
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Stores mappings for all the virtual key codes to the name of the key
|
// Stores mappings for all the virtual key codes to the name of the key
|
||||||
std::map<DWORD, std::wstring> keyboardLayoutMap;
|
|
||||||
std::mutex keyboardLayoutMap_mutex;
|
std::mutex keyboardLayoutMap_mutex;
|
||||||
|
|
||||||
|
// Stores the previous layout
|
||||||
HKL previousLayout = 0;
|
HKL previousLayout = 0;
|
||||||
|
|
||||||
|
// Stores the keys which have a unicode representation
|
||||||
|
std::map<DWORD, std::wstring> unicodeKeys;
|
||||||
|
|
||||||
|
// Stores the keys which do not have a name
|
||||||
|
std::map<DWORD, std::wstring> unknownKeys;
|
||||||
|
|
||||||
|
// Stores true if the fixed ordering key code list has already been set
|
||||||
|
bool isKeyCodeListGenerated = false;
|
||||||
|
|
||||||
|
// Stores a fixed order key code list for the drop down menus. It is kept fixed to change in ordering due to languages
|
||||||
|
std::vector<DWORD> keyCodeList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::map<DWORD, std::wstring> keyboardLayoutMap;
|
||||||
|
|
||||||
// Update Keyboard layout according to input locale identifier
|
// Update Keyboard layout according to input locale identifier
|
||||||
void UpdateLayout();
|
void UpdateLayout();
|
||||||
|
|
||||||
@ -26,4 +43,9 @@ public:
|
|||||||
// Function to return the unicode string name of the key
|
// Function to return the unicode string name of the key
|
||||||
std::wstring GetKeyName(DWORD key);
|
std::wstring GetKeyName(DWORD key);
|
||||||
|
|
||||||
|
// Function to return the list of key codes in the order for the drop down. It creates it if it doesn't exist
|
||||||
|
std::vector<DWORD> GetKeyCodeList(const bool isShortcut = false);
|
||||||
|
|
||||||
|
// Function to return the list of key name in the order for the drop down based on the key codes
|
||||||
|
Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable> GetKeyNameList(const bool isShortcut = false);
|
||||||
};
|
};
|
||||||
|
@ -391,26 +391,7 @@ void Shortcut::ResetKey(const DWORD& input, const bool& isWinBoth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to return the string representation of the shortcut
|
// Function to return a vector of hstring for each key in the display order
|
||||||
winrt::hstring Shortcut::ToHstring(LayoutMap& keyboardMap)
|
|
||||||
{
|
|
||||||
std::vector<winrt::hstring> keys = GetKeyVector(keyboardMap);
|
|
||||||
|
|
||||||
winrt::hstring output;
|
|
||||||
for (auto& key : keys)
|
|
||||||
{
|
|
||||||
output = output + key + winrt::to_hstring(L" ");
|
|
||||||
}
|
|
||||||
if (keys.size() > 1)
|
|
||||||
{
|
|
||||||
return winrt::hstring(output.c_str(), output.size() - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
||||||
{
|
{
|
||||||
std::vector<winrt::hstring> keys;
|
std::vector<winrt::hstring> keys;
|
||||||
@ -437,6 +418,43 @@ std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to return a vector of key codes in the display order
|
||||||
|
std::vector<DWORD> Shortcut::GetKeyCodes()
|
||||||
|
{
|
||||||
|
std::vector<DWORD> keys;
|
||||||
|
if (winKey != ModifierKey::Disabled)
|
||||||
|
{
|
||||||
|
keys.push_back(GetWinKey(ModifierKey::Left));
|
||||||
|
}
|
||||||
|
if (ctrlKey != ModifierKey::Disabled)
|
||||||
|
{
|
||||||
|
keys.push_back(GetCtrlKey());
|
||||||
|
}
|
||||||
|
if (altKey != ModifierKey::Disabled)
|
||||||
|
{
|
||||||
|
keys.push_back(GetAltKey());
|
||||||
|
}
|
||||||
|
if (shiftKey != ModifierKey::Disabled)
|
||||||
|
{
|
||||||
|
keys.push_back(GetShiftKey());
|
||||||
|
}
|
||||||
|
if (actionKey != NULL)
|
||||||
|
{
|
||||||
|
keys.push_back(actionKey);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set a shortcut from a vector of key codes
|
||||||
|
void Shortcut::SetKeyCodes(const std::vector<DWORD>& keys)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
for (int i = 0; i < keys.size(); i++)
|
||||||
|
{
|
||||||
|
SetKey(keys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function to check if all the modifiers in the shortcut have been pressed down
|
// Function to check if all the modifiers in the shortcut have been pressed down
|
||||||
bool Shortcut::CheckModifiersKeyboardState() const
|
bool Shortcut::CheckModifiersKeyboardState() const
|
||||||
{
|
{
|
||||||
@ -540,7 +558,7 @@ bool Shortcut::CheckModifiersKeyboardState() const
|
|||||||
bool Shortcut::IsKeyboardStateClearExceptShortcut() const
|
bool Shortcut::IsKeyboardStateClearExceptShortcut() const
|
||||||
{
|
{
|
||||||
// Iterate through all the virtual key codes - 0xFF is set to key down because of the Num Lock
|
// Iterate through all the virtual key codes - 0xFF is set to key down because of the Num Lock
|
||||||
for (int keyVal = 0; keyVal < 0xFF; keyVal++)
|
for (int keyVal = 1; keyVal < 0xFF; keyVal++)
|
||||||
{
|
{
|
||||||
// Skip mouse buttons. Keeping this could cause a remapping to fail if a mouse button is also pressed at the same time
|
// Skip mouse buttons. Keeping this could cause a remapping to fail if a mouse button is also pressed at the same time
|
||||||
if (keyVal == VK_LBUTTON || keyVal == VK_RBUTTON || keyVal == VK_MBUTTON || keyVal == VK_XBUTTON1 || keyVal == VK_XBUTTON2)
|
if (keyVal == VK_LBUTTON || keyVal == VK_RBUTTON || keyVal == VK_MBUTTON || keyVal == VK_XBUTTON1 || keyVal == VK_XBUTTON2)
|
||||||
|
@ -22,7 +22,6 @@ private:
|
|||||||
DWORD actionKey;
|
DWORD actionKey;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// By default create an empty shortcut
|
// By default create an empty shortcut
|
||||||
Shortcut() :
|
Shortcut() :
|
||||||
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
|
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
|
||||||
@ -136,12 +135,15 @@ public:
|
|||||||
// Function to reset the state of a shortcut key based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key.
|
// Function to reset the state of a shortcut key based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key.
|
||||||
void ResetKey(const DWORD& input, const bool& isWinBoth = false);
|
void ResetKey(const DWORD& input, const bool& isWinBoth = false);
|
||||||
|
|
||||||
// Function to return the string representation of the shortcut
|
// Function to return a vector of hstring for each key in the display order
|
||||||
winrt::hstring ToHstring(LayoutMap& keyboardMap);
|
|
||||||
|
|
||||||
// Function to return a vector of hstring for each key, in the same order as ToHstring()
|
|
||||||
std::vector<winrt::hstring> GetKeyVector(LayoutMap& keyboardMap) const;
|
std::vector<winrt::hstring> GetKeyVector(LayoutMap& keyboardMap) const;
|
||||||
|
|
||||||
|
// Function to return a vector of key codes in the display order
|
||||||
|
std::vector<DWORD> GetKeyCodes();
|
||||||
|
|
||||||
|
// Function to set a shortcut from a vector of key codes
|
||||||
|
void SetKeyCodes(const std::vector<DWORD>& keys);
|
||||||
|
|
||||||
// Function to check if all the modifiers in the shortcut have been pressed down
|
// Function to check if all the modifiers in the shortcut have been pressed down
|
||||||
bool CheckModifiersKeyboardState() const;
|
bool CheckModifiersKeyboardState() const;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "EditKeyboardWindow.h"
|
#include "EditKeyboardWindow.h"
|
||||||
#include "SingleKeyRemapControl.h"
|
#include "SingleKeyRemapControl.h"
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
@ -15,7 +16,6 @@ std::mutex editKeyboardWindowMutex;
|
|||||||
// Function to create the Edit Keyboard Window
|
// Function to create the Edit Keyboard Window
|
||||||
void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardManagerState)
|
void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardManagerState)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Window Registration
|
// Window Registration
|
||||||
const wchar_t szWindowClass[] = L"EditKeyboardWindow";
|
const wchar_t szWindowClass[] = L"EditKeyboardWindow";
|
||||||
if (!isEditKeyboardWindowRegistrationCompleted)
|
if (!isEditKeyboardWindowRegistrationCompleted)
|
||||||
@ -104,7 +104,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||||||
TextBlock keyRemapInfoHeader;
|
TextBlock keyRemapInfoHeader;
|
||||||
keyRemapInfoHeader.Text(winrt::to_hstring("Select the key you want to remap, original key, and it's new output when pressed, the new key"));
|
keyRemapInfoHeader.Text(winrt::to_hstring("Select the key you want to remap, original key, and it's new output when pressed, the new key"));
|
||||||
keyRemapInfoHeader.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
keyRemapInfoHeader.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
||||||
keyRemapInfoHeader.Margin({ 0, 0, 0, 10 });
|
keyRemapInfoHeader.Margin({ 10, 0, 0, 10 });
|
||||||
|
|
||||||
// Table to display the key remaps
|
// Table to display the key remaps
|
||||||
Windows::UI::Xaml::Controls::StackPanel keyRemapTable;
|
Windows::UI::Xaml::Controls::StackPanel keyRemapTable;
|
||||||
@ -143,14 +143,17 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||||||
SingleKeyRemapControl::EditKeyboardWindowHandle = _hWndEditKeyboardWindow;
|
SingleKeyRemapControl::EditKeyboardWindowHandle = _hWndEditKeyboardWindow;
|
||||||
// Store keyboard manager state
|
// Store keyboard manager state
|
||||||
SingleKeyRemapControl::keyboardManagerState = &keyboardManagerState;
|
SingleKeyRemapControl::keyboardManagerState = &keyboardManagerState;
|
||||||
|
KeyDropDownControl::keyboardManagerState = &keyboardManagerState;
|
||||||
// Clear the single key remap buffer
|
// Clear the single key remap buffer
|
||||||
SingleKeyRemapControl::singleKeyRemapBuffer.clear();
|
SingleKeyRemapControl::singleKeyRemapBuffer.clear();
|
||||||
|
// Vector to store dynamically allocated control objects to avoid early destruction
|
||||||
|
std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>> keyboardRemapControlObjects;
|
||||||
|
|
||||||
// Load existing remaps into UI
|
// Load existing remaps into UI
|
||||||
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyReMap_mutex);
|
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyReMap_mutex);
|
||||||
for (const auto& it : keyboardManagerState.singleKeyReMap)
|
for (const auto& it : keyboardManagerState.singleKeyReMap)
|
||||||
{
|
{
|
||||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, it.first, it.second);
|
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects, it.first, it.second);
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
@ -210,7 +213,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||||||
addRemapKey.Content(plusSymbol);
|
addRemapKey.Content(plusSymbol);
|
||||||
addRemapKey.Margin({ 10 });
|
addRemapKey.Margin({ 10 });
|
||||||
addRemapKey.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
addRemapKey.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable);
|
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
||||||
});
|
});
|
||||||
|
|
||||||
xamlContainer.Children().Append(header);
|
xamlContainer.Children().Append(header);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "EditShortcutsWindow.h"
|
#include "EditShortcutsWindow.h"
|
||||||
#include "ShortcutControl.h"
|
#include "ShortcutControl.h"
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
@ -133,14 +134,17 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
ShortcutControl::EditShortcutsWindowHandle = _hWndEditShortcutsWindow;
|
ShortcutControl::EditShortcutsWindowHandle = _hWndEditShortcutsWindow;
|
||||||
// Store keyboard manager state
|
// Store keyboard manager state
|
||||||
ShortcutControl::keyboardManagerState = &keyboardManagerState;
|
ShortcutControl::keyboardManagerState = &keyboardManagerState;
|
||||||
|
KeyDropDownControl::keyboardManagerState = &keyboardManagerState;
|
||||||
// Clear the shortcut remap buffer
|
// Clear the shortcut remap buffer
|
||||||
ShortcutControl::shortcutRemapBuffer.clear();
|
ShortcutControl::shortcutRemapBuffer.clear();
|
||||||
|
// Vector to store dynamically allocated control objects to avoid early destruction
|
||||||
|
std::vector<std::vector<std::unique_ptr<ShortcutControl>>> keyboardRemapControlObjects;
|
||||||
|
|
||||||
// Load existing shortcuts into UI
|
// Load existing shortcuts into UI
|
||||||
std::unique_lock<std::mutex> lock(keyboardManagerState.osLevelShortcutReMap_mutex);
|
std::unique_lock<std::mutex> lock(keyboardManagerState.osLevelShortcutReMap_mutex);
|
||||||
for (const auto& it : keyboardManagerState.osLevelShortcutReMap)
|
for (const auto& it : keyboardManagerState.osLevelShortcutReMap)
|
||||||
{
|
{
|
||||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, it.first, it.second.targetShortcut);
|
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects, it.first, it.second.targetShortcut);
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
@ -158,7 +162,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
Shortcut originalShortcut = ShortcutControl::shortcutRemapBuffer[i][0];
|
Shortcut originalShortcut = ShortcutControl::shortcutRemapBuffer[i][0];
|
||||||
Shortcut newShortcut = ShortcutControl::shortcutRemapBuffer[i][1];
|
Shortcut newShortcut = ShortcutControl::shortcutRemapBuffer[i][1];
|
||||||
|
|
||||||
if (originalShortcut.IsValidShortcut() && originalShortcut.IsValidShortcut())
|
if (originalShortcut.IsValidShortcut() && newShortcut.IsValidShortcut())
|
||||||
{
|
{
|
||||||
bool result = keyboardManagerState.AddOSLevelShortcut(originalShortcut, newShortcut);
|
bool result = keyboardManagerState.AddOSLevelShortcut(originalShortcut, newShortcut);
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -197,7 +201,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
addShortcut.Content(plusSymbol);
|
addShortcut.Content(plusSymbol);
|
||||||
addShortcut.Margin({ 10 });
|
addShortcut.Margin({ 10 });
|
||||||
addShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
addShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable);
|
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
||||||
});
|
});
|
||||||
|
|
||||||
xamlContainer.Children().Append(header);
|
xamlContainer.Children().Append(header);
|
||||||
|
113
src/modules/keyboardmanager/ui/KeyDropDownControl.cpp
Normal file
113
src/modules/keyboardmanager/ui/KeyDropDownControl.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
|
// Initialized to null
|
||||||
|
KeyboardManagerState* KeyDropDownControl::keyboardManagerState = nullptr;
|
||||||
|
|
||||||
|
// Function to set properties apart from the SelectionChanged event handler
|
||||||
|
void KeyDropDownControl::SetDefaultProperties(bool isShortcut)
|
||||||
|
{
|
||||||
|
dropDown.Width(100);
|
||||||
|
dropDown.MaxDropDownHeight(200);
|
||||||
|
// Initialise layout attribute
|
||||||
|
previousLayout = GetKeyboardLayout(0);
|
||||||
|
keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(isShortcut);
|
||||||
|
dropDown.ItemsSource(keyboardManagerState->keyboardMap.GetKeyNameList(isShortcut));
|
||||||
|
// drop down open handler - to reload the items with the latest layout
|
||||||
|
dropDown.DropDownOpened([&, isShortcut](IInspectable const& sender, auto args) {
|
||||||
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
|
CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to check if the layout has changed and accordingly update the drop down list
|
||||||
|
void KeyDropDownControl::CheckAndUpdateKeyboardLayout(ComboBox currentDropDown, bool isShortcut)
|
||||||
|
{
|
||||||
|
// Get keyboard layout for current thread
|
||||||
|
HKL layout = GetKeyboardLayout(0);
|
||||||
|
|
||||||
|
// Check if the layout has changed
|
||||||
|
if (previousLayout != layout)
|
||||||
|
{
|
||||||
|
keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(isShortcut);
|
||||||
|
currentDropDown.ItemsSource(keyboardManagerState->keyboardMap.GetKeyNameList(isShortcut));
|
||||||
|
previousLayout = layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set the selected index of the drop down
|
||||||
|
void KeyDropDownControl::SetSelectedIndex(int32_t index)
|
||||||
|
{
|
||||||
|
dropDown.SelectedIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to return the combo box element of the drop down
|
||||||
|
ComboBox KeyDropDownControl::GetComboBox()
|
||||||
|
{
|
||||||
|
return dropDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to add a drop down to the shortcut stack panel
|
||||||
|
void KeyDropDownControl::AddDropDown(StackPanel parent, const size_t rowIndex, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects)
|
||||||
|
{
|
||||||
|
keyDropDownControlObjects.push_back(std::move(std::unique_ptr<KeyDropDownControl>(new KeyDropDownControl(rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, parent))));
|
||||||
|
// Flyout to display the warning on the drop down element
|
||||||
|
Flyout warningFlyout;
|
||||||
|
TextBlock warningMessage;
|
||||||
|
warningFlyout.Content(warningMessage);
|
||||||
|
parent.Children().Append(keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->GetComboBox());
|
||||||
|
parent.UpdateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get the list of key codes from the shortcut combo box stack panel
|
||||||
|
std::vector<DWORD> KeyDropDownControl::GetKeysFromStackPanel(StackPanel parent)
|
||||||
|
{
|
||||||
|
std::vector<DWORD> keys;
|
||||||
|
std::vector<DWORD> keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(true);
|
||||||
|
for (int i = 0; i < (int)parent.Children().Size(); i++)
|
||||||
|
{
|
||||||
|
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||||
|
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||||
|
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex)
|
||||||
|
{
|
||||||
|
// If None is not the selected key
|
||||||
|
if (keyCodeList[selectedKeyIndex] != 0)
|
||||||
|
{
|
||||||
|
keys.push_back(keyCodeList[selectedKeyIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to check if a modifier has been repeated in the previous drop downs
|
||||||
|
bool KeyDropDownControl::CheckRepeatedModifier(StackPanel parent, uint32_t dropDownIndex, int selectedKeyIndex, const std::vector<DWORD>& keyCodeList)
|
||||||
|
{
|
||||||
|
// check if modifier has already been added before in a previous drop down
|
||||||
|
std::vector<DWORD> currentKeys = GetKeysFromStackPanel(parent);
|
||||||
|
bool matchPreviousModifier = false;
|
||||||
|
for (int i = 0; i < currentKeys.size(); i++)
|
||||||
|
{
|
||||||
|
// Skip the current drop down
|
||||||
|
if (i != dropDownIndex)
|
||||||
|
{
|
||||||
|
// If the key type for the newly added key matches any of the existing keys in the shortcut
|
||||||
|
if (GetKeyType(keyCodeList[selectedKeyIndex]) == GetKeyType(currentKeys[i]))
|
||||||
|
{
|
||||||
|
matchPreviousModifier = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchPreviousModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set the flyout warning message
|
||||||
|
void KeyDropDownControl::SetDropDownError(ComboBox dropDown, TextBlock messageBlock, hstring message)
|
||||||
|
{
|
||||||
|
messageBlock.Text(message);
|
||||||
|
dropDown.ContextFlyout().ShowAttachedFlyout((FrameworkElement)dropDown);
|
||||||
|
dropDown.SelectedIndex(-1);
|
||||||
|
}
|
190
src/modules/keyboardmanager/ui/KeyDropDownControl.h
Normal file
190
src/modules/keyboardmanager/ui/KeyDropDownControl.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||||
|
|
||||||
|
// Wrapper class for the key drop down menu
|
||||||
|
class KeyDropDownControl
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Stores the drop down combo box
|
||||||
|
ComboBox dropDown;
|
||||||
|
// Stores the previous layout
|
||||||
|
HKL previousLayout = 0;
|
||||||
|
// Stores the key code list
|
||||||
|
std::vector<DWORD> keyCodeList;
|
||||||
|
|
||||||
|
// Function to set properties apart from the SelectionChanged event handler
|
||||||
|
void SetDefaultProperties(bool isShortcut);
|
||||||
|
|
||||||
|
// Function to check if the layout has changed and accordingly update the drop down list
|
||||||
|
void CheckAndUpdateKeyboardLayout(ComboBox currentDropDown, bool isShortcut);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Pointer to the keyboard manager state
|
||||||
|
static KeyboardManagerState* keyboardManagerState;
|
||||||
|
|
||||||
|
// Constructor for single key drop down
|
||||||
|
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
||||||
|
{
|
||||||
|
SetDefaultProperties(false);
|
||||||
|
dropDown.SelectionChanged([&, rowIndex, colIndex](IInspectable const& sender, SelectionChangedEventArgs const& args) {
|
||||||
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
|
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||||
|
|
||||||
|
// Check if the element was not found or the index exceeds the known keys
|
||||||
|
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex)
|
||||||
|
{
|
||||||
|
singleKeyRemapBuffer[rowIndex][colIndex] = keyCodeList[selectedKeyIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reset to null if the key is not found
|
||||||
|
singleKeyRemapBuffer[rowIndex][colIndex] = NULL;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor for shortcut drop down
|
||||||
|
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, StackPanel parent)
|
||||||
|
{
|
||||||
|
SetDefaultProperties(true);
|
||||||
|
Flyout warningFlyout;
|
||||||
|
TextBlock warningMessage;
|
||||||
|
warningFlyout.Content(warningMessage);
|
||||||
|
dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout);
|
||||||
|
|
||||||
|
// drop down selection handler
|
||||||
|
dropDown.SelectionChanged([&, rowIndex, colIndex, parent, warningMessage](IInspectable const& sender, SelectionChangedEventArgs const&) {
|
||||||
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
|
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||||
|
uint32_t dropDownIndex = -1;
|
||||||
|
bool dropDownFound = parent.Children().IndexOf(currentDropDown, dropDownIndex);
|
||||||
|
|
||||||
|
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex && dropDownFound)
|
||||||
|
{
|
||||||
|
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen
|
||||||
|
if (parent.Children().Size() == 1 && !IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||||
|
}
|
||||||
|
// If it is the last drop down
|
||||||
|
else if (dropDownIndex == parent.Children().Size() - 1)
|
||||||
|
{
|
||||||
|
// If last drop down and a modifier is selected: add a new drop down (max of 5 drop downs should be enforced)
|
||||||
|
if (IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() < 5)
|
||||||
|
{
|
||||||
|
// If it matched any of the previous modifiers then reset that drop down
|
||||||
|
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||||
|
}
|
||||||
|
// If not, add a new drop down
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddDropDown(parent, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If last drop down and a modifier is selected but there are already 5 drop downs: warn the user
|
||||||
|
else if (IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() >= 5)
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||||
|
}
|
||||||
|
// If None is selected but it's the last index: warn
|
||||||
|
else if (keyCodeList[selectedKeyIndex] == 0)
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||||
|
}
|
||||||
|
// If none of the above, then the action key will be set
|
||||||
|
}
|
||||||
|
// If it is the not the last drop down
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||||
|
{
|
||||||
|
// If it matched any of the previous modifiers then reset that drop down
|
||||||
|
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||||
|
}
|
||||||
|
// If not, the modifier key will be set
|
||||||
|
}
|
||||||
|
// If None is selected and there are more than 2 drop downs
|
||||||
|
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() > 2)
|
||||||
|
{
|
||||||
|
// delete drop down
|
||||||
|
parent.Children().RemoveAt(dropDownIndex);
|
||||||
|
// delete drop down control object from the vector so that it can be destructed
|
||||||
|
keyDropDownControlObjects.erase(keyDropDownControlObjects.begin() + dropDownIndex);
|
||||||
|
parent.UpdateLayout();
|
||||||
|
}
|
||||||
|
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() <= 2)
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must have atleast 2 keys");
|
||||||
|
}
|
||||||
|
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key
|
||||||
|
else if (dropDownIndex != 0)
|
||||||
|
{
|
||||||
|
bool isClear = true;
|
||||||
|
for (int i = dropDownIndex + 1; i < (int)parent.Children().Size(); i++)
|
||||||
|
{
|
||||||
|
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||||
|
if (currentDropDown.SelectedIndex() != -1)
|
||||||
|
{
|
||||||
|
isClear = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClear)
|
||||||
|
{
|
||||||
|
// remove all the drop down
|
||||||
|
int elementsToBeRemoved = parent.Children().Size() - dropDownIndex - 1;
|
||||||
|
for (int i = 0; i < elementsToBeRemoved; i++)
|
||||||
|
{
|
||||||
|
parent.Children().RemoveAtEnd();
|
||||||
|
}
|
||||||
|
parent.UpdateLayout();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot have more than one action key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there an action key is chosen on the first drop down and there are more than one drop down menus
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// warn and reset the drop down
|
||||||
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the buffer based on the new selected drop down items
|
||||||
|
shortcutRemapBuffer[rowIndex][colIndex].SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set the selected index of the drop down
|
||||||
|
void SetSelectedIndex(int32_t index);
|
||||||
|
|
||||||
|
// Function to return the combo box element of the drop down
|
||||||
|
ComboBox GetComboBox();
|
||||||
|
|
||||||
|
// Function to add a drop down to the shortcut stack panel
|
||||||
|
static void AddDropDown(StackPanel parent, const size_t rowIndex, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects);
|
||||||
|
|
||||||
|
// Function to get the list of key codes from the shortcut combo box stack panel
|
||||||
|
std::vector<DWORD> GetKeysFromStackPanel(StackPanel parent);
|
||||||
|
|
||||||
|
// Function to check if a modifier has been repeated in the previous drop downs
|
||||||
|
bool CheckRepeatedModifier(StackPanel parent, uint32_t dropDownIndex, int selectedKeyIndex, const std::vector<DWORD>& keyCodeList);
|
||||||
|
|
||||||
|
// Function to set the flyout warning message
|
||||||
|
void SetDropDownError(ComboBox dropDown, TextBlock messageBlock, hstring message);
|
||||||
|
};
|
@ -98,7 +98,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="EditKeyboardWindow.cpp" />
|
<ClCompile Include="EditKeyboardWindow.cpp" />
|
||||||
<ClCompile Include="EditShortcutsWindow.cpp" />
|
<ClCompile Include="EditShortcutsWindow.cpp" />
|
||||||
<ClCompile Include="MainWindow.cpp" />
|
<ClCompile Include="KeyDropDownControl.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
@ -109,8 +109,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="EditKeyboardWindow.h" />
|
<ClInclude Include="EditKeyboardWindow.h" />
|
||||||
<ClInclude Include="EditShortcutsWindow.h" />
|
<ClInclude Include="EditShortcutsWindow.h" />
|
||||||
|
<ClInclude Include="KeyDropDownControl.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="MainWindow.h" />
|
|
||||||
<ClInclude Include="ShortcutControl.h" />
|
<ClInclude Include="ShortcutControl.h" />
|
||||||
<ClInclude Include="SingleKeyRemapControl.h" />
|
<ClInclude Include="SingleKeyRemapControl.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="MainWindow.cpp" />
|
|
||||||
<ClCompile Include="EditKeyboardWindow.cpp" />
|
<ClCompile Include="EditKeyboardWindow.cpp" />
|
||||||
<ClCompile Include="EditShortcutsWindow.cpp" />
|
<ClCompile Include="EditShortcutsWindow.cpp" />
|
||||||
<ClCompile Include="ShortcutControl.cpp" />
|
<ClCompile Include="ShortcutControl.cpp" />
|
||||||
<ClCompile Include="pch.cpp" />
|
<ClCompile Include="pch.cpp" />
|
||||||
<ClCompile Include="SingleKeyRemapControl.cpp" />
|
<ClCompile Include="SingleKeyRemapControl.cpp" />
|
||||||
|
<ClCompile Include="KeyDropDownControl.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="MainWindow.h" />
|
|
||||||
<ClInclude Include="EditKeyboardWindow.h" />
|
<ClInclude Include="EditKeyboardWindow.h" />
|
||||||
<ClInclude Include="EditShortcutsWindow.h" />
|
<ClInclude Include="EditShortcutsWindow.h" />
|
||||||
<ClInclude Include="ShortcutControl.h" />
|
<ClInclude Include="ShortcutControl.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="SingleKeyRemapControl.h" />
|
<ClInclude Include="SingleKeyRemapControl.h" />
|
||||||
|
<ClInclude Include="KeyDropDownControl.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
@ -1,150 +0,0 @@
|
|||||||
#include "pch.h"
|
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "EditKeyboardWindow.h"
|
|
||||||
#include "EditShortcutsWindow.h"
|
|
||||||
|
|
||||||
HWND _hWndMain;
|
|
||||||
HINSTANCE _hInstance;
|
|
||||||
// This Hwnd will be the window handler for the Xaml Island: A child window that contains Xaml.
|
|
||||||
HWND hWndXamlIslandMain = nullptr;
|
|
||||||
// This variable is used to check if window registration has been done to avoid repeated registration leading to an error.
|
|
||||||
bool isMainWindowRegistrationCompleted = false;
|
|
||||||
|
|
||||||
// Function to create the Main Window
|
|
||||||
void createMainWindow(HINSTANCE hInstance, KeyboardManagerState& keyboardManagerState)
|
|
||||||
{
|
|
||||||
_hInstance = hInstance;
|
|
||||||
|
|
||||||
// Window Registration
|
|
||||||
const wchar_t szWindowClass[] = L"MainWindowClass";
|
|
||||||
if (!isMainWindowRegistrationCompleted)
|
|
||||||
{
|
|
||||||
WNDCLASSEX windowClass = {};
|
|
||||||
windowClass.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
windowClass.lpfnWndProc = MainWindowProc;
|
|
||||||
windowClass.hInstance = hInstance;
|
|
||||||
windowClass.lpszClassName = szWindowClass;
|
|
||||||
windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
||||||
windowClass.hIconSm = LoadIcon(windowClass.hInstance, IDI_APPLICATION);
|
|
||||||
if (RegisterClassEx(&windowClass) == NULL)
|
|
||||||
{
|
|
||||||
MessageBox(NULL, L"Windows registration failed!", L"Error", NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isMainWindowRegistrationCompleted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Window Creation
|
|
||||||
_hWndMain = CreateWindow(
|
|
||||||
szWindowClass,
|
|
||||||
L"Keyboard Manager Settings",
|
|
||||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
hInstance,
|
|
||||||
NULL);
|
|
||||||
if (_hWndMain == NULL)
|
|
||||||
{
|
|
||||||
MessageBox(NULL, L"Call to CreateWindow failed!", L"Error", NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//XAML Island section
|
|
||||||
// This DesktopWindowXamlSource is the object that enables a non-UWP desktop application
|
|
||||||
// to host UWP controls in any UI element that is associated with a window handle (HWND).
|
|
||||||
DesktopWindowXamlSource desktopSource;
|
|
||||||
// Get handle to corewindow
|
|
||||||
auto interop = desktopSource.as<IDesktopWindowXamlSourceNative>();
|
|
||||||
// Parent the DesktopWindowXamlSource object to current window
|
|
||||||
check_hresult(interop->AttachToWindow(_hWndMain));
|
|
||||||
|
|
||||||
// Get the new child window's hwnd
|
|
||||||
interop->get_WindowHandle(&hWndXamlIslandMain);
|
|
||||||
// Update the xaml island window size becuase initially is 0,0
|
|
||||||
SetWindowPos(hWndXamlIslandMain, 0, 0, 0, 800, 800, SWP_SHOWWINDOW);
|
|
||||||
|
|
||||||
//Creating the Xaml content
|
|
||||||
Windows::UI::Xaml::Controls::StackPanel xamlContainer;
|
|
||||||
xamlContainer.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
|
||||||
|
|
||||||
Windows::UI::Xaml::Controls::StackPanel keyRow;
|
|
||||||
keyRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
|
||||||
keyRow.Spacing(10);
|
|
||||||
keyRow.Margin({ 10 });
|
|
||||||
|
|
||||||
Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable> keyNames{ single_threaded_vector<Windows::Foundation::IInspectable>(
|
|
||||||
{ winrt::box_value(L"Alt"),
|
|
||||||
winrt::box_value(L"Delete"),
|
|
||||||
winrt::box_value(L"LAlt"),
|
|
||||||
winrt::box_value(L"LWin"),
|
|
||||||
winrt::box_value(L"Shift"),
|
|
||||||
winrt::box_value(L"NumLock"),
|
|
||||||
winrt::box_value(L"LCtrl") }) };
|
|
||||||
Windows::UI::Xaml::Controls::ComboBox cb;
|
|
||||||
cb.IsEditable(true);
|
|
||||||
cb.Width(200);
|
|
||||||
cb.ItemsSource(keyNames);
|
|
||||||
|
|
||||||
Windows::UI::Xaml::Controls::Button bt;
|
|
||||||
bt.Content(winrt::box_value(winrt::to_hstring("Edit Keyboard")));
|
|
||||||
bt.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
|
||||||
std::thread th(createEditKeyboardWindow, _hInstance, std::ref(keyboardManagerState));
|
|
||||||
th.join();
|
|
||||||
});
|
|
||||||
|
|
||||||
Windows::UI::Xaml::Controls::Button bt2;
|
|
||||||
bt2.Content(winrt::box_value(winrt::to_hstring("Edit Shortcuts")));
|
|
||||||
bt2.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
|
||||||
std::thread th(createEditShortcutsWindow, _hInstance, std::ref(keyboardManagerState));
|
|
||||||
th.join();
|
|
||||||
});
|
|
||||||
|
|
||||||
keyRow.Children().Append(cb);
|
|
||||||
keyRow.Children().Append(bt);
|
|
||||||
keyRow.Children().Append(bt2);
|
|
||||||
|
|
||||||
xamlContainer.Children().Append(keyRow);
|
|
||||||
xamlContainer.UpdateLayout();
|
|
||||||
desktopSource.Content(xamlContainer);
|
|
||||||
//End XAML Island section
|
|
||||||
if (_hWndMain)
|
|
||||||
{
|
|
||||||
ShowWindow(_hWndMain, SW_SHOW);
|
|
||||||
UpdateWindow(_hWndMain);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Message loop:
|
|
||||||
MSG msg = {};
|
|
||||||
while (GetMessage(&msg, NULL, 0, 0))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
desktopSource.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
RECT rcClient;
|
|
||||||
|
|
||||||
switch (messageCode)
|
|
||||||
{
|
|
||||||
case WM_PAINT:
|
|
||||||
GetClientRect(hWnd, &rcClient);
|
|
||||||
SetWindowPos(hWndXamlIslandMain, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
|
|
||||||
break;
|
|
||||||
case WM_DESTROY:
|
|
||||||
PostQuitMessage(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return DefWindowProc(hWnd, messageCode, wParam, lParam);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
|
||||||
|
|
||||||
// Function to create the Main Window
|
|
||||||
__declspec(dllexport) void createMainWindow(HINSTANCE hInstance, KeyboardManagerState& keyboardManagerState);
|
|
||||||
LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM);
|
|
@ -1,5 +1,6 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "ShortcutControl.h"
|
#include "ShortcutControl.h"
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
//Both static members are initialized to null
|
//Both static members are initialized to null
|
||||||
HWND ShortcutControl::EditShortcutsWindowHandle = nullptr;
|
HWND ShortcutControl::EditShortcutsWindowHandle = nullptr;
|
||||||
@ -8,7 +9,7 @@ KeyboardManagerState* ShortcutControl::keyboardManagerState = nullptr;
|
|||||||
std::vector<std::vector<Shortcut>> ShortcutControl::shortcutRemapBuffer;
|
std::vector<std::vector<Shortcut>> ShortcutControl::shortcutRemapBuffer;
|
||||||
|
|
||||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||||
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, Shortcut originalKeys, Shortcut newKeys)
|
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys, Shortcut newKeys)
|
||||||
{
|
{
|
||||||
// Parent element for the row
|
// Parent element for the row
|
||||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||||
@ -16,27 +17,17 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, Shortcut orig
|
|||||||
tableRow.Spacing(100);
|
tableRow.Spacing(100);
|
||||||
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||||
|
|
||||||
|
// Create new ShortcutControl objects dynamically so that we does not get destructed
|
||||||
|
std::vector<std::unique_ptr<ShortcutControl>> newrow;
|
||||||
|
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(shortcutRemapBuffer.size(), 0))));
|
||||||
|
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(shortcutRemapBuffer.size(), 1))));
|
||||||
|
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||||
// ShortcutControl for the original shortcut
|
// ShortcutControl for the original shortcut
|
||||||
ShortcutControl originalSC(shortcutRemapBuffer.size(), 0);
|
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl());
|
||||||
tableRow.Children().Append(originalSC.getShortcutControl());
|
|
||||||
|
|
||||||
// ShortcutControl for the new shortcut
|
// ShortcutControl for the new shortcut
|
||||||
ShortcutControl newSC(shortcutRemapBuffer.size(), 1);
|
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl());
|
||||||
tableRow.Children().Append(newSC.getShortcutControl());
|
|
||||||
|
|
||||||
// Set the shortcut text if the two vectors are not empty (i.e. default args)
|
|
||||||
if (!originalKeys.IsEmpty() && !newKeys.IsEmpty())
|
|
||||||
{
|
|
||||||
shortcutRemapBuffer.push_back(std::vector<Shortcut>{ originalKeys, newKeys });
|
|
||||||
originalSC.shortcutText.Text(originalKeys.ToHstring(keyboardManagerState->keyboardMap));
|
|
||||||
newSC.shortcutText.Text(newKeys.ToHstring(keyboardManagerState->keyboardMap));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Initialize both shortcuts as empty shortcuts
|
|
||||||
shortcutRemapBuffer.push_back(std::vector<Shortcut>{ Shortcut(), Shortcut() });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Delete row button
|
// Delete row button
|
||||||
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
||||||
FontIcon deleteSymbol;
|
FontIcon deleteSymbol;
|
||||||
@ -50,9 +41,57 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, Shortcut orig
|
|||||||
parent.Children().RemoveAt(index);
|
parent.Children().RemoveAt(index);
|
||||||
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
||||||
shortcutRemapBuffer.erase(shortcutRemapBuffer.begin() + (index - 1));
|
shortcutRemapBuffer.erase(shortcutRemapBuffer.begin() + (index - 1));
|
||||||
|
// delete the ShortcutControl objects so that they get destructed
|
||||||
|
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + (index - 1));
|
||||||
});
|
});
|
||||||
tableRow.Children().Append(deleteShortcut);
|
tableRow.Children().Append(deleteShortcut);
|
||||||
|
tableRow.UpdateLayout();
|
||||||
parent.Children().Append(tableRow);
|
parent.Children().Append(tableRow);
|
||||||
|
parent.UpdateLayout();
|
||||||
|
|
||||||
|
// Set the shortcut text if the two vectors are not empty (i.e. default args)
|
||||||
|
if (originalKeys.IsValidShortcut() && newKeys.IsValidShortcut())
|
||||||
|
{
|
||||||
|
shortcutRemapBuffer.push_back(std::vector<Shortcut>{ Shortcut(), Shortcut() });
|
||||||
|
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->AddShortcutToControl(originalKeys, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutDropDownStackPanel, *keyboardManagerState, shortcutRemapBuffer.size() - 1, 0);
|
||||||
|
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->AddShortcutToControl(newKeys, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutDropDownStackPanel, *keyboardManagerState, shortcutRemapBuffer.size() - 1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Initialize both shortcuts as empty shortcuts
|
||||||
|
shortcutRemapBuffer.push_back(std::vector<Shortcut>{ Shortcut(), Shortcut() });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to add a shortcut to the shortcut control as combo boxes
|
||||||
|
void ShortcutControl::AddShortcutToControl(Shortcut& shortcut, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||||
|
{
|
||||||
|
// Delete the existing drop down menus
|
||||||
|
parent.Children().Clear();
|
||||||
|
// Remove references to the old drop down objects to destroy them
|
||||||
|
keyDropDownControlObjects.clear();
|
||||||
|
|
||||||
|
std::vector<DWORD> shortcutKeyCodes = shortcut.GetKeyCodes();
|
||||||
|
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList(true);
|
||||||
|
if (shortcutKeyCodes.size() != 0)
|
||||||
|
{
|
||||||
|
KeyDropDownControl::AddDropDown(parent, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||||
|
for (int i = 0; i < shortcutKeyCodes.size(); i++)
|
||||||
|
{
|
||||||
|
// New drop down gets added automatically when the SelectedIndex is set
|
||||||
|
if (i < (int)parent.Children().Size())
|
||||||
|
{
|
||||||
|
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||||
|
auto it = std::find(keyCodeList.begin(), keyCodeList.end(), shortcutKeyCodes[i]);
|
||||||
|
if (it != keyCodeList.end())
|
||||||
|
{
|
||||||
|
currentDropDown.SelectedIndex((int32_t)std::distance(keyCodeList.begin(), it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent.UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||||
@ -62,7 +101,7 @@ StackPanel ShortcutControl::getShortcutControl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to create the detect shortcut UI window
|
// Function to create the detect shortcut UI window
|
||||||
void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const int& rowIndex, const int& colIndex)
|
void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||||
{
|
{
|
||||||
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
||||||
ContentDialog detectShortcutBox;
|
ContentDialog detectShortcutBox;
|
||||||
@ -76,7 +115,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
||||||
|
|
||||||
// Get the linked text block for the "Type shortcut" button that was clicked
|
// Get the linked text block for the "Type shortcut" button that was clicked
|
||||||
TextBlock linkedShortcutText = getSiblingElement(sender).as<TextBlock>();
|
StackPanel linkedShortcutStackPanel = getSiblingElement(sender).as<StackPanel>();
|
||||||
|
|
||||||
auto unregisterKeys = [&keyboardManagerState]() {
|
auto unregisterKeys = [&keyboardManagerState]() {
|
||||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||||
@ -90,7 +129,8 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
keyboardManagerState.ResetDetectedShortcutKey(key);
|
keyboardManagerState.ResetDetectedShortcutKey(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto onAccept = [linkedShortcutText,
|
auto onAccept = [this,
|
||||||
|
linkedShortcutStackPanel,
|
||||||
detectShortcutBox,
|
detectShortcutBox,
|
||||||
&keyboardManagerState,
|
&keyboardManagerState,
|
||||||
&shortcutRemapBuffer,
|
&shortcutRemapBuffer,
|
||||||
@ -102,8 +142,8 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
|
|
||||||
if (!detectedShortcutKeys.IsEmpty())
|
if (!detectedShortcutKeys.IsEmpty())
|
||||||
{
|
{
|
||||||
shortcutRemapBuffer[rowIndex][colIndex] = detectedShortcutKeys;
|
// The shortcut buffer gets set in this function
|
||||||
linkedShortcutText.Text(detectedShortcutKeys.ToHstring(keyboardManagerState.keyboardMap));
|
AddShortcutToControl(detectedShortcutKeys, linkedShortcutStackPanel, keyboardManagerState, rowIndex, colIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the keyboard manager UI state
|
// Reset the keyboard manager UI state
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||||
#include <keyboardManager/common/Helpers.h>
|
#include <keyboardManager/common/Helpers.h>
|
||||||
#include <keyboardmanager/common/Shortcut.h>
|
#include <keyboardmanager/common/Shortcut.h>
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
class ShortcutControl
|
class ShortcutControl
|
||||||
{
|
{
|
||||||
@ -9,6 +10,9 @@ private:
|
|||||||
// Textblock to display the selected shortcut
|
// Textblock to display the selected shortcut
|
||||||
TextBlock shortcutText;
|
TextBlock shortcutText;
|
||||||
|
|
||||||
|
// Stack panel for the drop downs to display the selected shortcut
|
||||||
|
StackPanel shortcutDropDownStackPanel;
|
||||||
|
|
||||||
// Button to type the shortcut
|
// Button to type the shortcut
|
||||||
Button typeShortcut;
|
Button typeShortcut;
|
||||||
|
|
||||||
@ -22,9 +26,16 @@ public:
|
|||||||
static KeyboardManagerState* keyboardManagerState;
|
static KeyboardManagerState* keyboardManagerState;
|
||||||
// Stores the current list of remappings
|
// Stores the current list of remappings
|
||||||
static std::vector<std::vector<Shortcut>> shortcutRemapBuffer;
|
static std::vector<std::vector<Shortcut>> shortcutRemapBuffer;
|
||||||
|
// Vector to store dynamically allocated KeyDropDownControl objects to avoid early destruction
|
||||||
|
std::vector<std::unique_ptr<KeyDropDownControl>> keyDropDownControlObjects;
|
||||||
|
|
||||||
ShortcutControl(const int& rowIndex, const int& colIndex)
|
ShortcutControl(const size_t rowIndex, const size_t colIndex)
|
||||||
{
|
{
|
||||||
|
shortcutDropDownStackPanel.RequestedTheme(ElementTheme::Light);
|
||||||
|
shortcutDropDownStackPanel.Spacing(10);
|
||||||
|
shortcutDropDownStackPanel.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||||
|
KeyDropDownControl::AddDropDown(shortcutDropDownStackPanel, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||||
|
|
||||||
typeShortcut.Content(winrt::box_value(winrt::to_hstring("Type Shortcut")));
|
typeShortcut.Content(winrt::box_value(winrt::to_hstring("Type Shortcut")));
|
||||||
typeShortcut.Click([&, rowIndex, colIndex](IInspectable const& sender, RoutedEventArgs const&) {
|
typeShortcut.Click([&, rowIndex, colIndex](IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
||||||
@ -37,15 +48,19 @@ public:
|
|||||||
shortcutControlLayout.Spacing(10);
|
shortcutControlLayout.Spacing(10);
|
||||||
|
|
||||||
shortcutControlLayout.Children().Append(typeShortcut);
|
shortcutControlLayout.Children().Append(typeShortcut);
|
||||||
shortcutControlLayout.Children().Append(shortcutText);
|
shortcutControlLayout.Children().Append(shortcutDropDownStackPanel);
|
||||||
|
shortcutControlLayout.UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||||
static void AddNewShortcutControlRow(StackPanel& parent, Shortcut originalKeys = Shortcut(), Shortcut newKeys = Shortcut());
|
static void AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys = Shortcut(), Shortcut newKeys = Shortcut());
|
||||||
|
|
||||||
|
// Function to add a shortcut to the shortcut control as combo boxes
|
||||||
|
void AddShortcutToControl(Shortcut& shortcut, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||||
|
|
||||||
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||||
StackPanel getShortcutControl();
|
StackPanel getShortcutControl();
|
||||||
|
|
||||||
// Function to create the detect shortcut UI window
|
// Function to create the detect shortcut UI window
|
||||||
void createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const int& rowIndex, const int& colIndex);
|
void createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ KeyboardManagerState* SingleKeyRemapControl::keyboardManagerState = nullptr;
|
|||||||
std::vector<std::vector<DWORD>> SingleKeyRemapControl::singleKeyRemapBuffer;
|
std::vector<std::vector<DWORD>> SingleKeyRemapControl::singleKeyRemapBuffer;
|
||||||
|
|
||||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey, const DWORD& newKey)
|
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const DWORD newKey)
|
||||||
{
|
{
|
||||||
// Parent element for the row
|
// Parent element for the row
|
||||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||||
@ -16,20 +16,31 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const D
|
|||||||
tableRow.Spacing(100);
|
tableRow.Spacing(100);
|
||||||
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||||
|
|
||||||
|
// Create new SingleKeyRemapControl objects dynamically so that we does not get destructed
|
||||||
|
std::vector<std::unique_ptr<SingleKeyRemapControl>> newrow;
|
||||||
|
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(singleKeyRemapBuffer.size(), 0))));
|
||||||
|
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(singleKeyRemapBuffer.size(), 1))));
|
||||||
|
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||||
// SingleKeyRemapControl for the original key.
|
// SingleKeyRemapControl for the original key.
|
||||||
SingleKeyRemapControl originalRemapKeyControl(singleKeyRemapBuffer.size(), 0);
|
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl());
|
||||||
tableRow.Children().Append(originalRemapKeyControl.getSingleKeyRemapControl());
|
// SingleKeyRemapControl for the new remap key
|
||||||
|
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl());
|
||||||
// SingleKeyRemapControl for the new remap key.
|
|
||||||
SingleKeyRemapControl newRemapKeyControl(singleKeyRemapBuffer.size(), 1);
|
|
||||||
tableRow.Children().Append(newRemapKeyControl.getSingleKeyRemapControl());
|
|
||||||
|
|
||||||
// Set the key text if the two keys are not null (i.e. default args)
|
// Set the key text if the two keys are not null (i.e. default args)
|
||||||
if (originalKey != NULL && newKey != NULL)
|
if (originalKey != NULL && newKey != NULL)
|
||||||
{
|
{
|
||||||
singleKeyRemapBuffer.push_back(std::vector<DWORD>{ originalKey, newKey });
|
singleKeyRemapBuffer.push_back(std::vector<DWORD>{ originalKey, newKey });
|
||||||
originalRemapKeyControl.singleKeyRemapText.Text(winrt::to_hstring(keyboardManagerState->keyboardMap.GetKeyName(originalKey).c_str()));
|
std::vector<DWORD> keyCodes = keyboardManagerState->keyboardMap.GetKeyCodeList();
|
||||||
newRemapKeyControl.singleKeyRemapText.Text(winrt::to_hstring(keyboardManagerState->keyboardMap.GetKeyName(newKey).c_str()));
|
auto it = std::find(keyCodes.begin(), keyCodes.end(), originalKey);
|
||||||
|
if (it != keyCodes.end())
|
||||||
|
{
|
||||||
|
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->singleKeyRemapDropDown.SetSelectedIndex((int32_t)std::distance(keyCodes.begin(), it));
|
||||||
|
}
|
||||||
|
it = std::find(keyCodes.begin(), keyCodes.end(), newKey);
|
||||||
|
if (it != keyCodes.end())
|
||||||
|
{
|
||||||
|
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->singleKeyRemapDropDown.SetSelectedIndex((int32_t)std::distance(keyCodes.begin(), it));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -52,6 +63,8 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const D
|
|||||||
parent.Children().RemoveAt(index);
|
parent.Children().RemoveAt(index);
|
||||||
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
||||||
singleKeyRemapBuffer.erase(singleKeyRemapBuffer.begin() + (index - 1));
|
singleKeyRemapBuffer.erase(singleKeyRemapBuffer.begin() + (index - 1));
|
||||||
|
// delete the SingleKeyRemapControl objects so that they get destructed
|
||||||
|
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + (index - 1));
|
||||||
});
|
});
|
||||||
tableRow.Children().Append(deleteRemapKeys);
|
tableRow.Children().Append(deleteRemapKeys);
|
||||||
parent.Children().Append(tableRow);
|
parent.Children().Append(tableRow);
|
||||||
@ -64,7 +77,7 @@ StackPanel SingleKeyRemapControl::getSingleKeyRemapControl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to create the detect remap key UI window
|
// Function to create the detect remap key UI window
|
||||||
void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const int& rowIndex, const int& colIndex)
|
void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||||
{
|
{
|
||||||
// ContentDialog for detecting remap key. This is the parent UI element.
|
// ContentDialog for detecting remap key. This is the parent UI element.
|
||||||
ContentDialog detectRemapKeyBox;
|
ContentDialog detectRemapKeyBox;
|
||||||
@ -78,7 +91,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
||||||
|
|
||||||
// Get the linked text block for the "Type Key" button that was clicked
|
// Get the linked text block for the "Type Key" button that was clicked
|
||||||
TextBlock linkedRemapText = getSiblingElement(sender).as<TextBlock>();
|
ComboBox linkedRemapDropDown = getSiblingElement(sender).as<ComboBox>();
|
||||||
|
|
||||||
auto unregisterKeys = [&keyboardManagerState]() {
|
auto unregisterKeys = [&keyboardManagerState]() {
|
||||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||||
@ -87,7 +100,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
t2.detach();
|
t2.detach();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto onAccept = [linkedRemapText,
|
auto onAccept = [linkedRemapDropDown,
|
||||||
detectRemapKeyBox,
|
detectRemapKeyBox,
|
||||||
&keyboardManagerState,
|
&keyboardManagerState,
|
||||||
&singleKeyRemapBuffer,
|
&singleKeyRemapBuffer,
|
||||||
@ -99,8 +112,14 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
|
|
||||||
if (detectedKey != NULL)
|
if (detectedKey != NULL)
|
||||||
{
|
{
|
||||||
singleKeyRemapBuffer[rowIndex][colIndex] = detectedKey;
|
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList();
|
||||||
linkedRemapText.Text(winrt::to_hstring(keyboardManagerState.keyboardMap.GetKeyName(detectedKey).c_str()));
|
// Update the drop down list with the new language to ensure that the correct key is displayed
|
||||||
|
linkedRemapDropDown.ItemsSource(keyboardManagerState.keyboardMap.GetKeyNameList());
|
||||||
|
auto it = std::find(keyCodeList.begin(), keyCodeList.end(), detectedKey);
|
||||||
|
if (it != keyCodeList.end())
|
||||||
|
{
|
||||||
|
linkedRemapDropDown.SelectedIndex((int32_t)std::distance(keyCodeList.begin(), it));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the keyboard manager UI state
|
// Reset the keyboard manager UI state
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||||
|
#include "KeyDropDownControl.h"
|
||||||
|
|
||||||
class SingleKeyRemapControl
|
class SingleKeyRemapControl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Textblock to display the selected remap key
|
// Drop down to display the selected remap key
|
||||||
TextBlock singleKeyRemapText;
|
KeyDropDownControl singleKeyRemapDropDown;
|
||||||
|
|
||||||
// Button to type the remap key
|
// Button to type the remap key
|
||||||
Button typeKey;
|
Button typeKey;
|
||||||
@ -21,7 +22,8 @@ public:
|
|||||||
// Stores the current list of remappings
|
// Stores the current list of remappings
|
||||||
static std::vector<std::vector<DWORD>> singleKeyRemapBuffer;
|
static std::vector<std::vector<DWORD>> singleKeyRemapBuffer;
|
||||||
|
|
||||||
SingleKeyRemapControl(const int& rowIndex, const int& colIndex)
|
SingleKeyRemapControl(const size_t rowIndex, const size_t colIndex) :
|
||||||
|
singleKeyRemapDropDown(rowIndex, colIndex, singleKeyRemapBuffer)
|
||||||
{
|
{
|
||||||
typeKey.Content(winrt::box_value(winrt::to_hstring("Type Key")));
|
typeKey.Content(winrt::box_value(winrt::to_hstring("Type Key")));
|
||||||
typeKey.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
typeKey.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
||||||
@ -37,15 +39,16 @@ public:
|
|||||||
singleKeyRemapControlLayout.Spacing(10);
|
singleKeyRemapControlLayout.Spacing(10);
|
||||||
|
|
||||||
singleKeyRemapControlLayout.Children().Append(typeKey);
|
singleKeyRemapControlLayout.Children().Append(typeKey);
|
||||||
singleKeyRemapControlLayout.Children().Append(singleKeyRemapText);
|
singleKeyRemapControlLayout.Children().Append(singleKeyRemapDropDown.GetComboBox());
|
||||||
|
singleKeyRemapControlLayout.UpdateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||||
static void AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey = NULL, const DWORD& newKey = NULL);
|
static void AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = NULL, const DWORD newKey = NULL);
|
||||||
|
|
||||||
// Function to return the stack panel element of the SingleKeyRemapControl. This is the externally visible UI element which can be used to add it to other layouts
|
// Function to return the stack panel element of the SingleKeyRemapControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||||
StackPanel getSingleKeyRemapControl();
|
StackPanel getSingleKeyRemapControl();
|
||||||
|
|
||||||
// Function to create the detect remap keys UI window
|
// Function to create the detect remap keys UI window
|
||||||
void createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const int& rowIndex, const int& colIndex);
|
void createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user