📄 multitap.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "Input.hpp"
#include "MultiTap.h"
#include <winuserm.h>
#include "Controls.hpp"
#include "Common.hpp"
#include <RegExt.h>
#define INVALID_INDEX -1
//Global boolean varibale indicates if the phone IME is enabled
static BOOL s_PhoneIMEEnabled = FALSE;
//handle of current focused edit control
static HWND s_EditControlWithFocus = NULL;
/*------------------------------------------------------------------------------
Multitap_Initialize
Allows the input library to initialize internal controls/state -
Returns: HRESULT indicating success or failure.
------------------------------------------------------------------------------*/
HRESULT
Multitap_Initialize(
void
)
{
HRESULT hr = S_OK;
DWORD Value = 0;
hr = RegistryGetDWORD(
HKEY_LOCAL_MACHINE,
L"System\\State\\VoIP",
L"PhoneIME",
&Value
);
s_PhoneIMEEnabled = (Value != 0);
return hr;
}
/*------------------------------------------------------------------------------
Multitap_Initialize
Determines whether multi tap is supported or not
------------------------------------------------------------------------------*/
BOOL
Multitap_IsEnabled(
void
)
{
return s_PhoneIMEEnabled;
}
/*------------------------------------------------------------------------------
Multitap_InsertSymbol
Inserts symbol character into focused Edit control
------------------------------------------------------------------------------*/
HRESULT
Multitap_InsertSymbol(
WCHAR Symbol
)
{
if (!s_PhoneIMEEnabled)
{
return S_FALSE;
}
if (!s_EditControlWithFocus)
{
return E_FAIL;
}
SendMessage(s_EditControlWithFocus, WM_CHAR, Symbol, 0);
return S_OK;
}
/*------------------------------------------------------------------------------
Multitap_SetFocusedEditCtrl
remember the current focused edit control, also let UIManager to refresh the
input context button
Parameters:
EditControl: the edit control that just got focus
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
Multitap_SetFocusedEditCtrl(
HWND EditControl
)
{
if (!s_PhoneIMEEnabled)
{
return S_FALSE;
}
if (!IsWindow(EditControl))
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE);
}
//Remember the current focused edit control
s_EditControlWithFocus = EditControl;
// Refresh Input menu button
SendDlgItemMessage(
GetForegroundWindow(),
IDC_MENUBAR,
WM_MENUBAR_REFRESHINPUTMENUBUTTON,
0,
0
);
return S_OK;
}
/*------------------------------------------------------------------------------
Multitap_SetInputMode
Set a specific control to a desired input mode
Parameters:
Control: the control whose input mode needs to be modified
InputMode: the desired input mode
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
Multitap_SetInputMode(
HWND Control,
DWORD InputMode
)
{
if (!s_PhoneIMEEnabled)
{
return S_FALSE;
}
if (!IsWindow(Control))
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE);
}
CommonUtilities_t::ControlType_e ControlType =
CommonUtilities_t::GetControlType(Control);
if (CommonUtilities_t::ControlTypeListbox == ControlType)
{
SendMessage(
Control,
LB_SETINPUTMODE,
0,
InputMode
);
return S_OK;
}
else if (CommonUtilities_t::ControlTypeEdit == ControlType)
{
DWORD EditStyle = GetWindowLong(Control, GWL_STYLE);
// If the edit control is ES_READONLY, SetInputMode is going to
// hit an ASSERT.
if (EditStyle & ES_READONLY)
{
return S_FALSE;
}
if (EditStyle & (VES_DIALPAD | ES_NUMBER))
{
//If edit control is number only, we need to set it to ~ES_NUMBER
//before we actually set its input mode, to avoid the assertion
Edit_t EditControl;
EditControl = Control;
EditControl.SetNumbersOnly(FALSE);
InputMode = EIM_NUMBERS;
}
return CommonUtilities_t::ToHR(
SendMessage(
Control,
EM_SETINPUTMODE,
0,
InputMode
)
);
}
return E_FAIL;
}
/*------------------------------------------------------------------------------
Multitap_GetInputMode
Get the input mode from specific control
Parameters:
Control: the handle of the control
Returns (DWORD):
------------------------------------------------------------------------------*/
DWORD
Multitap_GetInputMode(
HWND Control
)
{
DWORD InputMode = EIM_NUMBERS;
if (!s_PhoneIMEEnabled)
{
return InputMode;
}
CommonUtilities_t::ControlType_e ControlType =
CommonUtilities_t::GetControlType(Control);
if (CommonUtilities_t::ControlTypeListbox == ControlType)
{
InputMode = SendMessage(
Control,
LB_GETINPUTMODE,
0,
(LPARAM)TRUE
);
}
else if (CommonUtilities_t::ControlTypeEdit == ControlType)
{
if (((DWORD)::GetWindowLong(Control, GWL_STYLE)) & (VES_DIALPAD | ES_NUMBER))
{
return EIM_NUMBERS;
}
InputMode = SendMessage(
Control,
EM_GETINPUTMODE,
0,
(LPARAM)TRUE
);
}
return InputMode;
}
/*------------------------------------------------------------------------------
Multitap_SetActiveIMEType
Set the current focused edit control to specific ime type
Parameters:
type: the specific ime type
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
Multitap_SetActiveIMEType(
Input_t::IMEType_e type
)
{
if (!s_PhoneIMEEnabled)
{
return S_FALSE;
}
//Send the correct flags to the control
HRESULT hr = S_OK;
DWORD InputMode = 0;
switch (type)
{
case Input_t::itNum:
InputMode = EIM_NUMBERS;
break;
case Input_t::itMultitap:
InputMode = EIM_SPELL |
EIMMF_SETCLR_CAPSLOCK |
EIMMF_SETCLR_SHIFT ;
break;
case Input_t::itMultitapUppercase:
InputMode = EIM_SPELL |
EIMMF_SETCLR_CAPSLOCK |
EIMMF_CAPSLOCK |
EIMMF_SETCLR_SHIFT |
EIMMF_SHIFT;
break;
default:
ASSERT(FALSE);
return E_INVALIDARG;
}
hr = Multitap_SetInputMode(
s_EditControlWithFocus,
InputMode
);
if (SUCCEEDED(hr))
{
// Refresh Input menu button
SendDlgItemMessage(
GetForegroundWindow(),
IDC_MENUBAR,
WM_MENUBAR_REFRESHINPUTMENUBUTTON,
0,
0
);
}
return hr;
}
/*------------------------------------------------------------------------------
Multitap_GetActiveIMEType
Get the ime type of current focused edit control
Returns(ImeType): the ime type of current focused edit control
------------------------------------------------------------------------------*/
Input_t::IMEType_e
Multitap_GetActiveIMEType(
void
)
{
Input_t::IMEType_e ReturnType = Input_t::itNum;
if (!s_PhoneIMEEnabled)
{
return ReturnType;
}
DWORD InputMode = EIM_NUMBERS;
if (s_EditControlWithFocus &&
!(GetWindowLong(s_EditControlWithFocus, GWL_STYLE) & (ES_NUMBER | ES_READONLY)))
{
//Unfortunately, 0 is both an indication of error AND
//EIM_SPELL. Therefore, if the return value looks like
//EIM_SPELL, we need to verify that the last error
//hasn't been set.
//Reset the last error
SetLastError(0);
InputMode = Multitap_GetInputMode(s_EditControlWithFocus);
//Check that EIM_SPELL is the actual ret val
if (InputMode == 0 && (GetLastError() != 0))
{
//Default to numeric mode
return ReturnType;
}
}
//Check the major type
switch (InputMode & IM_MASK)
{
case EIM_SPELL:
//EIM spell could have capslock modifiers to indicate uppercase
ReturnType = (InputMode & EIMMF_CAPSLOCK) ? Input_t::itMultitapUppercase : Input_t::itMultitap;
break;
case EIM_NUMBERS:
//default to numeric
default:
ReturnType = Input_t::itNum;
break;
}
return ReturnType;
}
/*------------------------------------------------------------------------------
Multitap_ShouldDispatchHotkey
Handles a hotkey (KEYDOWN) event concerning * or # hotkeys. Input lib is free to
modify the value that will be dispatched (e.g. instead of # dispatch a
space character). Return value indicates whether the key should be dispatched
or eaten
Parameters:
idxHotkey: The index of the hotkey
pCharacterToDispatch: OUT param - the value of the character to be dispatched
Returns (BOOL): TRUE if the outparam should be dispatched, FALSE otherwise
------------------------------------------------------------------------------*/
BOOL
Multitap_ShouldDispatchHotkey(
Input_t::HotKeyId_e id,
__out WCHAR* pCharacterToDispatch
)
{
BOOL ShouldDispatch = TRUE;
if (
!s_PhoneIMEEnabled ||
!s_EditControlWithFocus ||
!pCharacterToDispatch
)
{
return ShouldDispatch;
}
Input_t::IMEType_e Type = Multitap_GetActiveIMEType();
switch (id)
{
case Input_t::hkidStar:
switch (Type)
{
case Input_t::itMultitap:
Multitap_SetActiveIMEType(Input_t::itMultitapUppercase);
ShouldDispatch = FALSE;
break;
case Input_t::itMultitapUppercase:
Multitap_SetActiveIMEType(Input_t::itMultitap);
ShouldDispatch = FALSE;
break;
case Input_t::itNum:
default:
break;
}
break;
case Input_t::hkidPound:
*pCharacterToDispatch = (Type == Input_t::itNum) ? L'#' : L' ';
break;
default:
ASSERT(FALSE);
break;
}
return ShouldDispatch;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -