remove Pilz.Input
This commit is contained in:
@@ -1,431 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Threading;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Pilz.Input
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Listens keyboard globally.
|
|
||||||
///
|
|
||||||
/// <remarks>Uses WH_KEYBOARD_LL.</remarks>
|
|
||||||
/// </summary>
|
|
||||||
public class KeyboardListener : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates global keyboard listener.
|
|
||||||
/// </summary>
|
|
||||||
public KeyboardListener()
|
|
||||||
{
|
|
||||||
// Dispatcher thread handling the KeyDown/KeyUp events.
|
|
||||||
this.dispatcher = Dispatcher.CurrentDispatcher;
|
|
||||||
|
|
||||||
// We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
|
|
||||||
hookedLowLevelKeyboardProc = (InterceptKeys.LowLevelKeyboardProc)LowLevelKeyboardProc;
|
|
||||||
|
|
||||||
// Set the hook
|
|
||||||
hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc);
|
|
||||||
|
|
||||||
// Assign the asynchronous callback event
|
|
||||||
hookedKeyboardCallbackAsync = new KeyboardCallbackAsync(KeyboardListener_KeyboardCallbackAsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dispatcher dispatcher;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Destroys global keyboard listener.
|
|
||||||
/// </summary>
|
|
||||||
~KeyboardListener()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when any of the keys is pressed down.
|
|
||||||
/// </summary>
|
|
||||||
public event RawKeyEventHandler KeyDown;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when any of the keys is released.
|
|
||||||
/// </summary>
|
|
||||||
public event RawKeyEventHandler KeyUp;
|
|
||||||
|
|
||||||
#region Inner workings
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hook ID
|
|
||||||
/// </summary>
|
|
||||||
private IntPtr hookId = IntPtr.Zero;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Asynchronous callback hook.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="character">Character</param>
|
|
||||||
/// <param name="keyEvent">Keyboard event</param>
|
|
||||||
/// <param name="vkCode">VKCode</param>
|
|
||||||
private delegate void KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Actual callback hook.
|
|
||||||
///
|
|
||||||
/// <remarks>Calls asynchronously the asyncCallback.</remarks>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="nCode"></param>
|
|
||||||
/// <param name="wParam"></param>
|
|
||||||
/// <param name="lParam"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
|
|
||||||
{
|
|
||||||
string chars = "";
|
|
||||||
|
|
||||||
if (nCode >= 0)
|
|
||||||
if (wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN ||
|
|
||||||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYUP ||
|
|
||||||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN ||
|
|
||||||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYUP)
|
|
||||||
{
|
|
||||||
// Captures the character(s) pressed only on WM_KEYDOWN
|
|
||||||
chars = InterceptKeys.VKCodeToString((uint)Marshal.ReadInt32(lParam),
|
|
||||||
(wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN ||
|
|
||||||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN));
|
|
||||||
|
|
||||||
hookedKeyboardCallbackAsync.BeginInvoke((InterceptKeys.KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), chars, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event to be invoked asynchronously (BeginInvoke) each time key is pressed.
|
|
||||||
/// </summary>
|
|
||||||
private KeyboardCallbackAsync hookedKeyboardCallbackAsync;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Contains the hooked callback in runtime.
|
|
||||||
/// </summary>
|
|
||||||
private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="keyEvent">Keyboard event</param>
|
|
||||||
/// <param name="vkCode">VKCode</param>
|
|
||||||
/// <param name="character">Character as string.</param>
|
|
||||||
void KeyboardListener_KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character)
|
|
||||||
{
|
|
||||||
switch (keyEvent)
|
|
||||||
{
|
|
||||||
// KeyDown events
|
|
||||||
case InterceptKeys.KeyEvent.WM_KEYDOWN:
|
|
||||||
if (KeyDown != null)
|
|
||||||
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, false, character));
|
|
||||||
break;
|
|
||||||
case InterceptKeys.KeyEvent.WM_SYSKEYDOWN:
|
|
||||||
if (KeyDown != null)
|
|
||||||
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, true, character));
|
|
||||||
break;
|
|
||||||
|
|
||||||
// KeyUp events
|
|
||||||
case InterceptKeys.KeyEvent.WM_KEYUP:
|
|
||||||
if (KeyUp != null)
|
|
||||||
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, false, character));
|
|
||||||
break;
|
|
||||||
case InterceptKeys.KeyEvent.WM_SYSKEYUP:
|
|
||||||
if (KeyUp != null)
|
|
||||||
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, true, character));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IDisposable Members
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes the hook.
|
|
||||||
/// <remarks>This call is required as it calls the UnhookWindowsHookEx.</remarks>
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
InterceptKeys.UnhookWindowsHookEx(hookId);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raw KeyEvent arguments.
|
|
||||||
/// </summary>
|
|
||||||
public class RawKeyEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// VKCode of the key.
|
|
||||||
/// </summary>
|
|
||||||
public int VKCode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// WPF Key of the key.
|
|
||||||
/// </summary>
|
|
||||||
public Key Key;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the hitted key system key.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsSysKey;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert to string.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Returns string representation of this key, if not possible empty string is returned.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Character;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unicode character of key pressed.
|
|
||||||
/// </summary>
|
|
||||||
public string Character;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create raw keyevent arguments.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="VKCode"></param>
|
|
||||||
/// <param name="isSysKey"></param>
|
|
||||||
/// <param name="Character">Character</param>
|
|
||||||
public RawKeyEventArgs(int VKCode, bool isSysKey, string Character)
|
|
||||||
{
|
|
||||||
this.VKCode = VKCode;
|
|
||||||
this.IsSysKey = isSysKey;
|
|
||||||
this.Character = Character;
|
|
||||||
this.Key = System.Windows.Input.KeyInterop.KeyFromVirtualKey(VKCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raw keyevent handler.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">sender</param>
|
|
||||||
/// <param name="args">raw keyevent arguments</param>
|
|
||||||
public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args);
|
|
||||||
|
|
||||||
#region WINAPI Helper class
|
|
||||||
/// <summary>
|
|
||||||
/// Winapi Key interception helper class.
|
|
||||||
/// </summary>
|
|
||||||
internal static class InterceptKeys
|
|
||||||
{
|
|
||||||
public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
|
|
||||||
public static int WH_KEYBOARD_LL = 13;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Key event
|
|
||||||
/// </summary>
|
|
||||||
public enum KeyEvent : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Key down
|
|
||||||
/// </summary>
|
|
||||||
WM_KEYDOWN = 256,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Key up
|
|
||||||
/// </summary>
|
|
||||||
WM_KEYUP = 257,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System key up
|
|
||||||
/// </summary>
|
|
||||||
WM_SYSKEYUP = 261,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System key down
|
|
||||||
/// </summary>
|
|
||||||
WM_SYSKEYDOWN = 260
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr SetHook(LowLevelKeyboardProc proc)
|
|
||||||
{
|
|
||||||
using (Process curProcess = Process.GetCurrentProcess())
|
|
||||||
using (ProcessModule curModule = curProcess.MainModule)
|
|
||||||
{
|
|
||||||
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
||||||
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
||||||
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, UIntPtr wParam, IntPtr lParam);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
||||||
public static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
||||||
|
|
||||||
#region Convert VKCode to string
|
|
||||||
// Note: Sometimes single VKCode represents multiple chars, thus string.
|
|
||||||
// E.g. typing "^1" (notice that when pressing 1 the both characters appear,
|
|
||||||
// because of this behavior, "^" is called dead key)
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern bool GetKeyboardState(byte[] lpKeyState);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
|
|
||||||
private static extern IntPtr GetKeyboardLayout(uint dwLayout);
|
|
||||||
|
|
||||||
[DllImport("User32.dll")]
|
|
||||||
private static extern IntPtr GetForegroundWindow();
|
|
||||||
|
|
||||||
[DllImport("User32.dll")]
|
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
private static extern uint GetCurrentThreadId();
|
|
||||||
|
|
||||||
private static uint lastVKCode = 0;
|
|
||||||
private static uint lastScanCode = 0;
|
|
||||||
private static byte[] lastKeyState = new byte[255];
|
|
||||||
private static bool lastIsDead = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert VKCode to Unicode.
|
|
||||||
/// <remarks>isKeyDown is required for because of keyboard state inconsistencies!</remarks>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="VKCode">VKCode</param>
|
|
||||||
/// <param name="isKeyDown">Is the key down event?</param>
|
|
||||||
/// <returns>String representing single unicode character.</returns>
|
|
||||||
public static string VKCodeToString(uint VKCode, bool isKeyDown)
|
|
||||||
{
|
|
||||||
// ToUnicodeEx needs StringBuilder, it populates that during execution.
|
|
||||||
System.Text.StringBuilder sbString = new System.Text.StringBuilder(5);
|
|
||||||
|
|
||||||
byte[] bKeyState = new byte[255];
|
|
||||||
bool bKeyStateStatus;
|
|
||||||
bool isDead = false;
|
|
||||||
|
|
||||||
// Gets the current windows window handle, threadID, processID
|
|
||||||
IntPtr currentHWnd = GetForegroundWindow();
|
|
||||||
uint currentProcessID;
|
|
||||||
uint currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out currentProcessID);
|
|
||||||
|
|
||||||
// This programs Thread ID
|
|
||||||
uint thisProgramThreadId = GetCurrentThreadId();
|
|
||||||
|
|
||||||
// Attach to active thread so we can get that keyboard state
|
|
||||||
if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true))
|
|
||||||
{
|
|
||||||
// Current state of the modifiers in keyboard
|
|
||||||
bKeyStateStatus = GetKeyboardState(bKeyState);
|
|
||||||
|
|
||||||
// Detach
|
|
||||||
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Could not attach, perhaps it is this process?
|
|
||||||
bKeyStateStatus = GetKeyboardState(bKeyState);
|
|
||||||
}
|
|
||||||
|
|
||||||
// On failure we return empty string.
|
|
||||||
if (!bKeyStateStatus)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
// Gets the layout of keyboard
|
|
||||||
IntPtr HKL = GetKeyboardLayout(currentWindowThreadID);
|
|
||||||
|
|
||||||
// Maps the virtual keycode
|
|
||||||
uint lScanCode = MapVirtualKeyEx(VKCode, 0, HKL);
|
|
||||||
|
|
||||||
// Keyboard state goes inconsistent if this is not in place. In other words, we need to call above commands in UP events also.
|
|
||||||
if (!isKeyDown)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
// Converts the VKCode to unicode
|
|
||||||
int relevantKeyCountInBuffer = ToUnicodeEx(VKCode, lScanCode, bKeyState, sbString, sbString.Capacity, (uint)0, HKL);
|
|
||||||
|
|
||||||
string ret = "";
|
|
||||||
|
|
||||||
switch (relevantKeyCountInBuffer)
|
|
||||||
{
|
|
||||||
// Dead keys (^,`...)
|
|
||||||
case -1:
|
|
||||||
isDead = true;
|
|
||||||
|
|
||||||
// We must clear the buffer because ToUnicodeEx messed it up, see below.
|
|
||||||
ClearKeyboardBuffer(VKCode, lScanCode, HKL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Single character in buffer
|
|
||||||
case 1:
|
|
||||||
ret = sbString[0].ToString();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Two or more (only two of them is relevant)
|
|
||||||
case 2:
|
|
||||||
default:
|
|
||||||
ret = sbString.ToString().Substring(0, 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We inject the last dead key back, since ToUnicodeEx removed it.
|
|
||||||
// More about this peculiar behavior see e.g:
|
|
||||||
// http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_23453780.html
|
|
||||||
// http://blogs.msdn.com/michkap/archive/2005/01/19/355870.aspx
|
|
||||||
// http://blogs.msdn.com/michkap/archive/2007/10/27/5717859.aspx
|
|
||||||
if (lastVKCode != 0 && lastIsDead)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder sbTemp = new System.Text.StringBuilder(5);
|
|
||||||
ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, (uint)0, HKL);
|
|
||||||
lastVKCode = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save these
|
|
||||||
lastScanCode = lScanCode;
|
|
||||||
lastVKCode = VKCode;
|
|
||||||
lastIsDead = isDead;
|
|
||||||
lastKeyState = (byte[])bKeyState.Clone();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ClearKeyboardBuffer(uint vk, uint sc, IntPtr hkl)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder sb = new System.Text.StringBuilder(10);
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
byte[] lpKeyStateNull = new Byte[255];
|
|
||||||
rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl);
|
|
||||||
} while (rc < 0);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net5.0-windows7.0</TargetFramework>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
10
Pilz.sln
10
Pilz.sln
@@ -31,8 +31,6 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Pilz.Networking", "Pilz.Net
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pilz.Cryptography", "Pilz.Cryptography\Pilz.Cryptography.csproj", "{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pilz.Cryptography", "Pilz.Cryptography\Pilz.Cryptography.csproj", "{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.Input", "Pilz.Input\Pilz.Input.csproj", "{6F52431D-5D7D-4A6F-AF88-29575F4196B3}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -153,14 +151,6 @@ Global
|
|||||||
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|x86.ActiveCfg = Release|Any CPU
|
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|x86.Build.0 = Release|Any CPU
|
{3F5988E6-439E-4A9D-B2C6-47EFFB161AC6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{6F52431D-5D7D-4A6F-AF88-29575F4196B3}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user