mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +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);
|
||||
}
|
||||
|
||||
// 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
|
||||
bool isExtendedKey(DWORD key)
|
||||
{
|
||||
|
@ -2,6 +2,16 @@
|
||||
#include <vector>
|
||||
#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
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
bool isExtendedKey(DWORD key);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "LayoutMap.h"
|
||||
|
||||
// Function to return the unicode string name of the key
|
||||
std::wstring LayoutMap::GetKeyName(DWORD key)
|
||||
{
|
||||
std::wstring result = L"Undefined";
|
||||
@ -15,30 +16,41 @@ std::wstring LayoutMap::GetKeyName(DWORD key)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Update Keyboard layout according to input locale identifier
|
||||
void LayoutMap::UpdateLayout()
|
||||
{
|
||||
// Get keyboard layout for current thread
|
||||
HKL layout = GetKeyboardLayout(0);
|
||||
if (layout == previousLayout) {
|
||||
if (layout == previousLayout)
|
||||
{
|
||||
return;
|
||||
}
|
||||
previousLayout = layout;
|
||||
if (!isKeyCodeListGenerated)
|
||||
{
|
||||
unicodeKeys.clear();
|
||||
unknownKeys.clear();
|
||||
}
|
||||
|
||||
unsigned char btKeys[256] = { 0 };
|
||||
unsigned char* btKeys = new unsigned char[256]{ 0 };
|
||||
GetKeyboardState(btKeys);
|
||||
|
||||
// Iterate over all the virtual key codes
|
||||
for (int i = 0; i < 256; i++)
|
||||
// Iterate over all the virtual key codes. virtual key 0 is not used
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
// Get the scan code from the virtual key code
|
||||
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 };
|
||||
int result = ToUnicodeEx(i, scanCode, (BYTE*)btKeys, szBuffer, 3, 0, layout);
|
||||
// If a representation is returned
|
||||
if (result > 0)
|
||||
{
|
||||
keyboardLayoutMap[i] = szBuffer;
|
||||
if (!isKeyCodeListGenerated)
|
||||
{
|
||||
unicodeKeys[i] = szBuffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -46,9 +58,15 @@ void LayoutMap::UpdateLayout()
|
||||
std::wstring vk = L"VK ";
|
||||
vk += std::to_wstring(i);
|
||||
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", " "
|
||||
// To do: localization
|
||||
keyboardLayoutMap[VK_CANCEL] = L"Break";
|
||||
@ -155,3 +173,104 @@ void LayoutMap::UpdateLayout()
|
||||
keyboardLayoutMap[0xFF] = L"Undefined";
|
||||
// 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 <windows.h>
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
// Wrapper class to handle keyboard layout
|
||||
class LayoutMap
|
||||
{
|
||||
private:
|
||||
// Stores mappings for all the virtual key codes to the name of the key
|
||||
std::map<DWORD, std::wstring> keyboardLayoutMap;
|
||||
std::mutex keyboardLayoutMap_mutex;
|
||||
|
||||
// Stores the previous layout
|
||||
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:
|
||||
std::map<DWORD, std::wstring> keyboardLayoutMap;
|
||||
|
||||
// Update Keyboard layout according to input locale identifier
|
||||
void UpdateLayout();
|
||||
|
||||
@ -26,4 +43,9 @@ public:
|
||||
// Function to return the unicode string name of the 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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to return a vector of hstring for each key in the display order
|
||||
std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
||||
{
|
||||
std::vector<winrt::hstring> keys;
|
||||
@ -437,6 +418,43 @@ std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
||||
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
|
||||
bool Shortcut::CheckModifiersKeyboardState() const
|
||||
{
|
||||
@ -540,7 +558,7 @@ bool Shortcut::CheckModifiersKeyboardState() const
|
||||
bool Shortcut::IsKeyboardStateClearExceptShortcut() const
|
||||
{
|
||||
// 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
|
||||
if (keyVal == VK_LBUTTON || keyVal == VK_RBUTTON || keyVal == VK_MBUTTON || keyVal == VK_XBUTTON1 || keyVal == VK_XBUTTON2)
|
||||
|
@ -22,7 +22,6 @@ private:
|
||||
DWORD actionKey;
|
||||
|
||||
public:
|
||||
|
||||
// By default create an empty shortcut
|
||||
Shortcut() :
|
||||
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.
|
||||
void ResetKey(const DWORD& input, const bool& isWinBoth = false);
|
||||
|
||||
// Function to return the string representation of the shortcut
|
||||
winrt::hstring ToHstring(LayoutMap& keyboardMap);
|
||||
|
||||
// Function to return a vector of hstring for each key, in the same order as ToHstring()
|
||||
// Function to return a vector of hstring for each key in the display order
|
||||
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
|
||||
bool CheckModifiersKeyboardState() const;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "EditKeyboardWindow.h"
|
||||
#include "SingleKeyRemapControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
|
||||
LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
@ -15,7 +16,6 @@ std::mutex editKeyboardWindowMutex;
|
||||
// Function to create the Edit Keyboard Window
|
||||
void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardManagerState)
|
||||
{
|
||||
|
||||
// Window Registration
|
||||
const wchar_t szWindowClass[] = L"EditKeyboardWindow";
|
||||
if (!isEditKeyboardWindowRegistrationCompleted)
|
||||
@ -104,7 +104,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
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.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
|
||||
Windows::UI::Xaml::Controls::StackPanel keyRemapTable;
|
||||
@ -143,14 +143,17 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
SingleKeyRemapControl::EditKeyboardWindowHandle = _hWndEditKeyboardWindow;
|
||||
// Store keyboard manager state
|
||||
SingleKeyRemapControl::keyboardManagerState = &keyboardManagerState;
|
||||
KeyDropDownControl::keyboardManagerState = &keyboardManagerState;
|
||||
// Clear the single key remap buffer
|
||||
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
|
||||
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyReMap_mutex);
|
||||
for (const auto& it : keyboardManagerState.singleKeyReMap)
|
||||
{
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, it.first, it.second);
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects, it.first, it.second);
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
@ -210,7 +213,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
addRemapKey.Content(plusSymbol);
|
||||
addRemapKey.Margin({ 10 });
|
||||
addRemapKey.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable);
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
||||
});
|
||||
|
||||
xamlContainer.Children().Append(header);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "EditShortcutsWindow.h"
|
||||
#include "ShortcutControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
|
||||
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
@ -133,14 +134,17 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
ShortcutControl::EditShortcutsWindowHandle = _hWndEditShortcutsWindow;
|
||||
// Store keyboard manager state
|
||||
ShortcutControl::keyboardManagerState = &keyboardManagerState;
|
||||
KeyDropDownControl::keyboardManagerState = &keyboardManagerState;
|
||||
// Clear the shortcut remap buffer
|
||||
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
|
||||
std::unique_lock<std::mutex> lock(keyboardManagerState.osLevelShortcutReMap_mutex);
|
||||
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();
|
||||
|
||||
@ -158,7 +162,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
Shortcut originalShortcut = ShortcutControl::shortcutRemapBuffer[i][0];
|
||||
Shortcut newShortcut = ShortcutControl::shortcutRemapBuffer[i][1];
|
||||
|
||||
if (originalShortcut.IsValidShortcut() && originalShortcut.IsValidShortcut())
|
||||
if (originalShortcut.IsValidShortcut() && newShortcut.IsValidShortcut())
|
||||
{
|
||||
bool result = keyboardManagerState.AddOSLevelShortcut(originalShortcut, newShortcut);
|
||||
if (!result)
|
||||
@ -197,7 +201,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
addShortcut.Content(plusSymbol);
|
||||
addShortcut.Margin({ 10 });
|
||||
addShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable);
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
||||
});
|
||||
|
||||
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>
|
||||
<ClCompile Include="EditKeyboardWindow.cpp" />
|
||||
<ClCompile Include="EditShortcutsWindow.cpp" />
|
||||
<ClCompile Include="MainWindow.cpp" />
|
||||
<ClCompile Include="KeyDropDownControl.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
@ -109,8 +109,8 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EditKeyboardWindow.h" />
|
||||
<ClInclude Include="EditShortcutsWindow.h" />
|
||||
<ClInclude Include="KeyDropDownControl.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="MainWindow.h" />
|
||||
<ClInclude Include="ShortcutControl.h" />
|
||||
<ClInclude Include="SingleKeyRemapControl.h" />
|
||||
</ItemGroup>
|
||||
|
@ -1,20 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MainWindow.cpp" />
|
||||
<ClCompile Include="EditKeyboardWindow.cpp" />
|
||||
<ClCompile Include="EditShortcutsWindow.cpp" />
|
||||
<ClCompile Include="ShortcutControl.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="SingleKeyRemapControl.cpp" />
|
||||
<ClCompile Include="KeyDropDownControl.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MainWindow.h" />
|
||||
<ClInclude Include="EditKeyboardWindow.h" />
|
||||
<ClInclude Include="EditShortcutsWindow.h" />
|
||||
<ClInclude Include="ShortcutControl.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="SingleKeyRemapControl.h" />
|
||||
<ClInclude Include="KeyDropDownControl.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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 "ShortcutControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
|
||||
//Both static members are initialized to null
|
||||
HWND ShortcutControl::EditShortcutsWindowHandle = nullptr;
|
||||
@ -8,7 +9,7 @@ KeyboardManagerState* ShortcutControl::keyboardManagerState = nullptr;
|
||||
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.
|
||||
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
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
@ -16,27 +17,17 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, Shortcut orig
|
||||
tableRow.Spacing(100);
|
||||
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 originalSC(shortcutRemapBuffer.size(), 0);
|
||||
tableRow.Children().Append(originalSC.getShortcutControl());
|
||||
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl());
|
||||
// ShortcutControl for the new shortcut
|
||||
ShortcutControl newSC(shortcutRemapBuffer.size(), 1);
|
||||
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() });
|
||||
}
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl());
|
||||
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
||||
FontIcon deleteSymbol;
|
||||
@ -50,9 +41,57 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, Shortcut orig
|
||||
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
|
||||
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.UpdateLayout();
|
||||
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
|
||||
@ -62,7 +101,7 @@ StackPanel ShortcutControl::getShortcutControl()
|
||||
}
|
||||
|
||||
// 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 detectShortcutBox;
|
||||
@ -76,7 +115,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
||||
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// 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]() {
|
||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||
@ -90,7 +129,8 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
||||
keyboardManagerState.ResetDetectedShortcutKey(key);
|
||||
};
|
||||
|
||||
auto onAccept = [linkedShortcutText,
|
||||
auto onAccept = [this,
|
||||
linkedShortcutStackPanel,
|
||||
detectShortcutBox,
|
||||
&keyboardManagerState,
|
||||
&shortcutRemapBuffer,
|
||||
@ -102,8 +142,8 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
||||
|
||||
if (!detectedShortcutKeys.IsEmpty())
|
||||
{
|
||||
shortcutRemapBuffer[rowIndex][colIndex] = detectedShortcutKeys;
|
||||
linkedShortcutText.Text(detectedShortcutKeys.ToHstring(keyboardManagerState.keyboardMap));
|
||||
// The shortcut buffer gets set in this function
|
||||
AddShortcutToControl(detectedShortcutKeys, linkedShortcutStackPanel, keyboardManagerState, rowIndex, colIndex);
|
||||
}
|
||||
|
||||
// Reset the keyboard manager UI state
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||
#include <keyboardManager/common/Helpers.h>
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
#include "KeyDropDownControl.h"
|
||||
|
||||
class ShortcutControl
|
||||
{
|
||||
@ -9,6 +10,9 @@ private:
|
||||
// Textblock to display the selected shortcut
|
||||
TextBlock shortcutText;
|
||||
|
||||
// Stack panel for the drop downs to display the selected shortcut
|
||||
StackPanel shortcutDropDownStackPanel;
|
||||
|
||||
// Button to type the shortcut
|
||||
Button typeShortcut;
|
||||
|
||||
@ -22,9 +26,16 @@ public:
|
||||
static KeyboardManagerState* keyboardManagerState;
|
||||
// Stores the current list of remappings
|
||||
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.Click([&, rowIndex, colIndex](IInspectable const& sender, RoutedEventArgs const&) {
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
||||
@ -37,15 +48,19 @@ public:
|
||||
shortcutControlLayout.Spacing(10);
|
||||
|
||||
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.
|
||||
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
|
||||
StackPanel getShortcutControl();
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
@ -16,20 +16,31 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const D
|
||||
tableRow.Spacing(100);
|
||||
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 originalRemapKeyControl(singleKeyRemapBuffer.size(), 0);
|
||||
tableRow.Children().Append(originalRemapKeyControl.getSingleKeyRemapControl());
|
||||
|
||||
// SingleKeyRemapControl for the new remap key.
|
||||
SingleKeyRemapControl newRemapKeyControl(singleKeyRemapBuffer.size(), 1);
|
||||
tableRow.Children().Append(newRemapKeyControl.getSingleKeyRemapControl());
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl());
|
||||
// SingleKeyRemapControl for the new remap key
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl());
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
if (originalKey != NULL && newKey != NULL)
|
||||
{
|
||||
singleKeyRemapBuffer.push_back(std::vector<DWORD>{ originalKey, newKey });
|
||||
originalRemapKeyControl.singleKeyRemapText.Text(winrt::to_hstring(keyboardManagerState->keyboardMap.GetKeyName(originalKey).c_str()));
|
||||
newRemapKeyControl.singleKeyRemapText.Text(winrt::to_hstring(keyboardManagerState->keyboardMap.GetKeyName(newKey).c_str()));
|
||||
std::vector<DWORD> keyCodes = keyboardManagerState->keyboardMap.GetKeyCodeList();
|
||||
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
|
||||
{
|
||||
@ -52,6 +63,8 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const D
|
||||
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
|
||||
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);
|
||||
parent.Children().Append(tableRow);
|
||||
@ -64,7 +77,7 @@ StackPanel SingleKeyRemapControl::getSingleKeyRemapControl()
|
||||
}
|
||||
|
||||
// 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 detectRemapKeyBox;
|
||||
@ -78,7 +91,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
||||
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// 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]() {
|
||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||
@ -87,7 +100,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
||||
t2.detach();
|
||||
};
|
||||
|
||||
auto onAccept = [linkedRemapText,
|
||||
auto onAccept = [linkedRemapDropDown,
|
||||
detectRemapKeyBox,
|
||||
&keyboardManagerState,
|
||||
&singleKeyRemapBuffer,
|
||||
@ -99,8 +112,14 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
||||
|
||||
if (detectedKey != NULL)
|
||||
{
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = detectedKey;
|
||||
linkedRemapText.Text(winrt::to_hstring(keyboardManagerState.keyboardMap.GetKeyName(detectedKey).c_str()));
|
||||
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList();
|
||||
// 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
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||
#include "KeyDropDownControl.h"
|
||||
|
||||
class SingleKeyRemapControl
|
||||
{
|
||||
private:
|
||||
// Textblock to display the selected remap key
|
||||
TextBlock singleKeyRemapText;
|
||||
// Drop down to display the selected remap key
|
||||
KeyDropDownControl singleKeyRemapDropDown;
|
||||
|
||||
// Button to type the remap key
|
||||
Button typeKey;
|
||||
@ -21,7 +22,8 @@ public:
|
||||
// Stores the current list of remappings
|
||||
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.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
||||
@ -37,15 +39,16 @@ public:
|
||||
singleKeyRemapControlLayout.Spacing(10);
|
||||
|
||||
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.
|
||||
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
|
||||
StackPanel getSingleKeyRemapControl();
|
||||
|
||||
// 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