├── WindowsKeyboardLayout ├── Stdafx.h ├── Definitions.cpp ├── app.ico ├── app.rc ├── resource.h ├── WPFKeyboardNative.cpp ├── Stdafx.cpp ├── WPFKeyboardNative.h ├── KeyboardLayoutHelper.h ├── Definitions.h ├── CharModifier.h ├── ScanCodeText.h ├── ScanCodeText.cpp ├── CharModifier.cpp ├── ScanCode.h ├── VirtualKey.h ├── VirtualKey.cpp ├── ScanCode.cpp ├── KeyboardLayout.h ├── KeyboardLayout.cpp ├── temp │ ├── KLL.h │ └── KLL.cpp ├── AssemblyInfo.cpp ├── ReadMe.txt ├── KeyboardLayoutHelper.cpp ├── WPFKeyboardNative.vcxproj.filters └── WindowsKeyboardLayout.vcxproj ├── screenshot.png ├── Dependencies ├── WindowsInput.dll └── MouseKeyboardActivityMonitor.dll ├── Sample ├── Resources │ └── Windows8Logo.png ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── App.xaml ├── MainWindow.xaml.cs ├── App.xaml.cs ├── KeyTemplates │ ├── WindowsKeyTemplate.xaml │ ├── DefaultKeyTemplate.xaml.cs │ ├── WindowsKeyTemplate.xaml.cs │ ├── SampleKeyControlBuilder.cs │ └── DefaultKeyTemplate.xaml ├── MainWindow.xaml ├── ViewModels │ └── SampleKeyboardViewModel.cs └── Sample.csproj ├── Test └── KeyboardLayout │ ├── KeyboardLayout │ ├── resource.h │ ├── KeyboardLayout.rc │ ├── res │ │ ├── KeyboardLayout.ico │ │ ├── KeyboardLayout.rc2 │ │ └── KeyboardScancodes.bmp │ ├── stdafx.cpp │ ├── targetver.h │ ├── KeyboardScanCode.h │ ├── KeyboardLayout.h │ ├── KeyboardScanCode.cpp │ ├── KeyboardLayoutDlg.h │ ├── KLL.h │ ├── stdafx.h │ ├── KeyboardLayout.cpp │ ├── KeyboardLayout.vcxproj.filters │ ├── ReadMe.txt │ ├── KeyboardLayoutDlg.cpp │ ├── KeyboardLayout.vcxproj │ └── KLL.cpp │ └── KeyboardLayout.sln ├── WindowsKeyboardLayoutTest ├── stdafx.cpp ├── targetver.h ├── WPFKeyboardNativeTest.cpp ├── stdafx.h ├── WPFKeyboardNativeTest.vcxproj.filters ├── ReadMe.txt └── WindowsKeyboardLayoutTest.vcxproj ├── README.md ├── WPFKeyboard.sln.DotSettings ├── WPFKeyboard ├── BaseViewModel.cs ├── Models │ ├── OnScreenKeyboardViewModel.cs │ ├── OnScreenKeyboardSectionViewModel.cs │ ├── OnScreenKeyboardRowViewModel.cs │ ├── BaseOnScreenKeyViewModel.cs │ ├── ModifierKey.cs │ └── ShiftSensitiveKey.cs ├── IOnScreenKeyControlBuilder.cs ├── IButtonEventListener.cs ├── DefaultOnScreenKeyControlBuilder.cs ├── Controls │ ├── KeyboardWindow.cs │ ├── OnScreenKeyboardRow.cs │ ├── OnScreenKeyboardSection.cs │ ├── OnScreenKey.cs │ └── OnScreenKeyboard.cs ├── Helpers.cs ├── Properties │ └── AssemblyInfo.cs ├── IKeyEventListener.cs ├── Keyboard.cs └── WPFKeyboard.csproj ├── LICENSE ├── WPFKeyboard.KBD ├── Properties │ └── AssemblyInfo.cs ├── WPFKeyboard.KBD.csproj ├── VirtualKey.cs └── KPDOnScreenKeyboardViewModel.cs ├── Headers ├── KLL.h └── KLL.cpp ├── .gitattributes ├── .gitignore └── WPFKeyboard.sln /WindowsKeyboardLayout/Stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /WindowsKeyboardLayout/Definitions.cpp: -------------------------------------------------------------------------------- 1 | #include "Stdafx.h" 2 | #include "Definitions.h" -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/screenshot.png -------------------------------------------------------------------------------- /Dependencies/WindowsInput.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Dependencies/WindowsInput.dll -------------------------------------------------------------------------------- /WindowsKeyboardLayout/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/WindowsKeyboardLayout/app.ico -------------------------------------------------------------------------------- /WindowsKeyboardLayout/app.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/WindowsKeyboardLayout/app.rc -------------------------------------------------------------------------------- /Sample/Resources/Windows8Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Sample/Resources/Windows8Logo.png -------------------------------------------------------------------------------- /WindowsKeyboardLayout/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by app.rc 4 | -------------------------------------------------------------------------------- /Dependencies/MouseKeyboardActivityMonitor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Dependencies/MouseKeyboardActivityMonitor.dll -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Test/KeyboardLayout/KeyboardLayout/resource.h -------------------------------------------------------------------------------- /WindowsKeyboardLayout/WPFKeyboardNative.cpp: -------------------------------------------------------------------------------- 1 | // This is the main DLL file. 2 | 3 | #include "stdafx.h" 4 | 5 | #include "WPFKeyboardNative.h" 6 | 7 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.rc -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/res/KeyboardLayout.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Test/KeyboardLayout/KeyboardLayout/res/KeyboardLayout.ico -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/res/KeyboardLayout.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Test/KeyboardLayout/KeyboardLayout/res/KeyboardLayout.rc2 -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/res/KeyboardScancodes.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pauldotknopf/WPFKeyboard/HEAD/Test/KeyboardLayout/KeyboardLayout/res/KeyboardScancodes.bmp -------------------------------------------------------------------------------- /Sample/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/Stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WPFKeyboardNative.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/stdafx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // stdafx.cpp : source file that includes just the standard includes 3 | // KeyboardLayout.pch will be the pre-compiled header 4 | // stdafx.obj will contain the pre-compiled type information 5 | 6 | #include "stdafx.h" 7 | 8 | 9 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/WPFKeyboardNative.h: -------------------------------------------------------------------------------- 1 | // WPFKeyboardNative.h 2 | 3 | #pragma once 4 | 5 | using namespace System; 6 | 7 | namespace WPFKeyboardNative { 8 | 9 | public ref class Class1 10 | { 11 | // TODO: Add your methods for this class here. 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/KeyboardLayoutHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "KeyboardLayout.h" 3 | using namespace System; 4 | namespace WPFKeyboardNative 5 | { 6 | public ref class KeyboardLayoutHelper 7 | { 8 | public: 9 | KeyboardLayoutHelper(void); 10 | static KeyboardLayout^ GetLayout(String^ keyboardLayoutDll); 11 | }; 12 | } -------------------------------------------------------------------------------- /Sample/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WPFKeyboardNativeTest.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/Definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | namespace WPFKeyboardNative 3 | { 4 | public ref class Definitions 5 | { 6 | public: 7 | static int WCH_NONE = 0xF000; 8 | static int WCH_DEAD = 0xF001; 9 | static int WCH_LGTR = 0xF002; 10 | static int CAPLOK = 0x01; 11 | static int SGCAPS = 0x02; 12 | static int CAPLOKALTGR = 0x04; 13 | }; 14 | } -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/CharModifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | namespace WPFKeyboardNative 3 | { 4 | public ref class CharModifier 5 | { 6 | private: 7 | int _virtualKey; 8 | int _modifierBits; 9 | public: 10 | CharModifier(int virtualKey, int modifierBits); 11 | property int VirtualKey { int get (); }; 12 | property int ModifierBits { int get (); }; 13 | }; 14 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WPFKeyboard 2 | =========== 3 | 4 | A virtual keyboard in WPF. Fully customizable, with support for every language supported by windows using Windows KBD Layout dll files. 5 | 6 | ![Alt text](https://raw.github.com/theonlylawislove/WPFKeyboard/master/screenshot.png "Optional title") 7 | 8 | **WORK IN PROGRESS** 9 | 10 | Wait for me to finish, or help out! 11 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/ScanCodeText.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | using namespace System; 3 | namespace WPFKeyboardNative 4 | { 5 | public ref class ScanCodeText 6 | { 7 | private: 8 | int _scanCode; 9 | String^ _text; 10 | public: 11 | ScanCodeText(int scanCode, String^ text); 12 | property int ScanCode { int get (); }; 13 | property String^ Text { String^ get (); }; 14 | }; 15 | } -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/WPFKeyboardNativeTest.cpp: -------------------------------------------------------------------------------- 1 | // WPFKeyboardNativeTest.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "KLL.h" 6 | 7 | int _tmain(int argc, _TCHAR* argv[]) 8 | { 9 | CKLL *kll = new CKLL(); 10 | // KBDGR - german 11 | // KBDUSA - USA 12 | kll->LoadDLL("C:\\Windows\\SysWOW64\\KBDGR.DLL"); 13 | Sleep(1000000); 14 | return 0; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "targetver.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | -------------------------------------------------------------------------------- /WPFKeyboard.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | KPD -------------------------------------------------------------------------------- /WindowsKeyboardLayout/ScanCodeText.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ScanCodeText.h" 3 | 4 | 5 | WPFKeyboardNative::ScanCodeText::ScanCodeText(int scanCode, String^ text) 6 | { 7 | _scanCode = scanCode; 8 | _text = text; 9 | } 10 | 11 | int WPFKeyboardNative::ScanCodeText::ScanCode::get() 12 | { 13 | return _scanCode; 14 | } 15 | 16 | String^ WPFKeyboardNative::ScanCodeText::Text::get() 17 | { 18 | return _text; 19 | } -------------------------------------------------------------------------------- /WindowsKeyboardLayout/CharModifier.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CharModifier.h" 3 | 4 | 5 | WPFKeyboardNative::CharModifier::CharModifier(int virtualKey, int modifierBits) 6 | { 7 | _virtualKey = virtualKey; 8 | _modifierBits = modifierBits; 9 | } 10 | 11 | int WPFKeyboardNative::CharModifier::VirtualKey::get() 12 | { 13 | return _virtualKey; 14 | } 15 | 16 | int WPFKeyboardNative::CharModifier::ModifierBits::get() 17 | { 18 | return _modifierBits; 19 | } -------------------------------------------------------------------------------- /WindowsKeyboardLayout/ScanCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | namespace WPFKeyboardNative 3 | { 4 | public ref class ScanCode 5 | { 6 | private: 7 | int _virtualKey; 8 | int _scanCode; 9 | bool _e0Set; 10 | bool _e1Set; 11 | public: 12 | ScanCode(int virtualKey, int scanCode, bool e0Set, bool e1Set); 13 | property int VirtualKey { int get (); }; 14 | property int Code { int get (); }; 15 | property bool E0Set { bool get (); }; 16 | property bool E1Set { bool get (); }; 17 | }; 18 | } -------------------------------------------------------------------------------- /WindowsKeyboardLayout/VirtualKey.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | using namespace System; 3 | namespace WPFKeyboardNative 4 | { 5 | public ref class VirtualKey 6 | { 7 | private: 8 | int _virtualkey; 9 | int _attributes; 10 | array^ _characters; 11 | public: 12 | VirtualKey(int virtualKey, int attributes, array^ characters); 13 | property int Key { int get (); } 14 | property array^ Characters { array^ get (); } 15 | property int Attributes { int get (); } 16 | }; 17 | } -------------------------------------------------------------------------------- /WPFKeyboard/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace WPFKeyboard 4 | { 5 | public class BaseViewModel : INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | protected void RaisePropertyChanged(string propertyName) 10 | { 11 | var handler = PropertyChanged; 12 | if(handler != null) 13 | handler(this, new PropertyChangedEventArgs(propertyName)); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Sample.KeyTemplates; 2 | using WPFKeyboard; 3 | 4 | namespace Sample 5 | { 6 | /// 7 | /// Interaction logic for MainWindow.xaml 8 | /// 9 | public partial class MainWindow 10 | { 11 | public MainWindow() 12 | { 13 | InitializeComponent(); 14 | VirtualKeyboard.OnScreenKeyControlBuilder = new SampleKeyControlBuilder(); 15 | VirtualKeyboard.DataContext = new KPDOnScreenKeyboardViewModel(@"C:\Windows\SysWOW64\KBDUS.DLL"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/VirtualKey.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "VirtualKey.h" 3 | 4 | WPFKeyboardNative::VirtualKey::VirtualKey(int virtualKey, int attributes, array^ characters) 5 | { 6 | _attributes = attributes; 7 | _virtualkey = virtualKey; 8 | _characters = characters; 9 | } 10 | 11 | int WPFKeyboardNative::VirtualKey::Key::get() 12 | { 13 | return _virtualkey; 14 | } 15 | 16 | array^ WPFKeyboardNative::VirtualKey::Characters::get() 17 | { 18 | return _characters; 19 | } 20 | 21 | int WPFKeyboardNative::VirtualKey::Attributes::get() 22 | { 23 | return _attributes; 24 | } 25 | -------------------------------------------------------------------------------- /WPFKeyboard/Models/OnScreenKeyboardViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace WPFKeyboard.Models 8 | { 9 | public class OnScreenKeyboardViewModel 10 | { 11 | readonly ObservableCollection _sections = new ObservableCollection(); 12 | 13 | public ObservableCollection Sections 14 | { 15 | get { return _sections; } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardScanCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // CKeyboardScanCode dialog 5 | 6 | class CKeyboardScanCode : public CDialogEx 7 | { 8 | DECLARE_DYNAMIC(CKeyboardScanCode) 9 | 10 | public: 11 | CKeyboardScanCode(CWnd* pParent = NULL); // standard constructor 12 | virtual ~CKeyboardScanCode(); 13 | 14 | // Dialog Data 15 | enum { IDD = IDD_KEYBOARDLAYOUT }; 16 | 17 | protected: 18 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 19 | 20 | DECLARE_MESSAGE_MAP() 21 | public: 22 | afx_msg void OnBnClickedOk(); 23 | afx_msg void OnBnClickedCancel(); 24 | }; 25 | -------------------------------------------------------------------------------- /Sample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Windows; 8 | 9 | namespace Sample 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App 15 | { 16 | public App() 17 | { 18 | Startup += OnStartup; 19 | } 20 | 21 | private void OnStartup(object sender, StartupEventArgs startupEventArgs) 22 | { 23 | 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sample/KeyTemplates/WindowsKeyTemplate.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WPFKeyboard/IOnScreenKeyControlBuilder.cs: -------------------------------------------------------------------------------- 1 | using WPFKeyboard.Models; 2 | 3 | namespace WPFKeyboard 4 | { 5 | /// 6 | /// Contract for building the content for keys. 7 | /// This allows use to change the template for the keys 8 | /// 9 | public interface IOnScreenKeyControlBuilder 10 | { 11 | /// 12 | /// Build a WPF control to use as the template for the given key view model 13 | /// 14 | /// The key view model. 15 | /// 16 | object BuildControlForKey(BaseOnScreenKeyViewModel keyViewModel); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/ScanCode.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ScanCode.h" 3 | 4 | 5 | WPFKeyboardNative::ScanCode::ScanCode(int virtualKey, int scanCode, bool e0Set, bool e1Set) 6 | { 7 | _virtualKey = virtualKey; 8 | _scanCode = scanCode; 9 | _e0Set = e0Set; 10 | _e1Set = e1Set; 11 | } 12 | 13 | int WPFKeyboardNative::ScanCode::VirtualKey::get() 14 | { 15 | return _virtualKey; 16 | } 17 | 18 | int WPFKeyboardNative::ScanCode::Code::get() 19 | { 20 | return _scanCode; 21 | } 22 | 23 | bool WPFKeyboardNative::ScanCode::E0Set::get() 24 | { 25 | return _e0Set; 26 | } 27 | 28 | bool WPFKeyboardNative::ScanCode::E1Set::get() 29 | { 30 | return _e1Set; 31 | } -------------------------------------------------------------------------------- /WPFKeyboard/IButtonEventListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace WPFKeyboard 7 | { 8 | /// 9 | /// Key view models that implement this interface will have methods that get called when the button is pressed/released 10 | /// 11 | public interface IButtonEventListener 12 | { 13 | /// 14 | /// The button was pressed down 15 | /// 16 | void ButtonDown(); 17 | 18 | /// 19 | /// The buttonw as pressed up 20 | /// 21 | void ButtonUp(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.h: -------------------------------------------------------------------------------- 1 | 2 | // KeyboardLayout.h : main header file for the PROJECT_NAME application 3 | // 4 | 5 | #pragma once 6 | 7 | #ifndef __AFXWIN_H__ 8 | #error "include 'stdafx.h' before including this file for PCH" 9 | #endif 10 | 11 | #include "resource.h" // main symbols 12 | 13 | 14 | // CKeyboardLayoutApp: 15 | // See KeyboardLayout.cpp for the implementation of this class 16 | // 17 | 18 | class CKeyboardLayoutApp : public CWinApp 19 | { 20 | public: 21 | CKeyboardLayoutApp(); 22 | 23 | // Overrides 24 | public: 25 | virtual BOOL InitInstance(); 26 | 27 | // Implementation 28 | 29 | DECLARE_MESSAGE_MAP() 30 | }; 31 | 32 | extern CKeyboardLayoutApp theApp; -------------------------------------------------------------------------------- /Sample/KeyTemplates/DefaultKeyTemplate.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | 15 | namespace Sample.KeyTemplates 16 | { 17 | /// 18 | /// Interaction logic for DefaultKeyTemplate.xaml 19 | /// 20 | public partial class DefaultKeyTemplate : UserControl 21 | { 22 | public DefaultKeyTemplate() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sample/KeyTemplates/WindowsKeyTemplate.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | using System.Windows.Media.Imaging; 12 | using System.Windows.Navigation; 13 | using System.Windows.Shapes; 14 | 15 | namespace Sample.KeyTemplates 16 | { 17 | /// 18 | /// Interaction logic for WindowsKeyTemplate.xaml 19 | /// 20 | public partial class WindowsKeyTemplate : UserControl 21 | { 22 | public WindowsKeyTemplate() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/KeyboardLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CharModifier.h" 3 | #include "VirtualKey.h" 4 | #include "ScanCode.h" 5 | #include "ScanCodeText.h" 6 | using namespace System; 7 | using namespace System::Collections::Generic; 8 | namespace WPFKeyboardNative 9 | { 10 | public ref class KeyboardLayout 11 | { 12 | private: 13 | List^ _charModifiers; 14 | List^ _virtualKeys; 15 | List^ _scanCodes; 16 | List^ _scanCodeText; 17 | public: 18 | KeyboardLayout(String^ keyboardLayoutDllPath); 19 | property List^ CharModifiers { List^ get (); }; 20 | property List^ VirtualKeys { List^ get (); }; 21 | property List^ ScanCodes { List^ get (); }; 22 | property List^ CodeText { List^ get (); }; 23 | }; 24 | } -------------------------------------------------------------------------------- /WPFKeyboard/Models/OnScreenKeyboardSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.Windows; 3 | 4 | namespace WPFKeyboard.Models 5 | { 6 | public class OnScreenKeyboardSectionViewModel : BaseViewModel 7 | { 8 | GridLength _sectionWidth = new GridLength(1, GridUnitType.Star); 9 | readonly ObservableCollection _rows = new ObservableCollection(); 10 | 11 | public GridLength SectionWidth 12 | { 13 | get { return _sectionWidth; } 14 | set 15 | { 16 | _sectionWidth = value; 17 | RaisePropertyChanged("SectionWidth"); 18 | } 19 | } 20 | 21 | public ObservableCollection Rows 22 | { 23 | get { return _rows; } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WPFKeyboard/Models/OnScreenKeyboardRowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows; 7 | 8 | namespace WPFKeyboard.Models 9 | { 10 | public class OnScreenKeyboardRowViewModel : BaseViewModel 11 | { 12 | GridLength _rowHeight = new GridLength(1, GridUnitType.Star); 13 | ObservableCollection _keys = new ObservableCollection(); 14 | 15 | public GridLength RowHeight 16 | { 17 | get { return _rowHeight; } 18 | set 19 | { 20 | _rowHeight = value; 21 | RaisePropertyChanged("RowHeight"); 22 | } 23 | } 24 | 25 | public ObservableCollection Keys 26 | { 27 | get { return _keys; } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardLayout", "KeyboardLayout\KeyboardLayout.vcxproj", "{CF8CCD7C-CABE-4285-84EA-8410E05AA4EC}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {CF8CCD7C-CABE-4285-84EA-8410E05AA4EC}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {CF8CCD7C-CABE-4285-84EA-8410E05AA4EC}.Debug|Win32.Build.0 = Debug|Win32 14 | {CF8CCD7C-CABE-4285-84EA-8410E05AA4EC}.Release|Win32.ActiveCfg = Release|Win32 15 | {CF8CCD7C-CABE-4285-84EA-8410E05AA4EC}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/KeyboardLayout.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "KeyboardLayout.h" 3 | 4 | WPFKeyboardNative::KeyboardLayout::KeyboardLayout(String^ keyboardLayoutDllPath) 5 | { 6 | _charModifiers = gcnew List(); 7 | _virtualKeys = gcnew List(); 8 | _scanCodes = gcnew List(); 9 | _scanCodeText = gcnew List(); 10 | } 11 | 12 | List^ WPFKeyboardNative::KeyboardLayout::CharModifiers::get() 13 | { 14 | return _charModifiers; 15 | } 16 | 17 | List^ WPFKeyboardNative::KeyboardLayout::VirtualKeys::get() 18 | { 19 | return _virtualKeys; 20 | } 21 | 22 | List^ WPFKeyboardNative::KeyboardLayout::ScanCodes::get() 23 | { 24 | return _scanCodes; 25 | } 26 | 27 | List^ WPFKeyboardNative::KeyboardLayout::CodeText::get() 28 | { 29 | return _scanCodeText; 30 | } -------------------------------------------------------------------------------- /Sample/KeyTemplates/SampleKeyControlBuilder.cs: -------------------------------------------------------------------------------- 1 | using WindowsInput.Native; 2 | using WPFKeyboard; 3 | using WPFKeyboard.Models; 4 | 5 | namespace Sample.KeyTemplates 6 | { 7 | public class SampleKeyControlBuilder : WPFKeyboard.IOnScreenKeyControlBuilder 8 | { 9 | public object BuildControlForKey(BaseOnScreenKeyViewModel keyViewModel) 10 | { 11 | var virtualKeyViewModel = keyViewModel as VirtualKey; 12 | if (virtualKeyViewModel != null) 13 | { 14 | if (virtualKeyViewModel.Key == VirtualKeyCode.LWIN || virtualKeyViewModel.Key == VirtualKeyCode.RWIN) 15 | { 16 | return new WindowsKeyTemplate() 17 | { 18 | DataContext = keyViewModel 19 | }; 20 | } 21 | } 22 | var template = new DefaultKeyTemplate 23 | { 24 | DataContext = keyViewModel 25 | }; 26 | return template; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WPFKeyboard/DefaultOnScreenKeyControlBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Controls; 6 | using System.Windows.Data; 7 | 8 | namespace WPFKeyboard 9 | { 10 | /// 11 | /// The default control builder for the keys. 12 | /// It builds a simple textbox that binds the to the Display property of the base key view model. 13 | /// 14 | public class DefaultOnScreenKeyControlBuilder : IOnScreenKeyControlBuilder 15 | { 16 | /// 17 | /// Build a WPF control to use as the template for the given key view model 18 | /// 19 | /// The key view model. 20 | /// 21 | public object BuildControlForKey(Models.BaseOnScreenKeyViewModel keyViewModel) 22 | { 23 | var textBlock = new TextBlock(); 24 | textBlock.SetBinding(TextBlock.TextProperty, new Binding("Display")); 25 | return textBlock; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Paul Knopf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardScanCode.cpp: -------------------------------------------------------------------------------- 1 | // KeyboardScanCode.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "KeyboardLayout.h" 6 | #include "KeyboardScanCode.h" 7 | #include "afxdialogex.h" 8 | #include "KeyboardLayoutDlg.h" 9 | 10 | 11 | // CKeyboardScanCode dialog 12 | 13 | IMPLEMENT_DYNAMIC(CKeyboardScanCode, CDialogEx) 14 | 15 | CKeyboardScanCode::CKeyboardScanCode(CWnd* pParent /*=NULL*/) 16 | : CDialogEx(CKeyboardScanCode::IDD, pParent) 17 | { 18 | } 19 | 20 | CKeyboardScanCode::~CKeyboardScanCode() 21 | { 22 | } 23 | 24 | void CKeyboardScanCode::DoDataExchange(CDataExchange* pDX) 25 | { 26 | CDialogEx::DoDataExchange(pDX); 27 | } 28 | 29 | BEGIN_MESSAGE_MAP(CKeyboardScanCode, CDialogEx) 30 | ON_BN_CLICKED(IDOK, &CKeyboardScanCode::OnBnClickedOk) 31 | ON_BN_CLICKED(IDCANCEL, &CKeyboardScanCode::OnBnClickedCancel) 32 | END_MESSAGE_MAP() 33 | 34 | // CKeyboardScanCode message handlers 35 | 36 | 37 | void CKeyboardScanCode::OnBnClickedOk() 38 | { 39 | } 40 | 41 | void CKeyboardScanCode::OnBnClickedCancel() 42 | { 43 | CKeyboardLayoutDlg *pDlgParent = (CKeyboardLayoutDlg*)this->GetParent(); 44 | pDlgParent->OnBnClickedShowscancode(); 45 | } 46 | -------------------------------------------------------------------------------- /WPFKeyboard/Controls/KeyboardWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Interop; 5 | 6 | namespace WPFKeyboard.Controls 7 | { 8 | public class KeyboardWindow : Window 9 | { 10 | public KeyboardWindow() 11 | { 12 | Topmost = true; 13 | ResizeMode = ResizeMode.CanResizeWithGrip; 14 | } 15 | 16 | protected override void OnActivated(EventArgs e) 17 | { 18 | base.OnActivated(e); 19 | 20 | //Set the window style to noactivate. 21 | WindowInteropHelper helper = new WindowInteropHelper(this); 22 | SetWindowLong(helper.Handle, GWL_EXSTYLE, 23 | GetWindowLong(helper.Handle, GWL_EXSTYLE) | WS_EX_NOACTIVATE); 24 | } 25 | 26 | private const int GWL_EXSTYLE = -20; 27 | private const int WS_EX_NOACTIVATE = 0x08000000; 28 | 29 | [DllImport("user32.dll")] 30 | public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 31 | 32 | [DllImport("user32.dll")] 33 | public static extern int GetWindowLong(IntPtr hWnd, int nIndex); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sample/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34003 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Sample.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sample/KeyTemplates/DefaultKeyTemplate.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WPFKeyboard/Models/BaseOnScreenKeyViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Data; 4 | using System.Windows.Input; 5 | 6 | namespace WPFKeyboard.Models 7 | { 8 | public abstract class BaseOnScreenKeyViewModel : BaseViewModel 9 | { 10 | GridLength _buttonWidth = new GridLength(1, GridUnitType.Star); 11 | string _display; 12 | bool _isActive; 13 | private object _content; 14 | 15 | public GridLength ButtonWidth 16 | { 17 | get { return _buttonWidth; } 18 | set 19 | { 20 | _buttonWidth = value; 21 | RaisePropertyChanged("ButtonWidth"); 22 | } 23 | } 24 | 25 | public string Display 26 | { 27 | get { return _display; } 28 | set 29 | { 30 | _display = value; 31 | RaisePropertyChanged("Display"); 32 | } 33 | } 34 | 35 | public bool IsActive 36 | { 37 | get { return _isActive; } 38 | set 39 | { 40 | _isActive = value; 41 | RaisePropertyChanged("IsActive"); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /WPFKeyboard/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows; 7 | 8 | namespace WPFKeyboard 9 | { 10 | public static class Helpers 11 | { 12 | private static bool? _isInDesignMode; 13 | 14 | /// 15 | /// Gets a value indicating whether the control is in design mode (running in Blend 16 | /// or Visual Studio). 17 | /// 18 | public static bool IsInDesignMode 19 | { 20 | get 21 | { 22 | if (!_isInDesignMode.HasValue) 23 | { 24 | var prop = DesignerProperties.IsInDesignModeProperty; 25 | _isInDesignMode 26 | = (bool)DependencyPropertyDescriptor 27 | .FromProperty(prop, typeof(FrameworkElement)) 28 | .Metadata.DefaultValue; 29 | 30 | if (!_isInDesignMode.Value) 31 | if (System.Diagnostics.Process.GetCurrentProcess().ProcessName.StartsWith(@"devenv")) 32 | _isInDesignMode = true; 33 | 34 | } 35 | return _isInDesignMode.Value; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /WPFKeyboard/Models/ModifierKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using WindowsInput.Native; 6 | 7 | namespace WPFKeyboard.Models 8 | { 9 | public class ModifierKey : BaseOnScreenKeyViewModel, IKeyEventListener 10 | { 11 | private readonly VirtualKeyCode _key; 12 | private readonly VirtualKeyCode[] _additional; 13 | 14 | public ModifierKey(VirtualKeyCode key, params VirtualKeyCode[] additional) 15 | { 16 | _key = key; 17 | _additional = additional; 18 | if(_additional == null) 19 | _additional = new VirtualKeyCode[0]; 20 | } 21 | 22 | public void KeyDown(System.Windows.Forms.KeyEventArgs args) 23 | { 24 | if ((int)args.KeyCode == (int)_key || _additional.Any(x => (int)x == (int)args.KeyCode)) 25 | { 26 | IsActive = true; 27 | } 28 | } 29 | 30 | public void KeyPressed(System.Windows.Forms.KeyPressEventArgs character) 31 | { 32 | } 33 | 34 | public void KeyUp(System.Windows.Forms.KeyEventArgs args) 35 | { 36 | if ((int)args.KeyCode == (int)_key || _additional.Any(x => (int)x == (int)args.KeyCode)) 37 | { 38 | IsActive = false; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/temp/KLL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "kbd.h" 3 | #include "kbd64.h" 4 | #include 5 | 6 | //Loaddefs for a 32/64-bit handle of keyboard-loading 7 | typedef PKBDTABLES(* KbdLayerDescriptor)(VOID); 8 | typedef PKBDTABLES64(* KbdLayerDescriptor64)(VOID); 9 | typedef PVOID(*PFN_KBDLAYERDESCRIPTOR)(VOID); 10 | 11 | class CKLL 12 | { 13 | public: 14 | CKLL(void); 15 | ~CKLL(void); 16 | 17 | //Public functions to return info regarding the keyboard-dll loaded 18 | BOOL LoadDLL(char* sKeyboardDll); 19 | USHORT GetVKCount(); 20 | 21 | //Return TRUE if x64, false if not... 22 | BOOL Is64BitWindows(); 23 | 24 | ////////////////////////////////////////////////////////////////////////// 25 | //Structs to handle all keys assigned to a VK 26 | struct VK_STRUCT 27 | { 28 | USHORT nVK; 29 | BYTE attributes; 30 | std::vector aSC; 31 | std::vector aChar; 32 | }; 33 | 34 | CKLL::VK_STRUCT* CKLL::GetVKAtIndex(BYTE index); 35 | private: 36 | //Our loaded DLL 37 | HMODULE hHandle; 38 | void UnloadDLL(); 39 | 40 | //The actual DLL-function that init and fill the array 41 | PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor; 42 | 43 | //32-bit variables 44 | PKBDTABLES KbdTables; 45 | void Fill32(); 46 | 47 | //64-bit variables 48 | PKBDTABLES64 KbdTables64; 49 | void Fill64(); 50 | 51 | //Variable to keep track of VKs 52 | std::vector m_vkarray; 53 | 54 | void ClearVKChar(); 55 | }; 56 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayoutDlg.h: -------------------------------------------------------------------------------- 1 | 2 | // KeyboardLayoutDlg.h : header file 3 | // 4 | 5 | #pragma once 6 | #include "afxcmn.h" 7 | #include "KLL.h" 8 | #include "afxwin.h" 9 | #include "KeyboardScanCode.h" 10 | 11 | 12 | // CKeyboardLayoutDlg dialog 13 | class CKeyboardLayoutDlg : public CDialogEx 14 | { 15 | // Construction 16 | public: 17 | CKeyboardLayoutDlg(CWnd* pParent = NULL); // standard constructor 18 | 19 | // Dialog Data 20 | enum { IDD = IDD_KEYBOARDLAYOUT_DIALOG }; 21 | 22 | protected: 23 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 24 | 25 | 26 | // Implementation 27 | protected: 28 | HICON m_hIcon; 29 | 30 | //Sets welcome info and listview columns 31 | void SetListView(); 32 | 33 | // List for showing chars and VK related 34 | CListCtrl m_list; 35 | 36 | //The Keyboard Layout Loader (KLL) manage 32/64-bit loading between 37 | CKLL m_kll; 38 | 39 | //Scan code presentation to comparison of the layout in "real life" 40 | CKeyboardScanCode *pScanCodeDlg; 41 | 42 | // Generated message map functions 43 | virtual BOOL OnInitDialog(); 44 | afx_msg void OnPaint(); 45 | afx_msg HCURSOR OnQueryDragIcon(); 46 | DECLARE_MESSAGE_MAP() 47 | public: 48 | afx_msg void OnBnClickedOk(); 49 | afx_msg void OnBnClickedCancel(); 50 | afx_msg void OnBnClickedLoadkbl(); 51 | CStatic m_system; 52 | CStatic m_dll; 53 | afx_msg void OnBnClickedShowscancode(); 54 | CButton m_scancodes; 55 | }; 56 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/AssemblyInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | using namespace System; 4 | using namespace System::Reflection; 5 | using namespace System::Runtime::CompilerServices; 6 | using namespace System::Runtime::InteropServices; 7 | using namespace System::Security::Permissions; 8 | 9 | // 10 | // General Information about an assembly is controlled through the following 11 | // set of attributes. Change these attribute values to modify the information 12 | // associated with an assembly. 13 | // 14 | [assembly:AssemblyTitleAttribute("WPFKeyboardNative")]; 15 | [assembly:AssemblyDescriptionAttribute("")]; 16 | [assembly:AssemblyConfigurationAttribute("")]; 17 | [assembly:AssemblyCompanyAttribute("")]; 18 | [assembly:AssemblyProductAttribute("WPFKeyboardNative")]; 19 | [assembly:AssemblyCopyrightAttribute("Copyright (c) 2014")]; 20 | [assembly:AssemblyTrademarkAttribute("")]; 21 | [assembly:AssemblyCultureAttribute("")]; 22 | 23 | // 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the value or you can default the Revision and Build Numbers 32 | // by using the '*' as shown below: 33 | 34 | [assembly:AssemblyVersionAttribute("1.0.*")]; 35 | 36 | [assembly:ComVisible(false)]; 37 | 38 | [assembly:CLSCompliantAttribute(true)]; 39 | 40 | [assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; 41 | -------------------------------------------------------------------------------- /WPFKeyboard.KBD/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WPFKeyboard.KBD")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WPFKeyboard.KBD")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d0caa94a-cb5b-4c75-a279-cce7c0766a26")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KLL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "kbd.h" 3 | #include "kbd64.h" 4 | 5 | //Loaddefs for a 32/64-bit handle of keyboard-loading 6 | typedef PKBDTABLES(* KbdLayerDescriptor)(VOID); 7 | typedef PKBDTABLES64(* KbdLayerDescriptor64)(VOID); 8 | typedef PVOID(*PFN_KBDLAYERDESCRIPTOR)(VOID); 9 | 10 | class CKLL 11 | { 12 | public: 13 | CKLL(void); 14 | ~CKLL(void); 15 | 16 | //Public functions to return info regarding the keyboard-dll loaded 17 | BOOL LoadDLL(CString sKeyboardDll); 18 | USHORT GetVKCount(); 19 | CString GetChar(USHORT iVK); 20 | CString GetSC(USHORT iVK); 21 | 22 | //Return TRUE if x64, false if not... 23 | BOOL Is64BitWindows(); 24 | 25 | private: 26 | //Our loaded DLL 27 | HMODULE hHandle; 28 | void UnloadDLL(); 29 | 30 | //The actual DLL-function that init and fill the array 31 | PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor; 32 | 33 | //32-bit variables 34 | PKBDTABLES KbdTables; 35 | void Fill32(); 36 | 37 | //64-bit variables 38 | PKBDTABLES64 KbdTables64; 39 | void Fill64(); 40 | 41 | ////////////////////////////////////////////////////////////////////////// 42 | //Structs to handle all keys assigned to a VK 43 | struct VK_STRUCT 44 | { 45 | USHORT nVK; 46 | CUIntArray aSC; 47 | CStringArray aChar; 48 | }; 49 | 50 | //Variable to keep track of VKs 51 | std::vector m_vkarray; 52 | 53 | //Function to add / clear new VK-char 54 | void AddVKChar(USHORT nVK, CString wChar); //Returns the characters for the available VK 55 | void AddVKSC(USHORT nVK, USHORT nSC); //Returns the scan code for the available VK 56 | int VKExist(USHORT nVK); //Returns the number in the array for the VK 57 | void ClearVKChar(); //Clears the table 58 | }; 59 | -------------------------------------------------------------------------------- /WPFKeyboard/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | using System.Windows.Markup; 8 | 9 | [assembly: AssemblyTitle("WPFKeyboard")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("WPFKeyboard")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("e57711c3-1392-489f-b3d0-34ac4b6f1d75")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.0.0.0")] 37 | [assembly: AssemblyFileVersion("1.0.0.0")] 38 | 39 | [assembly: XmlnsDefinition("http://www.domain.com/wpfKeyboard", "WPFKeyboard.Controls")] 40 | [assembly: XmlnsPrefix("http://www.domain.com/wpfKeyboard", "wpfKeyboard")] -------------------------------------------------------------------------------- /WindowsKeyboardLayout/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | DYNAMIC LINK LIBRARY : WPFKeyboardNative Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WPFKeyboardNative DLL for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WPFKeyboardNative application. 9 | 10 | WPFKeyboardNative.vcxproj 11 | This is the main project file for VC++ projects generated using an Application Wizard. 12 | It contains information about the version of Visual C++ that generated the file, and 13 | information about the platforms, configurations, and project features selected with the 14 | Application Wizard. 15 | 16 | WPFKeyboardNative.vcxproj.filters 17 | This is the filters file for VC++ projects generated using an Application Wizard. 18 | It contains information about the association between the files in your project 19 | and the filters. This association is used in the IDE to show grouping of files with 20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 21 | "Source Files" filter). 22 | 23 | WPFKeyboardNative.cpp 24 | This is the main DLL source file. 25 | 26 | WPFKeyboardNative.h 27 | This file contains a class declaration. 28 | 29 | AssemblyInfo.cpp 30 | Contains custom attributes for modifying assembly metadata. 31 | 32 | ///////////////////////////////////////////////////////////////////////////// 33 | Other notes: 34 | 35 | AppWizard uses "TODO:" to indicate parts of the source code you 36 | should add to or customize. 37 | 38 | ///////////////////////////////////////////////////////////////////////////// 39 | -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/WPFKeyboardNativeTest.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /Headers/KLL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "kbd.h" 3 | #include "kbd64.h" 4 | #include 5 | 6 | //Loaddefs for a 32/64-bit handle of keyboard-loading 7 | typedef PKBDTABLES(* KbdLayerDescriptor)(VOID); 8 | typedef PKBDTABLES64(* KbdLayerDescriptor64)(VOID); 9 | typedef PVOID(*PFN_KBDLAYERDESCRIPTOR)(VOID); 10 | 11 | 12 | 13 | class __declspec( dllexport ) CKLL 14 | { 15 | public: 16 | 17 | struct VK_STRUCT 18 | { 19 | int VirtualKey; 20 | int Attributes; 21 | std::vector Characters; 22 | }; 23 | struct VK_MODIFIER 24 | { 25 | int VirtualKey; 26 | int ModifierBits; 27 | }; 28 | struct VK_SCANCODE 29 | { 30 | int VirtualKey; 31 | int ScanCode; 32 | bool E0Set; 33 | bool E1Set; 34 | }; 35 | struct SC_TEXT 36 | { 37 | int ScanCode; 38 | wchar_t *Text; 39 | }; 40 | 41 | CKLL(void); 42 | ~CKLL(void); 43 | 44 | BOOL LoadDLL(char* sKeyboardDll); 45 | 46 | BOOL Is64BitWindows(); 47 | 48 | int GetVKCount(); 49 | CKLL::VK_STRUCT* CKLL::GetVKAtIndex(int index); 50 | 51 | int GetModifiersCount(); 52 | CKLL::VK_MODIFIER* GetModifierAtIndex(int index); 53 | 54 | int GetScanCodesCount(); 55 | CKLL::VK_SCANCODE* GetScanCodeAtIndex(int index); 56 | 57 | int GetScanCodeTextCount(); 58 | CKLL::SC_TEXT* GetScanCodeTextAtIndex(int index); 59 | 60 | private: 61 | //Our loaded DLL 62 | HMODULE hHandle; 63 | void UnloadDLL(); 64 | 65 | //The actual DLL-function that init and fill the array 66 | PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor; 67 | 68 | //32-bit variables 69 | PKBDTABLES KbdTables; 70 | void Fill32(); 71 | 72 | //64-bit variables 73 | PKBDTABLES64 KbdTables64; 74 | void Fill64(); 75 | 76 | std::vector m_vkarray; 77 | void ClearVKChar(); 78 | std::vector m_vkModifiersArray; 79 | void ClearVKModifiers(); 80 | std::vector m_vkScanCodesArray; 81 | void ClearVKScanCodes(); 82 | std::vector m_scTextArray; 83 | void ClearSCText(); 84 | }; 85 | -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : WPFKeyboardNativeTest Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WPFKeyboardNativeTest application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WPFKeyboardNativeTest application. 9 | 10 | 11 | WPFKeyboardNativeTest.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | WPFKeyboardNativeTest.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | WPFKeyboardNativeTest.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named WPFKeyboardNativeTest.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/stdafx.h: -------------------------------------------------------------------------------- 1 | 2 | // stdafx.h : include file for standard system include files, 3 | // or project specific include files that are used frequently, 4 | // but are changed infrequently 5 | 6 | #pragma once 7 | 8 | #ifndef _SECURE_ATL 9 | #define _SECURE_ATL 1 10 | #endif 11 | 12 | #ifndef VC_EXTRALEAN 13 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 14 | #endif 15 | 16 | #include "targetver.h" 17 | 18 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 19 | 20 | // turns off MFC's hiding of some common and often safely ignored warning messages 21 | #define _AFX_ALL_WARNINGS 22 | 23 | #include // MFC core and standard components 24 | #include // MFC extensions 25 | 26 | 27 | #include // MFC Automation classes 28 | 29 | 30 | 31 | #ifndef _AFX_NO_OLE_SUPPORT 32 | #include // MFC support for Internet Explorer 4 Common Controls 33 | #endif 34 | #ifndef _AFX_NO_AFXCMN_SUPPORT 35 | #include // MFC support for Windows Common Controls 36 | #endif // _AFX_NO_AFXCMN_SUPPORT 37 | 38 | #include // MFC support for ribbons and control bars 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | #ifdef _UNICODE 49 | #if defined _M_IX86 50 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 51 | #elif defined _M_X64 52 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 53 | #else 54 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 55 | #endif 56 | #endif 57 | 58 | 59 | -------------------------------------------------------------------------------- /WPFKeyboard/Models/ShiftSensitiveKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows.Forms; 7 | using System.Windows.Input; 8 | using WindowsInput.Native; 9 | using KeyEventArgs = System.Windows.Forms.KeyEventArgs; 10 | 11 | namespace WPFKeyboard.Models 12 | { 13 | public class ShiftSensitiveKey : BaseOnScreenKeyViewModel, IKeyEventListener 14 | { 15 | private readonly VirtualKeyCode _keyCode; 16 | private readonly string _normal; 17 | private readonly string _modified; 18 | private readonly string _displayText; 19 | 20 | public ShiftSensitiveKey(VirtualKeyCode keyCode, string normal, string modified, string displayText) 21 | { 22 | _keyCode = keyCode; 23 | _normal = normal; 24 | _modified = modified; 25 | _displayText = displayText; 26 | Display = !string.IsNullOrEmpty(_displayText) ? _displayText : _normal; 27 | } 28 | 29 | #region IKeyEventListener 30 | 31 | public void KeyDown(KeyEventArgs args) 32 | { 33 | if (args.KeyCode == Keys.ShiftKey || args.KeyCode == Keys.LShiftKey || args.KeyCode == Keys.RShiftKey) 34 | { 35 | Display = !string.IsNullOrEmpty(_displayText) ? _displayText : _modified; 36 | }else if ((int)args.KeyCode == (int)_keyCode) 37 | { 38 | IsActive = true; 39 | } 40 | } 41 | 42 | public void KeyPressed(KeyPressEventArgs character) 43 | { 44 | 45 | } 46 | 47 | public void KeyUp(KeyEventArgs args) 48 | { 49 | if (args.KeyCode == Keys.ShiftKey || args.KeyCode == Keys.LShiftKey || args.KeyCode == Keys.RShiftKey) 50 | { 51 | Display = !string.IsNullOrEmpty(_displayText) ? _displayText : _normal; 52 | } 53 | else if ((int)args.KeyCode == (int)_keyCode) 54 | { 55 | IsActive = false; 56 | } 57 | } 58 | 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/KeyboardLayoutHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "KeyboardLayoutHelper.h" 3 | #include "KLL.h" 4 | 5 | WPFKeyboardNative::KeyboardLayoutHelper::KeyboardLayoutHelper(void) 6 | { 7 | } 8 | 9 | WPFKeyboardNative::KeyboardLayout^ WPFKeyboardNative::KeyboardLayoutHelper::GetLayout(System::String^ keyboardLayoutDll) 10 | { 11 | CKLL *kll = nullptr; 12 | try{ 13 | 14 | kll = new CKLL(); 15 | 16 | System::IntPtr p = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(keyboardLayoutDll); 17 | char *charKeyboardLayoutDll = static_cast(p.ToPointer()); 18 | bool result = kll->LoadDLL(charKeyboardLayoutDll); 19 | System::Runtime::InteropServices::Marshal::FreeHGlobal(p); 20 | 21 | if(!result) 22 | throw gcnew Exception(String::Format("Unabled to load keyboard layout dll {0}.", keyboardLayoutDll)); 23 | 24 | KeyboardLayout^ layout = gcnew KeyboardLayout(keyboardLayoutDll); 25 | 26 | for(int i=0;i < kll->GetModifiersCount(); i++) 27 | { 28 | layout->CharModifiers->Add(gcnew CharModifier(kll->GetModifierAtIndex(i)->VirtualKey, kll->GetModifierAtIndex(i)->ModifierBits)); 29 | } 30 | 31 | for(int i=0;i < kll->GetVKCount(); i++) 32 | { 33 | CKLL::VK_STRUCT *vk = kll->GetVKAtIndex(i); 34 | 35 | array^ characters = gcnew array(vk->Characters.size()); 36 | 37 | for(int y = 0; y Characters.size(); y++) 38 | { 39 | characters[y] = (int)vk->Characters[y]; 40 | } 41 | 42 | layout->VirtualKeys->Add(gcnew VirtualKey(vk->VirtualKey, vk->Attributes, characters)); 43 | } 44 | 45 | for(int i=0;i < kll->GetScanCodesCount(); i++) 46 | { 47 | layout->ScanCodes->Add(gcnew ScanCode(kll->GetScanCodeAtIndex(i)->VirtualKey, kll->GetScanCodeAtIndex(i)->ScanCode, kll->GetScanCodeAtIndex(i)->E0Set, kll->GetScanCodeAtIndex(i)->E1Set)); 48 | } 49 | 50 | for(int i=0;i < kll->GetScanCodeTextCount(); i++) 51 | { 52 | layout->CodeText->Add(gcnew ScanCodeText(kll->GetScanCodeTextAtIndex(i)->ScanCode, gcnew String(kll->GetScanCodeTextAtIndex(i)->Text))); 53 | } 54 | 55 | return layout; 56 | } finally { 57 | if(kll != nullptr) 58 | { 59 | delete kll; 60 | kll = nullptr; 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Sample")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("Sample")] 15 | [assembly: AssemblyCopyright("Copyright © 2014")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /WPFKeyboard/IKeyEventListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace WPFKeyboard 8 | { 9 | /// 10 | /// Key view models that implement this interface will receive notifications when a key has been pressed 11 | /// 12 | public interface IKeyEventListener 13 | { 14 | /// 15 | /// Occurs when a key is pressed. 16 | /// 17 | /// The instance containing the event data. 18 | /// True if the shift key (left or right) is pressed. 19 | /// True is caps lock is on. 20 | void KeyDown(KeyEventArgs args, bool isShifting, bool isCapsLockOn); 21 | 22 | /// 23 | /// Occurs when a key is pressed. 24 | /// 25 | /// The instance containing the event data. 26 | /// True if the shift key (left or right) is pressed. 27 | /// True is caps lock is on. 28 | /// 29 | /// Key events occur in the following order: 30 | /// 31 | /// KeyDown 32 | /// KeyPress 33 | /// KeyUp 34 | /// 35 | /// The KeyPress event is not raised by non-character keys; however, the non-character keys do raise the KeyDown and KeyUp events. 36 | /// Use the KeyChar property to sample keystrokes at run time and to consume or modify a subset of common keystrokes. 37 | /// To handle keyboard events only in your application and not enable other applications to receive keyboard events, 38 | /// set the property in your form's KeyPress event-handling method to true. 39 | /// 40 | void KeyPressed(KeyPressEventArgs character, bool isShifting, bool isCapsLockOn); 41 | 42 | /// 43 | /// Occurs when a key is released. 44 | /// 45 | /// The instance containing the event data. 46 | /// True if the shift key (left or right) is pressed. 47 | /// True is caps lock is on. 48 | void KeyUp(KeyEventArgs args, bool isShifting, bool isCapsLockOn); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.cpp: -------------------------------------------------------------------------------- 1 | 2 | // KeyboardLayout.cpp : Defines the class behaviors for the application. 3 | // 4 | 5 | #include "stdafx.h" 6 | #include "KeyboardLayout.h" 7 | #include "KeyboardLayoutDlg.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #endif 12 | 13 | 14 | // CKeyboardLayoutApp 15 | 16 | BEGIN_MESSAGE_MAP(CKeyboardLayoutApp, CWinApp) 17 | ON_COMMAND(ID_HELP, &CWinApp::OnHelp) 18 | END_MESSAGE_MAP() 19 | 20 | 21 | // CKeyboardLayoutApp construction 22 | 23 | CKeyboardLayoutApp::CKeyboardLayoutApp() 24 | { 25 | // TODO: add construction code here, 26 | // Place all significant initialization in InitInstance 27 | } 28 | 29 | 30 | // The one and only CKeyboardLayoutApp object 31 | 32 | CKeyboardLayoutApp theApp; 33 | 34 | 35 | // CKeyboardLayoutApp initialization 36 | 37 | BOOL CKeyboardLayoutApp::InitInstance() 38 | { 39 | // InitCommonControlsEx() is required on Windows XP if an application 40 | // manifest specifies use of ComCtl32.dll version 6 or later to enable 41 | // visual styles. Otherwise, any window creation will fail. 42 | INITCOMMONCONTROLSEX InitCtrls; 43 | InitCtrls.dwSize = sizeof(InitCtrls); 44 | // Set this to include all the common control classes you want to use 45 | // in your application. 46 | InitCtrls.dwICC = ICC_WIN95_CLASSES; 47 | InitCommonControlsEx(&InitCtrls); 48 | 49 | CWinApp::InitInstance(); 50 | 51 | 52 | AfxEnableControlContainer(); 53 | 54 | // Create the shell manager, in case the dialog contains 55 | // any shell tree view or shell list view controls. 56 | CShellManager *pShellManager = new CShellManager; 57 | 58 | // Standard initialization 59 | // If you are not using these features and wish to reduce the size 60 | // of your final executable, you should remove from the following 61 | // the specific initialization routines you do not need 62 | // Change the registry key under which our settings are stored 63 | // TODO: You should modify this string to be something appropriate 64 | // such as the name of your company or organization 65 | SetRegistryKey(_T("Local AppWizard-Generated Applications")); 66 | 67 | CKeyboardLayoutDlg dlg; 68 | m_pMainWnd = &dlg; 69 | INT_PTR nResponse = dlg.DoModal(); 70 | if (nResponse == IDOK) 71 | { 72 | // TODO: Place code here to handle when the dialog is 73 | // dismissed with OK 74 | } 75 | else if (nResponse == IDCANCEL) 76 | { 77 | // TODO: Place code here to handle when the dialog is 78 | // dismissed with Cancel 79 | } 80 | 81 | // Delete the shell manager created above. 82 | if (pShellManager != NULL) 83 | { 84 | delete pShellManager; 85 | } 86 | 87 | // Since the dialog has been closed, return FALSE so that we exit the 88 | // application, rather than start the application's message pump. 89 | return FALSE; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | *.pubxml 98 | 99 | # NuGet Packages Directory 100 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 101 | #packages/ 102 | 103 | # Windows Azure Build Output 104 | csx 105 | *.build.csdef 106 | 107 | # Windows Store app package directory 108 | AppPackages/ 109 | 110 | # Others 111 | sql/ 112 | *.Cache 113 | ClientBin/ 114 | [Ss]tyle[Cc]op.* 115 | ~$* 116 | *~ 117 | *.dbmdl 118 | *.[Pp]ublish.xml 119 | *.pfx 120 | *.publishsettings 121 | 122 | # RIA/Silverlight projects 123 | Generated_Code/ 124 | 125 | # Backup & report files from converting an old project file to a newer 126 | # Visual Studio version. Backup files are not needed, because we have git ;-) 127 | _UpgradeReport_Files/ 128 | Backup*/ 129 | UpgradeLog*.XML 130 | UpgradeLog*.htm 131 | 132 | # SQL Server files 133 | App_Data/*.mdf 134 | App_Data/*.ldf 135 | 136 | # ========================= 137 | # Windows detritus 138 | # ========================= 139 | 140 | # Windows image file caches 141 | Thumbs.db 142 | ehthumbs.db 143 | 144 | # Folder config file 145 | Desktop.ini 146 | 147 | # Recycle Bin used on file shares 148 | $RECYCLE.BIN/ 149 | 150 | # Mac crap 151 | .DS_Store 152 | -------------------------------------------------------------------------------- /Sample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Sample/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34003 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Sample.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sample.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /WPFKeyboard/Controls/OnScreenKeyboardRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Specialized; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Data; 6 | using WPFKeyboard.Models; 7 | 8 | namespace WPFKeyboard.Controls 9 | { 10 | public class OnScreenKeyboardRow : Grid 11 | { 12 | readonly OnScreenKeyboard _onScreenKeyboard; 13 | OnScreenKeyboardRowViewModel _viewModel; 14 | 15 | public OnScreenKeyboardRow(OnScreenKeyboard onScreenKeyboard) 16 | { 17 | _onScreenKeyboard = onScreenKeyboard; 18 | DataContextChanged += OnDataContextChanged; 19 | } 20 | 21 | private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 22 | { 23 | if (_viewModel != null) 24 | { 25 | _viewModel.Keys.CollectionChanged -= OnKeysCollectionChanged; 26 | _viewModel = null; 27 | OnKeysCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 28 | } 29 | 30 | if (DataContext is OnScreenKeyboardRowViewModel) 31 | { 32 | _viewModel = DataContext as OnScreenKeyboardRowViewModel; 33 | _viewModel.Keys.CollectionChanged += OnKeysCollectionChanged; 34 | OnKeysCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 35 | } 36 | } 37 | 38 | private void OnKeysCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 39 | { 40 | if (_viewModel == null) return; 41 | 42 | // remove extra children 43 | while (Children.Count > _viewModel.Keys.Count) 44 | { 45 | var child = (OnScreenKey)Children[Children.Count - 1]; 46 | child.DataContext = null; 47 | 48 | // remote the extra child and its column definition 49 | Children.Remove(child); 50 | ColumnDefinitions[ColumnDefinitions.Count - 1].ClearValue(ColumnDefinition.WidthProperty); 51 | ColumnDefinitions.RemoveAt(ColumnDefinitions.Count - 1); 52 | } 53 | 54 | // add enough row controls to match the number of key view models we have 55 | while (Children.Count < _viewModel.Keys.Count) 56 | { 57 | Children.Add(new OnScreenKey(_onScreenKeyboard)); 58 | ColumnDefinitions.Add(new ColumnDefinition()); 59 | } 60 | 61 | // now that we have an exact number of columns, 62 | // matching the exact number of controls, 63 | // update all the data contexts 64 | foreach (var key in _viewModel.Keys) 65 | { 66 | var index = _viewModel.Keys.IndexOf(key); 67 | var control = ((OnScreenKey)Children[index]); 68 | control.DataContext = key; 69 | SetColumn(control, index); 70 | ColumnDefinitions[index].SetBinding(ColumnDefinition.WidthProperty, new Binding("ButtonWidth") { Source = key }); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {1b78efb4-1921-4634-8e2a-8215d055bb7c} 18 | 19 | 20 | {67b2bf54-9fea-4e17-990c-e3194cae5705} 21 | 22 | 23 | 24 | 25 | 26 | Resource Files 27 | 28 | 29 | Resource Files 30 | 31 | 32 | Resource Files 33 | 34 | 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | KeyboardLayoutLoader 53 | 54 | 55 | KeyboardLayoutLoader 56 | 57 | 58 | KeyboardLayoutLoader 59 | 60 | 61 | Keyboard Scancode layout 62 | 63 | 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | KeyboardLayoutLoader 73 | 74 | 75 | Source Files 76 | 77 | 78 | Keyboard Scancode layout 79 | 80 | 81 | 82 | 83 | Resource Files 84 | 85 | 86 | -------------------------------------------------------------------------------- /WPFKeyboard/Controls/OnScreenKeyboardSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using WPFKeyboard.Models; 10 | 11 | namespace WPFKeyboard.Controls 12 | { 13 | public class OnScreenKeyboardSection : Grid 14 | { 15 | readonly OnScreenKeyboard _onScreenKeyboard; 16 | OnScreenKeyboardSectionViewModel _viewModel; 17 | 18 | public OnScreenKeyboardSection(OnScreenKeyboard onScreenKeyboard) 19 | { 20 | _onScreenKeyboard = onScreenKeyboard; 21 | DataContextChanged += OnDataContextChanged; 22 | } 23 | 24 | private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 25 | { 26 | if (_viewModel != null) 27 | { 28 | _viewModel.Rows.CollectionChanged -= OnRowsCollectionChanged; 29 | _viewModel = null; 30 | OnRowsCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 31 | } 32 | 33 | if (DataContext is OnScreenKeyboardSectionViewModel) 34 | { 35 | _viewModel = DataContext as OnScreenKeyboardSectionViewModel; 36 | _viewModel.Rows.CollectionChanged += OnRowsCollectionChanged; 37 | OnRowsCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 38 | } 39 | } 40 | 41 | private void OnRowsCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 42 | { 43 | if (_viewModel == null) return; 44 | 45 | // remove extra children 46 | while (Children.Count > _viewModel.Rows.Count) 47 | { 48 | var child = Children[Children.Count - 1]; 49 | if (child is FrameworkElement) 50 | (child as FrameworkElement).DataContext = null; 51 | 52 | // remote the extra child and its row definition 53 | Children.Remove(child); 54 | RowDefinitions[RowDefinitions.Count - 1].ClearValue(RowDefinition.HeightProperty); 55 | RowDefinitions.RemoveAt(RowDefinitions.Count - 1); 56 | } 57 | 58 | // add enough row controls to match the number of row view models we have 59 | while (Children.Count < _viewModel.Rows.Count) 60 | { 61 | Children.Add(new OnScreenKeyboardRow(_onScreenKeyboard)); 62 | RowDefinitions.Add(new RowDefinition()); 63 | } 64 | 65 | // now that we have an exact number of rows, 66 | // matching the exact number of controls, 67 | // update all the data contexts 68 | foreach (var row in _viewModel.Rows) 69 | { 70 | var index = _viewModel.Rows.IndexOf(row); 71 | var keyboardSectionRow = ((OnScreenKeyboardRow)Children[index]); 72 | keyboardSectionRow.DataContext = row; 73 | SetRow(keyboardSectionRow, index); 74 | RowDefinitions[index].SetBinding(RowDefinition.HeightProperty, new Binding("RowHeight") { Source = row }); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /WPFKeyboard.KBD/WPFKeyboard.KBD.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326} 8 | Library 9 | Properties 10 | WPFKeyboard 11 | WPFKeyboard.KBD 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\Dependencies\MouseKeyboardActivityMonitor.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ..\Dependencies\WindowsInput.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {ec8eb985-a262-4dc3-8d3e-ae38786c8b7d} 59 | WindowsKeyboardLayout 60 | 61 | 62 | {1b56a2ab-181d-4c58-9230-bf3f286a5d35} 63 | WPFKeyboard 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /WPFKeyboard/Controls/OnScreenKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Data; 5 | using System.Windows.Input; 6 | using WPFKeyboard.Models; 7 | 8 | namespace WPFKeyboard.Controls 9 | { 10 | /// 11 | /// This is the button that represents a key on our keyboard 12 | /// 13 | public class OnScreenKey : Button 14 | { 15 | readonly OnScreenKeyboard _onScreenKeyboard; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public OnScreenKey(OnScreenKeyboard onScreenKeyboard) 21 | { 22 | _onScreenKeyboard = onScreenKeyboard; 23 | DataContextChanged += OnDataContextChanged; 24 | Focusable = false; 25 | SetBinding(IsActiveProperty, new Binding("IsActive")); 26 | SetBinding(StyleProperty, new Binding("OnScreenKeyStyle") { Source = _onScreenKeyboard }); 27 | PreviewMouseDown += OnMouseDown; 28 | Click += OnClick; 29 | } 30 | 31 | #region Properties 32 | 33 | /// 34 | /// See IsActive 35 | /// 36 | public static readonly DependencyProperty IsActiveProperty = 37 | DependencyProperty.Register("IsActive", typeof(bool), typeof(OnScreenKey), new PropertyMetadata(default(bool))); 38 | 39 | /// 40 | /// Is the key currently active (pressed)? 41 | /// 42 | public bool IsActive 43 | { 44 | get { return (bool)GetValue(IsActiveProperty); } 45 | set { SetValue(IsActiveProperty, value); } 46 | } 47 | 48 | /// 49 | /// The key view model for this control 50 | /// 51 | public BaseOnScreenKeyViewModel ViewModel { get { return DataContext as BaseOnScreenKeyViewModel; } } 52 | 53 | #endregion 54 | 55 | #region Events 56 | 57 | /// 58 | /// This is raised when the button is released/clicked 59 | /// 60 | /// 61 | /// 62 | private void OnClick(object sender, RoutedEventArgs routedEventArgs) 63 | { 64 | var buttonEvent = DataContext as IButtonEventListener; 65 | if (buttonEvent != null) 66 | buttonEvent.ButtonUp(); 67 | } 68 | 69 | /// 70 | /// This is raised when the mouse is pressed (but not released) 71 | /// 72 | /// 73 | /// 74 | private void OnMouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs) 75 | { 76 | var buttonEvent = DataContext as IButtonEventListener; 77 | if (buttonEvent != null) 78 | buttonEvent.ButtonDown(); 79 | } 80 | 81 | /// 82 | /// This is raised when the data context changes 83 | /// 84 | /// 85 | /// 86 | private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 87 | { 88 | Content = ViewModel != null ? _onScreenKeyboard.BuildContentControlForKey(ViewModel) : null; 89 | } 90 | 91 | protected override void OnIsPressedChanged(DependencyPropertyChangedEventArgs e) 92 | { 93 | base.OnIsPressedChanged(e); 94 | if (ViewModel != null) 95 | { 96 | ViewModel.IsActive = IsPressed; 97 | } 98 | } 99 | 100 | #endregion 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /WPFKeyboard/Keyboard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using WindowsInput; 7 | using MouseKeyboardActivityMonitor; 8 | using MouseKeyboardActivityMonitor.WinApi; 9 | 10 | namespace WPFKeyboard 11 | { 12 | /// 13 | /// Static class that allows us to easily listen to keyboard events without managing hooks/listeners, and also has the static instance of the input simulator 14 | /// 15 | public static class Keyboard 16 | { 17 | private static KeyboardHookListener _keyboardHookListener; 18 | private static InputSimulator _inputSimulator = new InputSimulator(); 19 | private static IInputDeviceStateAdaptor _inputDeviceStateAdaptor = new WindowsInputDeviceStateAdaptor(); 20 | private static readonly object Lock = new object(); 21 | 22 | /// 23 | /// Internal method that ensures that our hook is created if it isn't already 24 | /// 25 | private static void EnsureHookCreated() 26 | { 27 | lock (Lock) 28 | { 29 | if (_keyboardHookListener == null) 30 | { 31 | _keyboardHookListener = new KeyboardHookListener(new GlobalHooker()); 32 | _keyboardHookListener.Enabled = true; 33 | } 34 | } 35 | } 36 | 37 | /// 38 | /// Get the input simulator 39 | /// 40 | public static InputSimulator Simulator { get { return _inputSimulator; } } 41 | 42 | /// 43 | /// Get the input device state adapter 44 | /// 45 | public static IInputDeviceStateAdaptor InputDeviceStateAdapter { get { return _inputDeviceStateAdaptor; } } 46 | 47 | /// 48 | /// Occurs when a key is pressed. 49 | /// 50 | public static event KeyEventHandler KeyDown 51 | { 52 | add 53 | { 54 | EnsureHookCreated(); 55 | _keyboardHookListener.KeyDown += value; 56 | } 57 | remove { _keyboardHookListener.KeyDown -= value; } 58 | } 59 | 60 | /// 61 | /// Occurs when a key is pressed. 62 | /// 63 | /// 64 | /// Key events occur in the following order: 65 | /// 66 | /// KeyDown 67 | /// KeyPress 68 | /// KeyUp 69 | /// 70 | /// The KeyPress event is not raised by non-character keys; however, the non-character keys do raise the KeyDown and KeyUp events. 71 | /// Use the KeyChar property to sample keystrokes at run time and to consume or modify a subset of common keystrokes. 72 | /// To handle keyboard events only in your application and not enable other applications to receive keyboard events, 73 | /// set the property in your form's KeyPress event-handling method to true. 74 | /// 75 | public static event KeyPressEventHandler KeyPress 76 | { 77 | add 78 | { 79 | EnsureHookCreated(); 80 | _keyboardHookListener.KeyPress += value; 81 | } 82 | remove { _keyboardHookListener.KeyPress -= value; } 83 | } 84 | 85 | /// 86 | /// Occurs when a key is released. 87 | /// 88 | public static event KeyEventHandler KeyUp 89 | { 90 | add 91 | { 92 | EnsureHookCreated(); 93 | _keyboardHookListener.KeyUp += value; 94 | } 95 | remove { _keyboardHookListener.KeyUp -= value; } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/WPFKeyboardNative.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Resource Files 99 | 100 | 101 | 102 | 103 | Resource Files 104 | 105 | 106 | -------------------------------------------------------------------------------- /WPFKeyboard/WPFKeyboard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35} 8 | Library 9 | Properties 10 | WPFKeyboard 11 | WPFKeyboard 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\Dependencies\MouseKeyboardActivityMonitor.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ..\Dependencies\WindowsInput.dll 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {ec8eb985-a262-4dc3-8d3e-ae38786c8b7d} 74 | WindowsKeyboardLayout 75 | 76 | 77 | 78 | 85 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | MICROSOFT FOUNDATION CLASS LIBRARY : KeyboardLayout Project Overview 3 | =============================================================================== 4 | 5 | The application wizard has created this KeyboardLayout application for 6 | you. This application not only demonstrates the basics of using the Microsoft 7 | Foundation Classes but is also a starting point for writing your application. 8 | 9 | This file contains a summary of what you will find in each of the files that 10 | make up your KeyboardLayout application. 11 | 12 | KeyboardLayout.vcxproj 13 | This is the main project file for VC++ projects generated using an application wizard. 14 | It contains information about the version of Visual C++ that generated the file, and 15 | information about the platforms, configurations, and project features selected with the 16 | application wizard. 17 | 18 | KeyboardLayout.vcxproj.filters 19 | This is the filters file for VC++ projects generated using an Application Wizard. 20 | It contains information about the association between the files in your project 21 | and the filters. This association is used in the IDE to show grouping of files with 22 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 23 | "Source Files" filter). 24 | 25 | KeyboardLayout.h 26 | This is the main header file for the application. It includes other 27 | project specific headers (including Resource.h) and declares the 28 | CKeyboardLayoutApp application class. 29 | 30 | KeyboardLayout.cpp 31 | This is the main application source file that contains the application 32 | class CKeyboardLayoutApp. 33 | 34 | KeyboardLayout.rc 35 | This is a listing of all of the Microsoft Windows resources that the 36 | program uses. It includes the icons, bitmaps, and cursors that are stored 37 | in the RES subdirectory. This file can be directly edited in Microsoft 38 | Visual C++. Your project resources are in 1033. 39 | 40 | res\KeyboardLayout.ico 41 | This is an icon file, which is used as the application's icon. This 42 | icon is included by the main resource file KeyboardLayout.rc. 43 | 44 | res\KeyboardLayout.rc2 45 | This file contains resources that are not edited by Microsoft 46 | Visual C++. You should place all resources not editable by 47 | the resource editor in this file. 48 | 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | 52 | The application wizard creates one dialog class: 53 | 54 | KeyboardLayoutDlg.h, KeyboardLayoutDlg.cpp - the dialog 55 | These files contain your CKeyboardLayoutDlg class. This class defines 56 | the behavior of your application's main dialog. The dialog's template is 57 | in KeyboardLayout.rc, which can be edited in Microsoft Visual C++. 58 | 59 | 60 | ///////////////////////////////////////////////////////////////////////////// 61 | 62 | Other Features: 63 | 64 | ActiveX Controls 65 | The application includes support to use ActiveX controls. 66 | 67 | ///////////////////////////////////////////////////////////////////////////// 68 | 69 | Other standard files: 70 | 71 | StdAfx.h, StdAfx.cpp 72 | These files are used to build a precompiled header (PCH) file 73 | named KeyboardLayout.pch and a precompiled types file named StdAfx.obj. 74 | 75 | Resource.h 76 | This is the standard header file, which defines new resource IDs. 77 | Microsoft Visual C++ reads and updates this file. 78 | 79 | KeyboardLayout.manifest 80 | Application manifest files are used by Windows XP to describe an applications 81 | dependency on specific versions of Side-by-Side assemblies. The loader uses this 82 | information to load the appropriate assembly from the assembly cache or private 83 | from the application. The Application manifest maybe included for redistribution 84 | as an external .manifest file that is installed in the same folder as the application 85 | executable or it may be included in the executable in the form of a resource. 86 | ///////////////////////////////////////////////////////////////////////////// 87 | 88 | Other notes: 89 | 90 | The application wizard uses "TODO:" to indicate parts of the source code you 91 | should add to or customize. 92 | 93 | If your application uses MFC in a shared DLL, you will need 94 | to redistribute the MFC DLLs. If your application is in a language 95 | other than the operating system's locale, you will also have to 96 | redistribute the corresponding localized resources MFC100XXX.DLL. 97 | For more information on both of these topics, please see the section on 98 | redistributing Visual C++ applications in MSDN documentation. 99 | 100 | ///////////////////////////////////////////////////////////////////////////// 101 | -------------------------------------------------------------------------------- /WPFKeyboard.KBD/VirtualKey.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using WindowsInput.Native; 3 | using WPFKeyboard.Models; 4 | using WPFKeyboardNative; 5 | 6 | namespace WPFKeyboard 7 | { 8 | public class VirtualKey : BaseOnScreenKeyViewModel, IButtonEventListener, IKeyEventListener 9 | { 10 | private readonly VirtualKeyCode _virtualKey; 11 | private readonly List _characters; 12 | private readonly bool _isAffectedByCapsLock; 13 | private readonly string _displayText; 14 | private readonly char characterBase; 15 | private readonly char characterShift; 16 | private readonly char characterAltGraphics; 17 | private readonly char characterControl; 18 | private readonly char characterShiftControl; 19 | private readonly char characterShiftAltGraphics; 20 | 21 | public VirtualKey(VirtualKeyCode virtualKey, 22 | string displayText, 23 | List characters, 24 | bool isAffectedByCapsLock) 25 | { 26 | _virtualKey = virtualKey; 27 | _characters = characters; 28 | _isAffectedByCapsLock = isAffectedByCapsLock; 29 | _displayText = displayText; 30 | 31 | for (var x = 0; x < characters.Count; x++) 32 | { 33 | var character = default(char); 34 | var value = characters[x]; 35 | if (value == Definitions.WCH_DEAD) 36 | { 37 | character = ' '; 38 | } 39 | else if (value == Definitions.WCH_LGTR) 40 | { 41 | character = ' '; 42 | } 43 | else if (value == Definitions.WCH_NONE) 44 | { 45 | character = ' '; 46 | } 47 | else 48 | { 49 | character = (char)value; 50 | } 51 | 52 | switch (x) 53 | { 54 | case 0: 55 | characterBase = character; 56 | break; 57 | case 1: 58 | characterShift = character; 59 | break; 60 | case 2: 61 | characterAltGraphics = character; 62 | break; 63 | case 3: 64 | characterControl = character; 65 | break; 66 | case 4: 67 | characterShiftControl = character; 68 | break; 69 | case 5: 70 | characterShiftAltGraphics = character; 71 | break; 72 | } 73 | } 74 | 75 | Display = GetDisplayValue(false, false); 76 | } 77 | 78 | public void ButtonDown() 79 | { 80 | Keyboard.Simulator.Keyboard.KeyDown(_virtualKey); 81 | } 82 | 83 | public void ButtonUp() 84 | { 85 | Keyboard.Simulator.Keyboard.KeyUp(_virtualKey); 86 | } 87 | 88 | public void KeyDown(System.Windows.Forms.KeyEventArgs args, bool isShifting, bool isCapsLockOn) 89 | { 90 | if ((int)args.KeyCode == (int)_virtualKey) 91 | { 92 | IsActive = true; 93 | } 94 | 95 | Display = GetDisplayValue(isShifting, isCapsLockOn); 96 | } 97 | 98 | public void KeyPressed(System.Windows.Forms.KeyPressEventArgs character, bool isShifting, bool isCapsLockOn) 99 | { 100 | } 101 | 102 | public void KeyUp(System.Windows.Forms.KeyEventArgs args, bool isShifting, bool isCapsLockOn) 103 | { 104 | if ((int)args.KeyCode == (int)_virtualKey) 105 | { 106 | IsActive = false; 107 | } 108 | 109 | Display = GetDisplayValue(isShifting, isCapsLockOn); 110 | } 111 | 112 | public VirtualKeyCode Key { get { return _virtualKey; } } 113 | 114 | private string GetDisplayValue(bool isShift, bool isCapsLockOn) 115 | { 116 | if (!string.IsNullOrEmpty(_displayText)) 117 | return _displayText; 118 | 119 | if (_characters == null || _characters.Count == 0) 120 | return ((VirtualKeyCode)_virtualKey).ToString(); 121 | 122 | if (_isAffectedByCapsLock) 123 | { 124 | if (isCapsLockOn) 125 | { 126 | return new string(isShift ? characterBase : characterShift, 1); 127 | } 128 | return new string(isShift ? characterShift : characterBase, 1); 129 | } 130 | return new string(isShift ? characterShift : characterBase, 1); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /WindowsKeyboardLayoutTest/WindowsKeyboardLayoutTest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {F17016EA-957F-4728-8BF0-1D8893067EE8} 15 | Win32Proj 16 | WindowsKeyboardLayoutTest 17 | WindowsKeyboardLayoutTest 18 | 19 | 20 | 21 | Application 22 | true 23 | v110 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v110 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | ..\Headers;$(IncludePath) 46 | 47 | 48 | false 49 | ..\Headers;$(IncludePath) 50 | 51 | 52 | 53 | Use 54 | Level3 55 | Disabled 56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 57 | 58 | 59 | Console 60 | true 61 | 62 | 63 | 64 | 65 | Level3 66 | Use 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 71 | 72 | 73 | Console 74 | true 75 | true 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | Create 93 | Create 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Sample/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Sample/ViewModels/SampleKeyboardViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Runtime.InteropServices.ComTypes; 3 | using System.Text; 4 | using System.Windows; 5 | using WindowsInput.Native; 6 | using WPFKeyboard.Models; 7 | 8 | namespace Sample.ViewModels 9 | { 10 | public class SampleKeyboardViewModel : OnScreenKeyboardViewModel 11 | { 12 | public SampleKeyboardViewModel() 13 | { 14 | //var mainSection = new OnScreenKeyboardSectionViewModel(); 15 | //mainSection.Rows.Add(new OnScreenKeyboardRowViewModel()); 16 | //mainSection.Rows.Add(new OnScreenKeyboardRowViewModel()); 17 | //mainSection.Rows.Add(new OnScreenKeyboardRowViewModel()); 18 | //mainSection.Rows.Add(new OnScreenKeyboardRowViewModel()); 19 | //mainSection.Rows.Add(new OnScreenKeyboardRowViewModel()); 20 | 21 | //mainSection.Rows[0].Keys.Add(new VirtualKey(VirtualKeyCode.ESCAPE, "Escape")); 22 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "`", "~")); 23 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "1", "!")); 24 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "2", "@")); 25 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "3", "#")); 26 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "4", "$")); 27 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "5", "%")); 28 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "6", "^")); 29 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "7", "&")); 30 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "8", "*")); 31 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "9", "(")); 32 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "0", ")")); 33 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "-", "_")); 34 | //mainSection.Rows[0].Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.OEM_3, "=", "+")); 35 | //mainSection.Rows[0].Keys.Add(new VirtualKey(VirtualKeyCode.BACK, "Backspace"){ButtonWidth = new GridLength(2, GridUnitType.Star)}); 36 | ////new OnScreenKey { GridRow = 0, GridColumn = 0, Key = new ShiftSensitiveKey(VirtualKeyCode.OEM_3, new List { "`", "~" })}, 37 | //// new OnScreenKey { GridRow = 0, GridColumn = 1, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_1, new List { "1", "!" })}, 38 | //// new OnScreenKey { GridRow = 0, GridColumn = 2, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_2, new List { "2", "@" })}, 39 | //// new OnScreenKey { GridRow = 0, GridColumn = 3, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_3, new List { "3", "#" })}, 40 | //// new OnScreenKey { GridRow = 0, GridColumn = 4, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_4, new List { "4", "$" })}, 41 | //// new OnScreenKey { GridRow = 0, GridColumn = 5, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_5, new List { "5", "%" })}, 42 | //// new OnScreenKey { GridRow = 0, GridColumn = 6, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_6, new List { "6", "^" })}, 43 | //// new OnScreenKey { GridRow = 0, GridColumn = 7, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_7, new List { "7", "&" })}, 44 | //// new OnScreenKey { GridRow = 0, GridColumn = 8, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_8, new List { "8", "*" })}, 45 | //// new OnScreenKey { GridRow = 0, GridColumn = 9, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_9, new List { "9", "(" })}, 46 | //// new OnScreenKey { GridRow = 0, GridColumn = 10, Key = new ShiftSensitiveKey(VirtualKeyCode.VK_0, new List { "0", ")" })}, 47 | //// new OnScreenKey { GridRow = 0, GridColumn = 11, Key = new ShiftSensitiveKey(VirtualKeyCode.OEM_MINUS, new List { "-", "_" })}, 48 | //// new OnScreenKey { GridRow = 0, GridColumn = 12, Key = new ShiftSensitiveKey(VirtualKeyCode.OEM_PLUS, new List { "=", "+" })}, 49 | //// new OnScreenKey { GridRow = 0, GridColumn = 13, Key = new VirtualKey(VirtualKeyCode.BACK, "Bksp"), GridWidth = new GridLength(2, GridUnitType.Star)}, 50 | 51 | 52 | //Sections.Add(mainSection); 53 | 54 | //AddKeys(testSection1, 15); 55 | 56 | //var testSection2 = new OnScreenKeyboardSectionViewModel 57 | //{ 58 | // SectionWidth = new GridLength(1, GridUnitType.Star) 59 | //}; 60 | //testSection2.Rows.Add(new OnScreenKeyboardRowViewModel()); 61 | //testSection2.Rows.Add(new OnScreenKeyboardRowViewModel()); 62 | //testSection2.Rows.Add(new OnScreenKeyboardRowViewModel()); 63 | 64 | //Sections.Add(testSection1); 65 | //Sections.Add(testSection2); 66 | 67 | //AddKeys(testSection2, 3); 68 | } 69 | 70 | private void AddKeys(OnScreenKeyboardSectionViewModel section, int keysPerRow) 71 | { 72 | foreach (var row in section.Rows) 73 | { 74 | for (var x = 1; x <= keysPerRow; x++) 75 | { 76 | //row.Keys.Add(new ModifierKey(VirtualKeyCode.SHIFT, VirtualKeyCode.LSHIFT, VirtualKeyCode.RSHIFT)); 77 | //row.Keys.Add(new ShiftSensitiveKey(VirtualKeyCode.VK_A, "a", "A")); 78 | } 79 | row.Keys[1].ButtonWidth = new GridLength(5, GridUnitType.Star); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/WindowsKeyboardLayout.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D} 15 | v4.0 16 | ManagedCProj 17 | WindowsKeyboardLayout 18 | WindowsKeyboardLayout 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v110 25 | true 26 | Unicode 27 | 28 | 29 | DynamicLibrary 30 | false 31 | v110 32 | true 33 | Unicode 34 | 35 | 36 | v110 37 | 38 | 39 | v110 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | true 53 | .;..\Headers;$(IncludePath) 54 | 55 | 56 | false 57 | .;..\Headers;$(IncludePath) 58 | 59 | 60 | 61 | Level3 62 | Disabled 63 | WIN32;_DEBUG;%(PreprocessorDefinitions) 64 | Use 65 | 66 | 67 | true 68 | 69 | 70 | 71 | 72 | 73 | Level3 74 | WIN32;NDEBUG;%(PreprocessorDefinitions) 75 | Use 76 | 77 | 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | Create 112 | Create 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayoutDlg.cpp: -------------------------------------------------------------------------------- 1 | 2 | // KeyboardLayoutDlg.cpp : implementation file 3 | // 4 | 5 | #include "stdafx.h" 6 | #include "KeyboardLayout.h" 7 | #include "KeyboardLayoutDlg.h" 8 | #include "afxdialogex.h" 9 | 10 | #ifdef _DEBUG 11 | #define new DEBUG_NEW 12 | #endif 13 | 14 | 15 | // CKeyboardLayoutDlg dialog 16 | 17 | CKeyboardLayoutDlg::CKeyboardLayoutDlg(CWnd* pParent /*=NULL*/) 18 | : CDialogEx(CKeyboardLayoutDlg::IDD, pParent) 19 | { 20 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 21 | } 22 | 23 | void CKeyboardLayoutDlg::DoDataExchange(CDataExchange* pDX) 24 | { 25 | CDialogEx::DoDataExchange(pDX); 26 | DDX_Control(pDX, IDC_LIST, m_list); 27 | DDX_Control(pDX, IDC_X64, m_system); 28 | DDX_Control(pDX, IDC_DLL, m_dll); 29 | DDX_Control(pDX, IDC_SHOWSCANCODE, m_scancodes); 30 | } 31 | 32 | BEGIN_MESSAGE_MAP(CKeyboardLayoutDlg, CDialogEx) 33 | ON_WM_PAINT() 34 | ON_WM_QUERYDRAGICON() 35 | ON_BN_CLICKED(IDOK, &CKeyboardLayoutDlg::OnBnClickedOk) 36 | ON_BN_CLICKED(IDCANCEL, &CKeyboardLayoutDlg::OnBnClickedCancel) 37 | ON_BN_CLICKED(IDC_LOADKBL, &CKeyboardLayoutDlg::OnBnClickedLoadkbl) 38 | ON_BN_CLICKED(IDC_SHOWSCANCODE, &CKeyboardLayoutDlg::OnBnClickedShowscancode) 39 | END_MESSAGE_MAP() 40 | 41 | 42 | // CKeyboardLayoutDlg message handlers 43 | 44 | BOOL CKeyboardLayoutDlg::OnInitDialog() 45 | { 46 | CDialogEx::OnInitDialog(); 47 | 48 | // Set the icon for this dialog. The framework does this automatically 49 | // when the application's main window is not a dialog 50 | SetIcon(m_hIcon, TRUE); // Set big icon 51 | SetIcon(m_hIcon, FALSE); // Set small icon 52 | 53 | //Init the window 54 | this->SetListView(); 55 | 56 | //Create the scan code dialog for comparison 57 | pScanCodeDlg = new CKeyboardScanCode(this); 58 | pScanCodeDlg->Create(IDD_KEYBOARDLAYOUT, this); 59 | 60 | return TRUE; // return TRUE unless you set the focus to a control 61 | } 62 | 63 | // If you add a minimize button to your dialog, you will need the code below 64 | // to draw the icon. For MFC applications using the document/view model, 65 | // this is automatically done for you by the framework. 66 | 67 | void CKeyboardLayoutDlg::OnPaint() 68 | { 69 | if (IsIconic()) 70 | { 71 | CPaintDC dc(this); // device context for painting 72 | 73 | SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); 74 | 75 | // Center icon in client rectangle 76 | int cxIcon = GetSystemMetrics(SM_CXICON); 77 | int cyIcon = GetSystemMetrics(SM_CYICON); 78 | CRect rect; 79 | GetClientRect(&rect); 80 | int x = (rect.Width() - cxIcon + 1) / 2; 81 | int y = (rect.Height() - cyIcon + 1) / 2; 82 | 83 | // Draw the icon 84 | dc.DrawIcon(x, y, m_hIcon); 85 | } 86 | else 87 | { 88 | CDialogEx::OnPaint(); 89 | } 90 | } 91 | 92 | // The system calls this function to obtain the cursor to display while the user drags 93 | // the minimized window. 94 | HCURSOR CKeyboardLayoutDlg::OnQueryDragIcon() 95 | { 96 | return static_cast(m_hIcon); 97 | } 98 | 99 | void CKeyboardLayoutDlg::SetListView() 100 | { 101 | //Insert header and resize colums 102 | m_list.InsertColumn(0, L"Virtual Key"); 103 | m_list.InsertColumn(1, L"Scan code"); 104 | m_list.InsertColumn(2, L"Char"); 105 | CRect m_rect; 106 | m_list.GetClientRect(m_rect); 107 | m_list.SetColumnWidth(0, m_rect.Width()/5); 108 | m_list.SetColumnWidth(1, m_rect.Width()/5); 109 | m_list.SetColumnWidth(2, (m_rect.Width()/5)*3); 110 | m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT); 111 | 112 | //Welcome info 113 | m_list.InsertItem(0, L"How to start"); 114 | m_list.SetItemText(0, 2, L"Press the \"Load Keyboard\" and select a KBD*.dll file"); 115 | 116 | //Set text based on 64-bit or 32-bit 117 | CString sText; 118 | int nSystem = 32; 119 | if(m_kll.Is64BitWindows()) 120 | nSystem = 64; 121 | sText.Format(L"32-bit application running on a %i-bit system", nSystem); 122 | m_system.SetWindowText(sText); 123 | } 124 | 125 | void CKeyboardLayoutDlg::OnBnClickedOk() 126 | { 127 | } 128 | 129 | 130 | void CKeyboardLayoutDlg::OnBnClickedCancel() 131 | { 132 | //Delete the scancode window 133 | pScanCodeDlg->DestroyWindow(); 134 | delete pScanCodeDlg; 135 | pScanCodeDlg = NULL; 136 | CDialogEx::OnCancel(); 137 | } 138 | 139 | 140 | void CKeyboardLayoutDlg::OnBnClickedLoadkbl() 141 | { 142 | //Get the folder where kbd*.dll files are located 143 | TCHAR sFolder[MAX_PATH]; 144 | UINT nSize = GetSystemWow64Directory(sFolder, MAX_PATH); 145 | 146 | //Get the 32-bit system drive, since nSize = 0 equal no 64-bit system path 147 | if(nSize == 0) 148 | if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEMX86, NULL, 0, sFolder))) 149 | return; 150 | 151 | //Now prompt for a keyboard-dll-file 152 | OPENFILENAME ofn; 153 | WCHAR fileName[MAX_PATH] = L""; 154 | ZeroMemory(&ofn, sizeof(ofn)); 155 | ofn.lStructSize = sizeof(OPENFILENAME); 156 | ofn.lpstrInitialDir = sFolder; 157 | ofn.hwndOwner = this->GetSafeHwnd(); 158 | ofn.lpstrFilter = L"Keyboard DLLs\0kbd*.dll\0\0"; 159 | ofn.lpstrFile = fileName; 160 | ofn.nMaxFile = MAX_PATH; 161 | ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; 162 | ofn.lpstrDefExt = L""; 163 | 164 | //Only load DLL if the filename was set 165 | if ( GetOpenFileName(&ofn) ) 166 | { 167 | //Load the dll 168 | if(m_kll.LoadDLL(fileName)) 169 | { 170 | CString sDllLoad(fileName); 171 | sDllLoad.Format(L"Loaded %s", sDllLoad.Right(sDllLoad.GetLength()-sDllLoad.ReverseFind('\\')-1)); 172 | m_dll.SetWindowText(sDllLoad); 173 | 174 | //Clear old list 175 | m_list.DeleteAllItems(); 176 | 177 | //Loop through each VK and show the ScanCode (SC) and chars attached to that VK 178 | for(BYTE i=0;i < m_kll.GetVKCount(); i++) 179 | { 180 | sDllLoad.Format(L"%i", i); 181 | m_list.InsertItem(i, sDllLoad); 182 | m_list.SetItemText(i, 1, m_kll.GetSC(i)); 183 | m_list.SetItemText(i, 2, m_kll.GetChar(i)); 184 | } 185 | } 186 | } 187 | } 188 | 189 | void CKeyboardLayoutDlg::OnBnClickedShowscancode() 190 | { 191 | // TODO: Add your control notification handler code here 192 | CString sText = L" Scan Codes"; 193 | 194 | if(pScanCodeDlg->IsWindowVisible()) 195 | sText = L"Show" + sText; 196 | else 197 | sText = L"Hide" + sText; 198 | 199 | //Set text to button and show/hide window 200 | pScanCodeDlg->ShowWindow(!pScanCodeDlg->IsWindowVisible()); 201 | m_scancodes.SetWindowText(sText); 202 | } 203 | -------------------------------------------------------------------------------- /WPFKeyboard.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "Sample\Sample.csproj", "{F12F830F-6B12-4D83-925B-01B2ABE37D8B}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFKeyboard", "WPFKeyboard\WPFKeyboard.csproj", "{1B56A2AB-181D-4C58-9230-BF3F286A5D35}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D} = {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsKeyboardLayout", "WindowsKeyboardLayout\WindowsKeyboardLayout.vcxproj", "{EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}" 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsKeyboardLayoutTest", "WindowsKeyboardLayoutTest\WindowsKeyboardLayoutTest.vcxproj", "{F17016EA-957F-4728-8BF0-1D8893067EE8}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFKeyboard.KBD", "WPFKeyboard.KBD\WPFKeyboard.KBD.csproj", "{23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}" 16 | EndProject 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KBD", "KBD", "{AA19BF65-78DC-4BF4-B6FC-542188370F51}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|Mixed Platforms = Debug|Mixed Platforms 23 | Debug|Win32 = Debug|Win32 24 | Release|Any CPU = Release|Any CPU 25 | Release|Mixed Platforms = Release|Mixed Platforms 26 | Release|Win32 = Release|Win32 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 32 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Mixed Platforms.Build.0 = Debug|x86 33 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Win32.ActiveCfg = Debug|Any CPU 34 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Debug|Win32.Build.0 = Debug|Any CPU 35 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Mixed Platforms.ActiveCfg = Release|x86 38 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Mixed Platforms.Build.0 = Release|x86 39 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Win32.ActiveCfg = Release|Any CPU 40 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B}.Release|Win32.Build.0 = Release|Any CPU 41 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 44 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 45 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Win32.ActiveCfg = Debug|Any CPU 46 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Debug|Win32.Build.0 = Debug|Any CPU 47 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 50 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Mixed Platforms.Build.0 = Release|Any CPU 51 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Win32.ActiveCfg = Release|Any CPU 52 | {1B56A2AB-181D-4C58-9230-BF3F286A5D35}.Release|Win32.Build.0 = Release|Any CPU 53 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Debug|Any CPU.ActiveCfg = Debug|Win32 54 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 55 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 56 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Debug|Win32.ActiveCfg = Debug|Win32 57 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Debug|Win32.Build.0 = Debug|Win32 58 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Release|Any CPU.ActiveCfg = Release|Win32 59 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 60 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Release|Mixed Platforms.Build.0 = Release|Win32 61 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Release|Win32.ActiveCfg = Release|Win32 62 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D}.Release|Win32.Build.0 = Release|Win32 63 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Debug|Any CPU.ActiveCfg = Debug|Win32 64 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 65 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 66 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Debug|Win32.ActiveCfg = Debug|Win32 67 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Debug|Win32.Build.0 = Debug|Win32 68 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Release|Any CPU.ActiveCfg = Release|Win32 69 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 70 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Release|Mixed Platforms.Build.0 = Release|Win32 71 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Release|Win32.ActiveCfg = Release|Win32 72 | {F17016EA-957F-4728-8BF0-1D8893067EE8}.Release|Win32.Build.0 = Release|Win32 73 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 74 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Debug|Any CPU.Build.0 = Debug|Any CPU 75 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 76 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 77 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Debug|Win32.ActiveCfg = Debug|Any CPU 78 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Release|Any CPU.ActiveCfg = Release|Any CPU 79 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Release|Any CPU.Build.0 = Release|Any CPU 80 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 81 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Release|Mixed Platforms.Build.0 = Release|Any CPU 82 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326}.Release|Win32.ActiveCfg = Release|Any CPU 83 | EndGlobalSection 84 | GlobalSection(SolutionProperties) = preSolution 85 | HideSolutionNode = FALSE 86 | EndGlobalSection 87 | GlobalSection(NestedProjects) = preSolution 88 | {23207FA6-7DCA-4ECE-BE26-1D0B25E4B326} = {AA19BF65-78DC-4BF4-B6FC-542188370F51} 89 | {F17016EA-957F-4728-8BF0-1D8893067EE8} = {AA19BF65-78DC-4BF4-B6FC-542188370F51} 90 | {EC8EB985-A262-4DC3-8D3E-AE38786C8B7D} = {AA19BF65-78DC-4BF4-B6FC-542188370F51} 91 | EndGlobalSection 92 | EndGlobal 93 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KeyboardLayout.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {CF8CCD7C-CABE-4285-84EA-8410E05AA4EC} 15 | KeyboardLayout 16 | MFCProj 17 | 18 | 19 | 20 | Application 21 | true 22 | Unicode 23 | Dynamic 24 | v110 25 | 26 | 27 | Application 28 | false 29 | true 30 | Unicode 31 | Dynamic 32 | v110 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | 47 | 48 | false 49 | 50 | 51 | 52 | Use 53 | Level3 54 | Disabled 55 | WIN32;_WINDOWS;_DEBUG;_UNICODE;%(PreprocessorDefinitions) 56 | true 57 | 58 | 59 | Windows 60 | true 61 | 62 | 63 | false 64 | true 65 | _DEBUG;%(PreprocessorDefinitions) 66 | 67 | 68 | 0x0409 69 | _DEBUG;%(PreprocessorDefinitions) 70 | $(IntDir);%(AdditionalIncludeDirectories) 71 | 72 | 73 | 74 | 75 | Level3 76 | Use 77 | MaxSpeed 78 | true 79 | true 80 | WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) 81 | 82 | 83 | Windows 84 | true 85 | true 86 | true 87 | 88 | 89 | false 90 | true 91 | NDEBUG;%(PreprocessorDefinitions) 92 | 93 | 94 | 0x0409 95 | NDEBUG;%(PreprocessorDefinitions) 96 | $(IntDir);%(AdditionalIncludeDirectories) 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Create 123 | Create 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /WindowsKeyboardLayout/temp/KLL.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "KLL.h" 3 | #include 4 | 5 | ////////////////////////////////////////////////////////////////////////// 6 | // Create / destruct of CKLL class 7 | CKLL::CKLL(void) 8 | { 9 | hHandle = NULL; 10 | KbdTables = NULL; 11 | KbdTables64 = NULL; 12 | } 13 | 14 | CKLL::~CKLL(void) 15 | { 16 | this->ClearVKChar(); 17 | this->UnloadDLL(); 18 | } 19 | ////////////////////////////////////////////////////////////////////////// 20 | 21 | ////////////////////////////////////////////////////////////////////////// 22 | // Load DLL and UnloadDLL functions 23 | // Manages 32 and 64-bit system, when running a 32-bit app 24 | BOOL CKLL::LoadDLL(char* sKeyboardDll ) 25 | { 26 | std::cout << "64bit\n"; 27 | 28 | //Unload if loaded... 29 | if(hHandle) 30 | this->UnloadDLL(); 31 | 32 | //Load the dll as usual 33 | //TRACE(L"Loading Keyboard DLL %ws\n", sKeyboardDll); 34 | hHandle = LoadLibraryA(sKeyboardDll); 35 | if (!hHandle) 36 | { 37 | //AfxMessageBox(L"Failed to load dll " + sKeyboardDll); 38 | this->UnloadDLL(); 39 | return FALSE; 40 | } 41 | 42 | //Get the Keyboard import function 43 | pfnKbdLayerDescriptor = (PFN_KBDLAYERDESCRIPTOR)GetProcAddress(hHandle, "KbdLayerDescriptor"); 44 | 45 | //Return if error 46 | if(!pfnKbdLayerDescriptor) 47 | { 48 | //AfxMessageBox(L"Could not load kbdLayerDescriptor, is it a real keyboard layout file?"); 49 | this->UnloadDLL(); 50 | return FALSE; 51 | } 52 | 53 | //Get the keyboard descriptor export and set table 54 | if(!Is64BitWindows()) //32-bit 55 | { 56 | //Init the tables 57 | KbdTables = (PKBDTABLES)pfnKbdLayerDescriptor(); 58 | 59 | //If not set, unload 60 | if(!KbdTables) 61 | { 62 | this->UnloadDLL(); 63 | return FALSE; 64 | } 65 | 66 | //Clear, then fill the array 67 | this->ClearVKChar(); 68 | this->Fill32(); 69 | } 70 | else //64-bit 71 | { 72 | //Init the tables 73 | KbdTables64 = (PKBDTABLES64)pfnKbdLayerDescriptor(); 74 | 75 | //If not set, unload 76 | if(!KbdTables64) 77 | { 78 | this->UnloadDLL(); 79 | return FALSE; 80 | } 81 | 82 | //Clear, then fill the array 83 | this->ClearVKChar(); 84 | this->Fill64(); 85 | } 86 | 87 | return TRUE; 88 | } 89 | 90 | void CKLL::UnloadDLL() 91 | { 92 | //Free DLL, if loaded 93 | if(hHandle != NULL) 94 | { 95 | //TRACE(L"Free handle of keyboard dll...\n"); 96 | FreeLibrary(hHandle); 97 | hHandle = NULL; 98 | KbdTables = NULL; 99 | KbdTables64 = NULL; 100 | } 101 | } 102 | 103 | // Fill functions add all the chars based on the VK to an array 104 | void CKLL::Fill32() 105 | { 106 | std::cout << "32bit\n"; 107 | 108 | //If KbdTables aren't set, just silent return 109 | if(!KbdTables) 110 | return; 111 | 112 | /* 113 | * Modifier keys 114 | */ 115 | PMODIFIERS pCharModifiers = KbdTables->pCharModifiers; 116 | PVK_TO_BIT pVkToBit = pCharModifiers->pVkToBit; 117 | while (pVkToBit->Vk) 118 | { 119 | std::cout << "VkToBit " << pVkToBit->Vk << " -> " << pVkToBit->ModBits << "\n"; 120 | ++pVkToBit; 121 | } 122 | 123 | ////Handle all the chars with modifieres 124 | //PVK_TO_WCHAR_TABLE pVkToWchTbl = KbdTables->pVkToWcharTable; 125 | //while (pVkToWchTbl->pVkToWchars) 126 | //{ 127 | // PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars; 128 | // while (pVkToWch->VirtualKey) 129 | // { 130 | // VK_STRUCT *pVK = new VK_STRUCT(); 131 | // pVK->nVK = pVkToWch->VirtualKey; 132 | // pVK->attributes = pVkToWch->Attributes; 133 | 134 | // for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 135 | // { 136 | // pVK->aChar.insert(pVK->aChar.end(), pVkToWch->wch[i]); 137 | // } 138 | // m_vkarray.insert(m_vkarray.end(), pVK); 139 | 140 | // pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 141 | // } 142 | // ++pVkToWchTbl; 143 | //} 144 | 145 | ////If KbdTables aren't set, just silent return 146 | //if(!KbdTables) 147 | // return; 148 | 149 | ////Fill all the SC into VKs array 150 | //for (int i = 0; i < KbdTables->bMaxVSCtoVK; i++) 151 | // this->AddVKSC(KbdTables->pusVSCtoVK[i], i); 152 | 153 | ////Handle all the chars with modifieres 154 | //PVK_TO_WCHAR_TABLE pVkToWchTbl = KbdTables->pVkToWcharTable; 155 | //while (pVkToWchTbl->pVkToWchars) 156 | //{ 157 | // PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars; 158 | // while (pVkToWch->VirtualKey) 159 | // { 160 | // for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 161 | // { 162 | // sChar.Format(L"%wc (%.4x)", pVkToWch->wch[i], pVkToWch->wch[i]); 163 | // this->AddVKChar(pVkToWch->VirtualKey, sChar); 164 | // } 165 | 166 | // pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 167 | // } 168 | // ++pVkToWchTbl; 169 | //} 170 | } 171 | 172 | void CKLL::Fill64() 173 | { 174 | std::cout << "64bit\n"; 175 | 176 | //If KbdTables64 aren't set, just silent return 177 | if(!KbdTables64) 178 | return; 179 | 180 | /* 181 | * Modifier keys 182 | */ 183 | PMODIFIERS pCharModifiers = KbdTables->pCharModifiers; 184 | PVK_TO_BIT pVkToBit = pCharModifiers->pVkToBit; 185 | while (pVkToBit->Vk) 186 | { 187 | std::cout << "VkToBit " << pVkToBit->Vk << " -> " << pVkToBit->ModBits << "\n"; 188 | ++pVkToBit; 189 | } 190 | 191 | //Handle all the chars with modifieres 192 | PVK_TO_WCHAR_TABLE64 pVkToWchTbl = KbdTables64->pVkToWcharTable; 193 | while (pVkToWchTbl->pVkToWchars) 194 | { 195 | PVK_TO_WCHARS641 pVkToWch = pVkToWchTbl->pVkToWchars; 196 | while (pVkToWch->VirtualKey) 197 | { 198 | VK_STRUCT *pVK = new VK_STRUCT(); 199 | pVK->nVK = pVkToWch->VirtualKey; 200 | pVK->attributes = pVkToWch->Attributes; 201 | 202 | for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 203 | { 204 | pVK->aChar.insert(pVK->aChar.end(), pVkToWch->wch[i]); 205 | } 206 | m_vkarray.insert(m_vkarray.end(), pVK); 207 | 208 | pVkToWch = (PVK_TO_WCHARS641)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 209 | } 210 | ++pVkToWchTbl; 211 | } 212 | } 213 | 214 | USHORT CKLL::GetVKCount() 215 | { 216 | return m_vkarray.size(); 217 | } 218 | 219 | CKLL::VK_STRUCT* CKLL::GetVKAtIndex(BYTE index) 220 | { 221 | return m_vkarray[index]; 222 | } 223 | 224 | void CKLL::ClearVKChar() 225 | { 226 | for(int i = 0;i 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F12F830F-6B12-4D83-925B-01B2ABE37D8B} 8 | Exe 9 | Properties 10 | Sample 11 | Sample 12 | v4.0 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | 17 | 18 | x86 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x86 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | true 41 | bin\x86\Debug\ 42 | DEBUG;TRACE 43 | full 44 | x86 45 | prompt 46 | MinimumRecommendedRules.ruleset 47 | 48 | 49 | bin\x86\Release\ 50 | TRACE 51 | true 52 | pdbonly 53 | x86 54 | prompt 55 | MinimumRecommendedRules.ruleset 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 4.0 67 | 68 | 69 | 70 | 71 | 72 | False 73 | ..\Dependencies\WindowsInput.dll 74 | 75 | 76 | 77 | 78 | MSBuild:Compile 79 | Designer 80 | 81 | 82 | DefaultKeyTemplate.xaml 83 | 84 | 85 | 86 | WindowsKeyTemplate.xaml 87 | 88 | 89 | 90 | Designer 91 | MSBuild:Compile 92 | 93 | 94 | Designer 95 | MSBuild:Compile 96 | 97 | 98 | MSBuild:Compile 99 | Designer 100 | 101 | 102 | App.xaml 103 | Code 104 | 105 | 106 | MainWindow.xaml 107 | Code 108 | 109 | 110 | 111 | 112 | Code 113 | 114 | 115 | True 116 | True 117 | Resources.resx 118 | 119 | 120 | True 121 | Settings.settings 122 | True 123 | 124 | 125 | ResXFileCodeGenerator 126 | Resources.Designer.cs 127 | 128 | 129 | SettingsSingleFileGenerator 130 | Settings.Designer.cs 131 | 132 | 133 | 134 | 135 | 136 | {23207fa6-7dca-4ece-be26-1d0b25e4b326} 137 | WPFKeyboard.KBD 138 | 139 | 140 | {1b56a2ab-181d-4c58-9230-bf3f286a5d35} 141 | WPFKeyboard 142 | 143 | 144 | 145 | 146 | 147 | 148 | 155 | -------------------------------------------------------------------------------- /Test/KeyboardLayout/KeyboardLayout/KLL.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "KLL.h" 3 | 4 | 5 | ////////////////////////////////////////////////////////////////////////// 6 | // Create / destruct of CKLL class 7 | CKLL::CKLL(void) 8 | { 9 | hHandle = NULL; 10 | KbdTables = NULL; 11 | KbdTables64 = NULL; 12 | } 13 | 14 | CKLL::~CKLL(void) 15 | { 16 | this->ClearVKChar(); 17 | this->UnloadDLL(); 18 | } 19 | ////////////////////////////////////////////////////////////////////////// 20 | 21 | ////////////////////////////////////////////////////////////////////////// 22 | // Load DLL and UnloadDLL functions 23 | // Manages 32 and 64-bit system, when running a 32-bit app 24 | BOOL CKLL::LoadDLL( CString sKeyboardDll ) 25 | { 26 | //Unload if loaded... 27 | if(hHandle) 28 | this->UnloadDLL(); 29 | 30 | //Load the dll as usual 31 | TRACE(L"Loading Keyboard DLL %ws\n", sKeyboardDll); 32 | hHandle = LoadLibrary(sKeyboardDll); 33 | if (!hHandle) 34 | { 35 | AfxMessageBox(L"Failed to load dll " + sKeyboardDll); 36 | this->UnloadDLL(); 37 | return FALSE; 38 | } 39 | 40 | //Get the Keyboard import function 41 | pfnKbdLayerDescriptor = (PFN_KBDLAYERDESCRIPTOR)GetProcAddress(hHandle, "KbdLayerDescriptor"); 42 | 43 | //Return if error 44 | if(!pfnKbdLayerDescriptor) 45 | { 46 | AfxMessageBox(L"Could not load kbdLayerDescriptor, is it a real keyboard layout file?"); 47 | this->UnloadDLL(); 48 | return FALSE; 49 | } 50 | 51 | //Get the keyboard descriptor export and set table 52 | if(!Is64BitWindows()) //32-bit 53 | { 54 | //Init the tables 55 | KbdTables = (PKBDTABLES)pfnKbdLayerDescriptor(); 56 | 57 | //If not set, unload 58 | if(!KbdTables) 59 | { 60 | this->UnloadDLL(); 61 | return FALSE; 62 | } 63 | 64 | //Clear, then fill the array 65 | this->ClearVKChar(); 66 | this->Fill32(); 67 | } 68 | else //64-bit 69 | { 70 | //Init the tables 71 | KbdTables64 = (PKBDTABLES64)pfnKbdLayerDescriptor(); 72 | 73 | //If not set, unload 74 | if(!KbdTables64) 75 | { 76 | this->UnloadDLL(); 77 | return FALSE; 78 | } 79 | 80 | //Clear, then fill the array 81 | this->ClearVKChar(); 82 | this->Fill64(); 83 | } 84 | 85 | return TRUE; 86 | } 87 | 88 | void CKLL::UnloadDLL() 89 | { 90 | //Free DLL, if loaded 91 | if(hHandle != NULL) 92 | { 93 | TRACE(L"Free handle of keyboard dll...\n"); 94 | FreeLibrary(hHandle); 95 | hHandle = NULL; 96 | KbdTables = NULL; 97 | KbdTables64 = NULL; 98 | } 99 | } 100 | ////////////////////////////////////////////////////////////////////////// 101 | 102 | 103 | ////////////////////////////////////////////////////////////////////////// 104 | // Fill functions add all the chars based on the VK to an array 105 | void CKLL::Fill32() 106 | { 107 | //If KbdTables aren't set, just silent return 108 | if(!KbdTables) 109 | return; 110 | 111 | //Variable to handle char 112 | CString sChar; 113 | 114 | //Fill all the SC into VKs array 115 | for (int i = 0; i < KbdTables->bMaxVSCtoVK; i++) 116 | this->AddVKSC(KbdTables->pusVSCtoVK[i], i); 117 | 118 | //Handle all the chars with modifieres 119 | PVK_TO_WCHAR_TABLE pVkToWchTbl = KbdTables->pVkToWcharTable; 120 | while (pVkToWchTbl->pVkToWchars) 121 | { 122 | PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars; 123 | while (pVkToWch->VirtualKey) 124 | { 125 | for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 126 | { 127 | sChar.Format(L"%wc (%.4x)", pVkToWch->wch[i], pVkToWch->wch[i]); 128 | this->AddVKChar(pVkToWch->VirtualKey, sChar); 129 | } 130 | 131 | pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 132 | } 133 | ++pVkToWchTbl; 134 | } 135 | } 136 | 137 | void CKLL::Fill64() 138 | { 139 | //If KbdTables64 aren't set, just silent return 140 | if(!KbdTables64) 141 | return; 142 | 143 | //Variable to handle char 144 | CString sChar; 145 | 146 | //Fill all the SC into VKs array 147 | for (int i = 0; i < KbdTables64->bMaxVSCtoVK; i++) 148 | this->AddVKSC(KbdTables64->pusVSCtoVK[i], i); 149 | 150 | //Handle all the chars with modifieres 151 | PVK_TO_WCHAR_TABLE64 pVkToWchTbl = KbdTables64->pVkToWcharTable; 152 | while (pVkToWchTbl->pVkToWchars) 153 | { 154 | PVK_TO_WCHARS641 pVkToWch = pVkToWchTbl->pVkToWchars; 155 | while (pVkToWch->VirtualKey) 156 | { 157 | for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 158 | { 159 | sChar.Format(L"%wc (%.4x)", pVkToWch->wch[i], pVkToWch->wch[i]); 160 | this->AddVKChar(pVkToWch->VirtualKey, sChar); 161 | } 162 | 163 | pVkToWch = (PVK_TO_WCHARS641)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 164 | } 165 | ++pVkToWchTbl; 166 | } 167 | } 168 | ////////////////////////////////////////////////////////////////////////// 169 | // Returns the size of our array (actually the count of VKs) 170 | USHORT CKLL::GetVKCount() 171 | { 172 | return m_vkarray.GetCount(); 173 | } 174 | ////////////////////////////////////////////////////////////////////////// 175 | 176 | ////////////////////////////////////////////////////////////////////////// 177 | // Get char returns the char(s) defined on that iVK (ignore keyboard state) 178 | CString CKLL::GetChar( USHORT iVK ) 179 | { 180 | //Return nothing, if we past the count 181 | if(iVK >= this->GetVKCount()) 182 | return L""; 183 | 184 | //Return variable 185 | CString sText = L""; 186 | 187 | //Return our chars 188 | VK_STRUCT *pVK = (VK_STRUCT*)m_vkarray.GetAt(iVK); 189 | for(int i=0;iaChar.GetCount();i++) 190 | sText = sText+pVK->aChar.GetAt(i)+L", "; 191 | 192 | //Remove the last ", " 193 | sText = sText.Left(sText.GetLength() - 2); 194 | return sText; 195 | } 196 | 197 | //Get the scan code(s) for this virtual key 198 | CString CKLL::GetSC( USHORT iVK ) 199 | { 200 | //Return nothing, if we past the count 201 | if(iVK >= this->GetVKCount()) 202 | return L""; 203 | 204 | //Return variable 205 | CString sText = L"", sSC; 206 | 207 | //Return our chars 208 | VK_STRUCT *pVK = (VK_STRUCT*)m_vkarray.GetAt(iVK); 209 | for(int i=0;iaSC.GetCount();i++) 210 | { 211 | sSC.Format(L"%x, ", pVK->aSC.GetAt(i)); 212 | sText = sText+sSC; 213 | } 214 | 215 | //Remove the last ", " 216 | sText = sText.Left(sText.GetLength() - 2); 217 | return sText; 218 | } 219 | 220 | ////////////////////////////////////////////////////////////////////////// 221 | // Array functions 222 | // Just a simple store array for VK+SC+CHARS and it doesn't care about modifiers 223 | void CKLL::AddVKChar( USHORT nVK, CString wChar ) 224 | { 225 | //Check if the VK already exists, add char if so 226 | INT_PTR iVKArray = this->VKExist(nVK); 227 | if(iVKArray!=-1) 228 | { 229 | ((VK_STRUCT *)m_vkarray.GetAt(iVKArray))->aChar.Add(wChar); 230 | return; 231 | } 232 | 233 | //Create a new item and store into the array 234 | VK_STRUCT *pVK = new VK_STRUCT(); 235 | pVK->nVK = nVK; 236 | pVK->aChar.Add(wChar); 237 | m_vkarray.Add(pVK); 238 | } 239 | 240 | 241 | void CKLL::AddVKSC( USHORT nVK, USHORT nSC ) 242 | { 243 | //Check if the VK already exists, add SC if so 244 | INT_PTR iVKArray = this->VKExist(nVK); 245 | if(iVKArray!=-1) 246 | { 247 | ((VK_STRUCT *)m_vkarray.GetAt(iVKArray))->aSC.Add(nSC); 248 | return; 249 | } 250 | 251 | //Create a new item and store into the array 252 | VK_STRUCT *pVK = new VK_STRUCT(); 253 | pVK->nVK = nVK; 254 | pVK->aSC.Add(nSC); 255 | m_vkarray.Add(pVK); 256 | } 257 | 258 | //Returns the number of where the item exists 259 | int CKLL::VKExist( USHORT nVK ) 260 | { 261 | //Check if the VK already exists, add char if so 262 | for(INT_PTR i = 0;inVK == nVK) 266 | return i; 267 | } 268 | 269 | //Not found 270 | return -1; 271 | } 272 | 273 | void CKLL::ClearVKChar() 274 | { 275 | for(INT_PTR i = 0;i 4 | 5 | ////////////////////////////////////////////////////////////////////////// 6 | // Create / destruct of CKLL class 7 | CKLL::CKLL(void) 8 | { 9 | hHandle = NULL; 10 | KbdTables = NULL; 11 | KbdTables64 = NULL; 12 | } 13 | 14 | CKLL::~CKLL(void) 15 | { 16 | this->ClearVKChar(); 17 | this->ClearVKModifiers(); 18 | this->ClearVKScanCodes(); 19 | this->ClearSCText(); 20 | this->UnloadDLL(); 21 | } 22 | ////////////////////////////////////////////////////////////////////////// 23 | 24 | ////////////////////////////////////////////////////////////////////////// 25 | // Load DLL and UnloadDLL functions 26 | // Manages 32 and 64-bit system, when running a 32-bit app 27 | BOOL CKLL::LoadDLL(char* sKeyboardDll ) 28 | { 29 | std::cout << "64bit\n"; 30 | 31 | //Unload if loaded... 32 | if(hHandle) 33 | this->UnloadDLL(); 34 | 35 | //Load the dll as usual 36 | //TRACE(L"Loading Keyboard DLL %ws\n", sKeyboardDll); 37 | hHandle = LoadLibraryA(sKeyboardDll); 38 | if (!hHandle) 39 | { 40 | //AfxMessageBox(L"Failed to load dll " + sKeyboardDll); 41 | this->UnloadDLL(); 42 | return FALSE; 43 | } 44 | 45 | //Get the Keyboard import function 46 | pfnKbdLayerDescriptor = (PFN_KBDLAYERDESCRIPTOR)GetProcAddress(hHandle, "KbdLayerDescriptor"); 47 | 48 | //Return if error 49 | if(!pfnKbdLayerDescriptor) 50 | { 51 | //AfxMessageBox(L"Could not load kbdLayerDescriptor, is it a real keyboard layout file?"); 52 | this->UnloadDLL(); 53 | return FALSE; 54 | } 55 | 56 | //Get the keyboard descriptor export and set table 57 | if(!Is64BitWindows()) //32-bit 58 | { 59 | //Init the tables 60 | KbdTables = (PKBDTABLES)pfnKbdLayerDescriptor(); 61 | 62 | //If not set, unload 63 | if(!KbdTables) 64 | { 65 | this->UnloadDLL(); 66 | return FALSE; 67 | } 68 | 69 | this->ClearVKChar(); 70 | this->ClearVKModifiers(); 71 | this->ClearVKScanCodes(); 72 | this->ClearSCText(); 73 | this->Fill32(); 74 | } 75 | else //64-bit 76 | { 77 | //Init the tables 78 | KbdTables64 = (PKBDTABLES64)pfnKbdLayerDescriptor(); 79 | 80 | //If not set, unload 81 | if(!KbdTables64) 82 | { 83 | this->UnloadDLL(); 84 | return FALSE; 85 | } 86 | 87 | this->ClearVKChar(); 88 | this->ClearVKModifiers(); 89 | this->ClearVKScanCodes(); 90 | this->ClearSCText(); 91 | this->Fill64(); 92 | } 93 | 94 | return TRUE; 95 | } 96 | 97 | void CKLL::UnloadDLL() 98 | { 99 | //Free DLL, if loaded 100 | if(hHandle != NULL) 101 | { 102 | FreeLibrary(hHandle); 103 | hHandle = NULL; 104 | KbdTables = NULL; 105 | KbdTables64 = NULL; 106 | } 107 | } 108 | 109 | // Fill functions add all the chars based on the VK to an array 110 | void CKLL::Fill32() 111 | { 112 | std::cout << "32bit\n"; 113 | 114 | //If KbdTables aren't set, just silent return 115 | if(!KbdTables) 116 | return; 117 | 118 | ///* 119 | //* Modifier keys 120 | //*/ 121 | //PMODIFIERS pCharModifiers = KbdTables->pCharModifiers; 122 | //PVK_TO_BIT pVkToBit = pCharModifiers->pVkToBit; 123 | //while (pVkToBit->Vk) 124 | //{ 125 | // std::cout << "VkToBit " << pVkToBit->Vk << " -> " << pVkToBit->ModBits << "\n"; 126 | // ++pVkToBit; 127 | //} 128 | 129 | ////Handle all the chars with modifieres 130 | //PVK_TO_WCHAR_TABLE pVkToWchTbl = KbdTables->pVkToWcharTable; 131 | //while (pVkToWchTbl->pVkToWchars) 132 | //{ 133 | // PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars; 134 | // while (pVkToWch->VirtualKey) 135 | // { 136 | // VK_STRUCT *pVK = new VK_STRUCT(); 137 | // pVK->nVK = pVkToWch->VirtualKey; 138 | // pVK->attributes = pVkToWch->Attributes; 139 | 140 | // for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 141 | // { 142 | // pVK->aChar.insert(pVK->aChar.end(), pVkToWch->wch[i]); 143 | // } 144 | // m_vkarray.insert(m_vkarray.end(), pVK); 145 | 146 | // pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 147 | // } 148 | // ++pVkToWchTbl; 149 | //} 150 | 151 | ////If KbdTables aren't set, just silent return 152 | //if(!KbdTables) 153 | // return; 154 | 155 | ////Fill all the SC into VKs array 156 | //for (int i = 0; i < KbdTables->bMaxVSCtoVK; i++) 157 | // this->AddVKSC(KbdTables->pusVSCtoVK[i], i); 158 | 159 | ////Handle all the chars with modifieres 160 | //PVK_TO_WCHAR_TABLE pVkToWchTbl = KbdTables->pVkToWcharTable; 161 | //while (pVkToWchTbl->pVkToWchars) 162 | //{ 163 | // PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars; 164 | // while (pVkToWch->VirtualKey) 165 | // { 166 | // for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 167 | // { 168 | // sChar.Format(L"%wc (%.4x)", pVkToWch->wch[i], pVkToWch->wch[i]); 169 | // this->AddVKChar(pVkToWch->VirtualKey, sChar); 170 | // } 171 | 172 | // pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 173 | // } 174 | // ++pVkToWchTbl; 175 | //} 176 | } 177 | 178 | void CKLL::Fill64() 179 | { 180 | // if KbdTables64 aren't set, just silent return 181 | if(!KbdTables64) 182 | return; 183 | 184 | // modifier keys 185 | PMODIFIERS64 pCharModifiers = KbdTables64->pCharMODIFIERS64; 186 | PVK_TO_BIT64 pVkToBit = pCharModifiers->pVkToBit; 187 | while (pVkToBit->Vk) 188 | { 189 | VK_MODIFIER *modifier = new VK_MODIFIER(); 190 | modifier->VirtualKey = pVkToBit->Vk; 191 | modifier->ModifierBits = pVkToBit->ModBits; 192 | m_vkModifiersArray.insert(m_vkModifiersArray.end(), modifier); 193 | ++pVkToBit; 194 | } 195 | 196 | // virtual keys to chars with modifieres 197 | PVK_TO_WCHAR_TABLE64 pVkToWchTbl = KbdTables64->pVkToWcharTable; 198 | while (pVkToWchTbl->pVkToWchars) 199 | { 200 | PVK_TO_WCHARS641 pVkToWch = pVkToWchTbl->pVkToWchars; 201 | while (pVkToWch->VirtualKey) 202 | { 203 | printf("Virtual Key: %d\n", pVkToWch->VirtualKey); 204 | VK_STRUCT *pVK = new VK_STRUCT(); 205 | pVK->VirtualKey = (int)pVkToWch->VirtualKey; 206 | pVK->Attributes = pVkToWch->Attributes; 207 | 208 | for (int i = 0; i < pVkToWchTbl->nModifications; ++i) 209 | { 210 | //std::wcout << "Char: " << pVkToWch->wch[i] << "\n"; 211 | printf("Char: %d\n", pVkToWch->wch[i]); 212 | pVK->Characters.insert(pVK->Characters.end(), pVkToWch->wch[i]); 213 | } 214 | m_vkarray.insert(m_vkarray.end(), pVK); 215 | 216 | pVkToWch = (PVK_TO_WCHARS641)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize); 217 | } 218 | ++pVkToWchTbl; 219 | } 220 | 221 | // virtual key scan codes 222 | for(int i = 0; i < KbdTables64->bMaxVSCtoVK; i++ ) 223 | { 224 | VK_SCANCODE *scanCode = new VK_SCANCODE(); 225 | scanCode->VirtualKey = KbdTables64->pusVSCtoVK[i]; 226 | scanCode->ScanCode = i; 227 | m_vkScanCodesArray.insert(m_vkScanCodesArray.end(), scanCode); 228 | } 229 | 230 | PVSC_VK64 E0ScanCodes = KbdTables64->pVSCtoVK_E0; 231 | while(E0ScanCodes->Vsc > 0) 232 | { 233 | VK_SCANCODE *scanCode = new VK_SCANCODE(); 234 | scanCode->VirtualKey = E0ScanCodes->Vk; 235 | scanCode->ScanCode = E0ScanCodes->Vsc; 236 | scanCode->E0Set = true; 237 | m_vkScanCodesArray.insert(m_vkScanCodesArray.end(), scanCode); 238 | E0ScanCodes++; 239 | } 240 | 241 | PVSC_VK64 E1ScanCodes = KbdTables64->pVSCtoVK_E1; 242 | while(E1ScanCodes->Vsc > 0) 243 | { 244 | VK_SCANCODE *scanCode = new VK_SCANCODE(); 245 | scanCode->VirtualKey = E1ScanCodes->Vk; 246 | scanCode->ScanCode = E1ScanCodes->Vsc; 247 | scanCode->E1Set = true; 248 | m_vkScanCodesArray.insert(m_vkScanCodesArray.end(), scanCode); 249 | E1ScanCodes++; 250 | } 251 | 252 | // virtual key text 253 | PVSC_LPWSTR64 keyNames = KbdTables64->pKeyNames; 254 | while(keyNames->vsc) 255 | { 256 | SC_TEXT *scanCodeText = new SC_TEXT(); 257 | scanCodeText->ScanCode = keyNames->vsc; 258 | scanCodeText->Text = keyNames->pwsz; 259 | m_scTextArray.insert(m_scTextArray.end(), scanCodeText); 260 | keyNames++; 261 | } 262 | 263 | ///*PDEADKEY64 pDEADKEY64 = KbdTables64->pDEADKEY64; 264 | //int count = 0; 265 | //while(pDEADKEY64){ 266 | //count++; 267 | //pDEADKEY64++; 268 | //}*/ 269 | } 270 | 271 | int CKLL::GetVKCount() 272 | { 273 | return m_vkarray.size(); 274 | } 275 | 276 | CKLL::VK_STRUCT* CKLL::GetVKAtIndex(int index) 277 | { 278 | return m_vkarray[index]; 279 | } 280 | 281 | void CKLL::ClearVKChar() 282 | { 283 | for(int i = 0;i 12 | /// This view model uses a KPD dll to build the keyboard layout. 13 | /// Supporting KPD files allows us to instantly support every windows language. 14 | /// 15 | public class KPDOnScreenKeyboardViewModel : OnScreenKeyboardViewModel 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The KPD file location. 21 | public KPDOnScreenKeyboardViewModel(string kpdFileLocation) 22 | { 23 | BuildKeyboardLayout(KeyboardLayoutHelper.GetLayout(kpdFileLocation)); 24 | } 25 | 26 | /// 27 | /// Build the keyboard layout based on the given class that represents the KPD file given in the constructor. 28 | /// 29 | /// The keyboard layout. 30 | public void BuildKeyboardLayout(KeyboardLayout keyboardLayout) 31 | { 32 | //var sb = new StringBuilder(); 33 | 34 | //sb.AppendLine("---------"); 35 | //sb.AppendLine("CharModifiers"); 36 | //sb.AppendLine("---------"); 37 | //foreach (var charModifier in keyboardLayout.CharModifiers) 38 | //{ 39 | // sb.AppendLine(string.Format("ModifierBits:{0}:VirtualKey:{1}", charModifier.ModifierBits, 40 | // charModifier.VirtualKey)); 41 | //} 42 | 43 | //sb.AppendLine("---------"); 44 | //sb.AppendLine("ScanCodeText"); 45 | //sb.AppendLine("---------"); 46 | //foreach (var scanCodeText in keyboardLayout.CodeText) 47 | //{ 48 | // sb.AppendLine(string.Format("ScanCode:{0:X}:Text:{1}", scanCodeText.ScanCode, 49 | // scanCodeText.Text)); 50 | //} 51 | 52 | //sb.AppendLine("---------"); 53 | //sb.AppendLine("ScanCodes"); 54 | //sb.AppendLine("---------"); 55 | //foreach (var scanCode in keyboardLayout.ScanCodes.Where(x => !x.E0Set && !x.E1Set)) 56 | //{ 57 | // sb.AppendLine(string.Format("ScanCode:{0:X}:VirtualKey:{1}:E0:{2}:E1:{3}", scanCode.Code, 58 | // scanCode.VirtualKey, scanCode.E0Set, scanCode.E1Set)); 59 | //} 60 | 61 | //sb.AppendLine("---------"); 62 | //sb.AppendLine("ScanCodes E0"); 63 | //sb.AppendLine("---------"); 64 | //foreach (var scanCode in keyboardLayout.ScanCodes.Where(x => x.E0Set)) 65 | //{ 66 | // sb.AppendLine(string.Format("ScanCode:{0:X}:VirtualKey:{1}:E0:{2}:E1:{3}", scanCode.Code, 67 | // scanCode.VirtualKey, scanCode.E0Set, scanCode.E1Set)); 68 | //} 69 | 70 | //sb.AppendLine("---------"); 71 | //sb.AppendLine("ScanCodes E1"); 72 | //sb.AppendLine("---------"); 73 | //foreach (var scanCode in keyboardLayout.ScanCodes.Where(x => x.E1Set)) 74 | //{ 75 | // sb.AppendLine(string.Format("ScanCode:{0:X}:VirtualKey:{1}:E0:{2}:E1:{3}", scanCode.Code, 76 | // scanCode.VirtualKey, scanCode.E0Set, scanCode.E1Set)); 77 | //} 78 | 79 | //sb.AppendLine("---------"); 80 | //sb.AppendLine("VirtualKeys"); 81 | //sb.AppendLine("---------"); 82 | //foreach (var virtualkey in keyboardLayout.VirtualKeys) 83 | //{ 84 | // sb.AppendLine(string.Format("VirtualKey:{0}:Attributes:{1}:Characters:{2}", virtualkey.Key, 85 | // virtualkey.Attributes, string.Join(" - ", virtualkey.Characters.Select(x => string.Format("{0:X}", x))))); 86 | //} 87 | 88 | //var result = sb.ToString(); 89 | 90 | var mainSection = new OnScreenKeyboardSectionViewModel(); 91 | mainSection.Rows.Add(BuildRow1(keyboardLayout)); 92 | mainSection.Rows.Add(BuildRow2(keyboardLayout)); 93 | mainSection.Rows.Add(BuildRow3(keyboardLayout)); 94 | mainSection.Rows.Add(BuildRow4(keyboardLayout)); 95 | mainSection.Rows.Add(BuildRow5(keyboardLayout)); 96 | Sections.Add(mainSection); 97 | } 98 | 99 | private OnScreenKeyboardRowViewModel BuildRow1(KeyboardLayout layout) 100 | { 101 | var row = new OnScreenKeyboardRowViewModel(); 102 | row.Keys.Add(KeyForScanCode(0x29, layout)); // ~ 103 | row.Keys.Add(KeyForScanCode(0x02, layout)); // 1 104 | row.Keys.Add(KeyForScanCode(0x03, layout)); // 2 105 | row.Keys.Add(KeyForScanCode(0x04, layout)); // 3 106 | row.Keys.Add(KeyForScanCode(0x05, layout)); // 4 107 | row.Keys.Add(KeyForScanCode(0x06, layout)); // 5 108 | row.Keys.Add(KeyForScanCode(0x07, layout)); // 6 109 | row.Keys.Add(KeyForScanCode(0x08, layout)); // 7 110 | row.Keys.Add(KeyForScanCode(0x09, layout)); // 8 111 | row.Keys.Add(KeyForScanCode(0x0A, layout)); // 9 112 | row.Keys.Add(KeyForScanCode(0x0B, layout)); // 0 113 | row.Keys.Add(KeyForScanCode(0x0C, layout)); // - 114 | row.Keys.Add(KeyForScanCode(0x0D, layout)); // + 115 | row.Keys.Add(KeyForScanCode(0x0E, layout, 20)); // backspace 116 | return row; 117 | } 118 | 119 | private OnScreenKeyboardRowViewModel BuildRow2(KeyboardLayout layout) 120 | { 121 | var row = new OnScreenKeyboardRowViewModel(); 122 | row.Keys.Add(KeyForScanCode(0x0F, layout, 15)); // tab 123 | row.Keys.Add(KeyForScanCode(0x10, layout)); // Q 124 | row.Keys.Add(KeyForScanCode(0x11, layout)); // W 125 | row.Keys.Add(KeyForScanCode(0x12, layout)); // E 126 | row.Keys.Add(KeyForScanCode(0x13, layout)); // R 127 | row.Keys.Add(KeyForScanCode(0x14, layout)); // T 128 | row.Keys.Add(KeyForScanCode(0x15, layout)); // Y 129 | row.Keys.Add(KeyForScanCode(0x16, layout)); // U 130 | row.Keys.Add(KeyForScanCode(0x17, layout)); // I 131 | row.Keys.Add(KeyForScanCode(0x18, layout)); // O 132 | row.Keys.Add(KeyForScanCode(0x19, layout)); // P 133 | row.Keys.Add(KeyForScanCode(0x1A, layout)); // [ 134 | row.Keys.Add(KeyForScanCode(0x1B, layout)); // ] 135 | row.Keys.Add(KeyForScanCode(0x2B, layout, 15)); // \ 136 | return row; 137 | } 138 | 139 | private OnScreenKeyboardRowViewModel BuildRow3(KeyboardLayout layout) 140 | { 141 | var row = new OnScreenKeyboardRowViewModel(); 142 | row.Keys.Add(KeyForScanCode(0x3A, layout, 17)); // caps lock 143 | row.Keys.Add(KeyForScanCode(0x1E, layout)); // A 144 | row.Keys.Add(KeyForScanCode(0x1F, layout)); // S 145 | row.Keys.Add(KeyForScanCode(0x20, layout)); // D 146 | row.Keys.Add(KeyForScanCode(0x21, layout)); // F 147 | row.Keys.Add(KeyForScanCode(0x22, layout)); // G 148 | row.Keys.Add(KeyForScanCode(0x23, layout)); // H 149 | row.Keys.Add(KeyForScanCode(0x24, layout)); // J 150 | row.Keys.Add(KeyForScanCode(0x25, layout)); // K 151 | row.Keys.Add(KeyForScanCode(0x26, layout)); // L 152 | row.Keys.Add(KeyForScanCode(0x27, layout)); // ; 153 | row.Keys.Add(KeyForScanCode(0x28, layout)); // ' 154 | row.Keys.Add(KeyForScanCode(0x1C, layout, 21)); // enter 155 | return row; 156 | } 157 | 158 | private OnScreenKeyboardRowViewModel BuildRow4(KeyboardLayout layout) 159 | { 160 | var row = new OnScreenKeyboardRowViewModel(); 161 | row.Keys.Add(KeyForScanCode(0x2A, layout, 21)); // left shift 162 | row.Keys.Add(KeyForScanCode(0x2C, layout)); // Z 163 | row.Keys.Add(KeyForScanCode(0x2D, layout)); // X 164 | row.Keys.Add(KeyForScanCode(0x2E, layout)); // C 165 | row.Keys.Add(KeyForScanCode(0x2F, layout)); // V 166 | row.Keys.Add(KeyForScanCode(0x30, layout)); // B 167 | row.Keys.Add(KeyForScanCode(0x31, layout)); // N 168 | row.Keys.Add(KeyForScanCode(0x32, layout)); // M 169 | row.Keys.Add(KeyForScanCode(0x33, layout)); // , 170 | row.Keys.Add(KeyForScanCode(0x34, layout)); // . 171 | row.Keys.Add(KeyForScanCode(0x35, layout)); // / 172 | row.Keys.Add(KeyForScanCode(0x36, layout, 21)); // right shift 173 | return row; 174 | } 175 | 176 | private OnScreenKeyboardRowViewModel BuildRow5(KeyboardLayout layout) 177 | { 178 | var row = new OnScreenKeyboardRowViewModel(); 179 | row.Keys.Add(KeyForScanCode(0x1D, layout)); // right control 180 | row.Keys.Add(KeyForScanCode(0x5B, layout, isE0: true)); // left windows 181 | row.Keys.Add(KeyForScanCode(0x38, layout)); // left alt 182 | row.Keys.Add(KeyForScanCode(0x39, layout, 45)); // space bar 183 | row.Keys.Add(KeyForScanCode(0x38, layout, isE0: true)); // right alt 184 | row.Keys.Add(KeyForScanCode(0x5C, layout, isE0: true)); // right windows 185 | row.Keys.Add(KeyForScanCode(0x5D, layout, isE0: true)); // menu 186 | row.Keys.Add(KeyForScanCode(0x1D, layout, isE0: true)); // right control 187 | return row; 188 | } 189 | 190 | private BaseOnScreenKeyViewModel KeyForScanCode(int scanCode, KeyboardLayout layout, int widthWeight = 10, bool isE0 = false, bool isE1 = false) 191 | { 192 | var sc = layout.ScanCodes.FirstOrDefault(x => x.Code == scanCode && x.E0Set == isE0 && x.E1Set == isE1); 193 | 194 | if (sc == null) 195 | throw new Exception(string.Format("The scan code {0:X} isn't valid.", scanCode)); 196 | 197 | var virtualKey = (VirtualKeyCode)(sc.VirtualKey & 0xFF); 198 | 199 | var virtualKeyInfo = layout.VirtualKeys.SingleOrDefault(x => x.Key == sc.VirtualKey); 200 | 201 | var scanCodeText = layout.CodeText.SingleOrDefault(x => x.ScanCode == scanCode); 202 | 203 | return new VirtualKey(virtualKey, 204 | scanCodeText != null ? scanCodeText.Text : null, 205 | virtualKeyInfo != null ? virtualKeyInfo.Characters.ToList() : new List(), 206 | virtualKeyInfo != null && virtualKeyInfo.Attributes == 1) 207 | { 208 | ButtonWidth = new GridLength(widthWeight, GridUnitType.Star) 209 | }; 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /WPFKeyboard/Controls/OnScreenKeyboard.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Diagnostics; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Forms; 8 | using WindowsInput.Native; 9 | using WPFKeyboard.Models; 10 | using Binding = System.Windows.Data.Binding; 11 | 12 | namespace WPFKeyboard.Controls 13 | { 14 | public class OnScreenKeyboard : Grid 15 | { 16 | OnScreenKeyboardViewModel _viewModel; 17 | 18 | public OnScreenKeyboard() 19 | { 20 | DataContextChanged += OnDataContextChanged; 21 | Loaded += OnLoaded; 22 | Unloaded += OnUnloaded; 23 | } 24 | 25 | #region Properties 26 | 27 | /// 28 | /// See OnScreenKeyStyle 29 | /// 30 | public static readonly DependencyProperty OnScreenKeyStyleProperty = 31 | DependencyProperty.Register("ButtonStyle", typeof(Style), typeof(OnScreenKeyboard), new PropertyMetadata(default(Style))); 32 | 33 | /// 34 | /// The style to be applied to the on screen key 35 | /// 36 | public Style OnScreenKeyStyle 37 | { 38 | get { return (Style)GetValue(OnScreenKeyStyleProperty); } 39 | set { SetValue(OnScreenKeyStyleProperty, value); } 40 | } 41 | 42 | /// 43 | /// See OnScreenKeyControlBuilder 44 | /// 45 | public static readonly DependencyProperty OnScreenKeyControlBuilderProperty = 46 | DependencyProperty.Register("OnScreenKeyControlBuilder", typeof(IOnScreenKeyControlBuilder), typeof(OnScreenKeyboard), new PropertyMetadata(new DefaultOnScreenKeyControlBuilder(), OnScreenKeyControlBuilderPropertyChangedCallback), OnScreenKeyControlBuilderValidateValueCallback); 47 | 48 | private static void OnScreenKeyControlBuilderPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 49 | { 50 | var keyboard = (OnScreenKeyboard)dependencyObject; 51 | keyboard.RefreshKeyContentControls(); 52 | } 53 | 54 | private static bool OnScreenKeyControlBuilderValidateValueCallback(object value) 55 | { 56 | if (value == null) 57 | return false; 58 | 59 | return value is IOnScreenKeyControlBuilder; 60 | } 61 | 62 | /// 63 | /// The control builder that is used to 64 | /// 65 | public IOnScreenKeyControlBuilder OnScreenKeyControlBuilder 66 | { 67 | get { return (IOnScreenKeyControlBuilder)GetValue(OnScreenKeyControlBuilderProperty); } 68 | set { SetValue(OnScreenKeyControlBuilderProperty, value); } 69 | } 70 | 71 | #endregion 72 | 73 | #region Events 74 | 75 | private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 76 | { 77 | if (_viewModel != null) 78 | { 79 | _viewModel.Sections.CollectionChanged -= OnSectionsCollectionChanged; 80 | _viewModel = null; 81 | OnSectionsCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 82 | } 83 | 84 | if (DataContext is OnScreenKeyboardViewModel) 85 | { 86 | _viewModel = DataContext as OnScreenKeyboardViewModel; 87 | _viewModel.Sections.CollectionChanged += OnSectionsCollectionChanged; 88 | OnSectionsCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 89 | } 90 | } 91 | 92 | private void OnSectionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 93 | { 94 | if (_viewModel == null) return; 95 | 96 | // remove extra children 97 | while (Children.Count > _viewModel.Sections.Count) 98 | { 99 | var child = (OnScreenKeyboardSection)Children[Children.Count - 1]; 100 | child.DataContext = null; 101 | 102 | // remote the extra child and its column definition 103 | Children.Remove(child); 104 | ColumnDefinitions[ColumnDefinitions.Count - 1].ClearValue(ColumnDefinition.WidthProperty); 105 | ColumnDefinitions.RemoveAt(ColumnDefinitions.Count - 1); 106 | } 107 | 108 | // add enough section controls to match the number of section view models we have 109 | while (Children.Count < _viewModel.Sections.Count) 110 | { 111 | Children.Add(new OnScreenKeyboardSection(this)); 112 | ColumnDefinitions.Add(new ColumnDefinition()); 113 | } 114 | 115 | // now that we have an exact number of columns, 116 | // matching the exact number of controls, 117 | // update all the data contexts 118 | foreach (var section in _viewModel.Sections) 119 | { 120 | var index = _viewModel.Sections.IndexOf(section); 121 | var keyboardSection = ((OnScreenKeyboardSection)Children[index]); 122 | keyboardSection.DataContext = section; 123 | SetColumn(keyboardSection, index); 124 | ColumnDefinitions[index].SetBinding(ColumnDefinition.WidthProperty, new Binding("SectionWidth") { Source = section }); 125 | } 126 | } 127 | 128 | private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) 129 | { 130 | if (Helpers.IsInDesignMode) return; 131 | Keyboard.KeyDown += OnKeyDown; 132 | Keyboard.KeyPress += OnKeyPress; 133 | Keyboard.KeyUp += OnKeyUp; 134 | } 135 | 136 | private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs) 137 | { 138 | if (Helpers.IsInDesignMode) return; 139 | Keyboard.KeyDown -= OnKeyDown; 140 | Keyboard.KeyPress -= OnKeyPress; 141 | Keyboard.KeyUp -= OnKeyUp; 142 | } 143 | 144 | private void OnKeyUp(object sender, System.Windows.Forms.KeyEventArgs args) 145 | { 146 | Debug.WriteLine((int)args.KeyCode); 147 | //PrintState(); 148 | bool? isShifting = null; 149 | bool? isCapsLockOn = null; 150 | 151 | foreach (var section in _viewModel.Sections) 152 | { 153 | foreach (var row in section.Rows) 154 | { 155 | foreach (var key in row.Keys) 156 | { 157 | if (key is IKeyEventListener) 158 | { 159 | if (!isShifting.HasValue) 160 | { 161 | isShifting = Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.SHIFT); 162 | if (args.KeyCode == Keys.Shift 163 | || args.KeyCode == Keys.LShiftKey 164 | || args.KeyCode == Keys.RShiftKey) 165 | isShifting = false; 166 | } 167 | if (!isCapsLockOn.HasValue) 168 | isCapsLockOn = Keyboard.InputDeviceStateAdapter.IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL); 169 | (key as IKeyEventListener).KeyUp(args, isShifting.Value, isCapsLockOn.Value); 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | private void OnKeyPress(object sender, System.Windows.Forms.KeyPressEventArgs args) 177 | { 178 | //PrintState(); 179 | bool? isShifting = null; 180 | bool? isCapsLockOn = null; 181 | 182 | foreach (var section in _viewModel.Sections) 183 | { 184 | foreach (var row in section.Rows) 185 | { 186 | foreach (var key in row.Keys) 187 | { 188 | if (key is IKeyEventListener) 189 | { 190 | if (!isShifting.HasValue) 191 | isShifting = Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.SHIFT); 192 | if (!isCapsLockOn.HasValue) 193 | isCapsLockOn = Keyboard.InputDeviceStateAdapter.IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL); 194 | (key as IKeyEventListener).KeyPressed(args, isShifting.Value, isCapsLockOn.Value); 195 | } 196 | } 197 | } 198 | } 199 | } 200 | 201 | private void OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs args) 202 | { 203 | //PrintState(); 204 | bool? isShifting = null; 205 | bool? isCapsLockOn = null; 206 | 207 | foreach (var section in _viewModel.Sections) 208 | { 209 | foreach (var row in section.Rows) 210 | { 211 | foreach (var key in row.Keys) 212 | { 213 | if (key is IKeyEventListener) 214 | { 215 | if (!isShifting.HasValue) 216 | { 217 | isShifting = Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.SHIFT); 218 | if (args.KeyCode == Keys.Shift 219 | || args.KeyCode == Keys.LShiftKey 220 | || args.KeyCode == Keys.RShiftKey) 221 | isShifting = true; 222 | } 223 | if (!isCapsLockOn.HasValue) 224 | isCapsLockOn = Keyboard.InputDeviceStateAdapter.IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL); 225 | (key as IKeyEventListener).KeyDown(args, isShifting.Value, isCapsLockOn.Value); 226 | } 227 | } 228 | } 229 | } 230 | } 231 | 232 | private void PrintState() 233 | { 234 | Debug.WriteLine("IsKeyDown(VirtualKeyCode.SHIFT) == {0}", Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.SHIFT)); 235 | Debug.WriteLine("IsKeyDown(VirtualKeyCode.RSHIFT) == {0}", Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.RSHIFT)); 236 | Debug.WriteLine("IsKeyDown(VirtualKeyCode.LSHIFT) == {0}", Keyboard.InputDeviceStateAdapter.IsKeyDown(VirtualKeyCode.LSHIFT)); 237 | Debug.WriteLine("IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL) == {0}", Keyboard.InputDeviceStateAdapter.IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL)); 238 | } 239 | 240 | #endregion 241 | 242 | #region Methods 243 | 244 | /// 245 | /// Calling this method will rebuild the controls for every key 246 | /// 247 | private void RefreshKeyContentControls() 248 | { 249 | var controlBuilder = OnScreenKeyControlBuilder; 250 | foreach (OnScreenKeyboardSection section in Children) 251 | foreach (OnScreenKeyboardRow row in section.Children) 252 | foreach (OnScreenKey key in row.Children) 253 | key.Content = controlBuilder.BuildControlForKey(key.ViewModel); 254 | } 255 | 256 | /// 257 | /// Build the control that is to be used for the given key view model 258 | /// 259 | /// The key view model. 260 | /// 261 | public object BuildContentControlForKey(BaseOnScreenKeyViewModel keyViewModel) 262 | { 263 | return OnScreenKeyControlBuilder.BuildControlForKey(keyViewModel); 264 | } 265 | 266 | #endregion 267 | 268 | 269 | } 270 | } 271 | --------------------------------------------------------------------------------