📄 softkeybd.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 <Sipapi.h>
#include "Common.hpp"
typedef BOOL (*PFN_SIPGETINFO)(SIPINFO*);
typedef BOOL (*PFN_SIPSETINFO)(SIPINFO*);
typedef BOOL (*PFN_SIPSHOWIM)(DWORD);
/*------------------------------------------------------------------------------
CoredllExports_t
Helper class to call SIP APIs from coredll
------------------------------------------------------------------------------*/
class CoredllExports_t
{
public:
// Load the library
static
HRESULT
Initialize(
void
)
{
s_Instance = LoadLibrary(L"coredll.dll");
if (!s_Instance)
{
return CommonUtilities_t::GetErrorFromWin32();
}
s_pfnSipGetInfo = (PFN_SIPGETINFO)GetProcAddress(s_Instance, L"SipGetInfo");
s_pfnSipSetInfo = (PFN_SIPSETINFO)GetProcAddress(s_Instance, L"SipSetInfo");
s_pfnSipShowIM = (PFN_SIPSHOWIM)GetProcAddress(s_Instance, L"SipShowIM");
if (
!s_pfnSipGetInfo ||
!s_pfnSipSetInfo ||
!s_pfnSipShowIM
)
{
return E_NOTIMPL;
}
return S_OK;
}
// Free the library
static
HRESULT
UnInitialize(
void
)
{
s_pfnSipGetInfo = NULL;
if (!s_Instance)
{
return S_FALSE;
}
FreeLibrary(s_Instance);
s_Instance = NULL;
return S_OK;
}
static
BOOL
IsSIPEnabled(
void
)
{
return (
s_Instance &&
s_pfnSipGetInfo &&
s_pfnSipSetInfo &&
s_pfnSipShowIM
);
}
static
BOOL
SipGetInfo(
__in SIPINFO* pInfo
)
{
if (!s_pfnSipGetInfo)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
return s_pfnSipGetInfo(pInfo);
}
static
BOOL
SipSetInfo(
__in SIPINFO* pInfo
)
{
if (!s_pfnSipSetInfo)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
return s_pfnSipSetInfo(pInfo);
}
static
BOOL
SipShowIM(
DWORD Show
)
{
if (!s_pfnSipShowIM)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
return s_pfnSipShowIM(Show);
}
private:
static HINSTANCE s_Instance;
static PFN_SIPGETINFO s_pfnSipGetInfo;
static PFN_SIPSETINFO s_pfnSipSetInfo;
static PFN_SIPSHOWIM s_pfnSipShowIM;
};
HINSTANCE CoredllExports_t::s_Instance = NULL;
PFN_SIPGETINFO CoredllExports_t::s_pfnSipGetInfo = NULL;
PFN_SIPSETINFO CoredllExports_t::s_pfnSipSetInfo = NULL;
PFN_SIPSHOWIM CoredllExports_t::s_pfnSipShowIM = NULL;
//Global boolean varibale indicates if the input panel is turned
//on/off by user
static BOOL s_fSoftKeybdInvokedByUser = TRUE;
//handle of current focused edit control
static HWND s_EditControlWithFocus = NULL;
BOOL
SoftKeybd_IsEnabled(
void
)
{
return CoredllExports_t::IsSIPEnabled();
}
/*------------------------------------------------------------------------------
SoftKeybd_IsVisible
Determines the current Input panel status, if it is on, return TRUE, otherwise
return FALSE
------------------------------------------------------------------------------*/
BOOL
SoftKeybd_IsVisible(
void
)
{
SIPINFO si = {0};
si.cbSize = sizeof(si);
if (CoredllExports_t::SipGetInfo(&si))
{
return (si.fdwFlags & SIPF_ON);
}
return FALSE;
}
/*------------------------------------------------------------------------------
SoftKeybd_GetTop
Get the top position of current Input panel
------------------------------------------------------------------------------*/
int SoftKeybd_GetTop()
{
SIPINFO si = {0};
si.cbSize = sizeof(si);
if (CoredllExports_t::SipGetInfo(&si))
{
return si.rcSipRect.top;
}
ASSERT(FALSE);
return 0;
}
/*------------------------------------------------------------------------------
SoftKeybd_ShowHide
Turn on/off the Input Panel
Params:
Show : indicate if we want to turn on/off the SIP panel
InvokedByUser : indicate if this operation is intended by user,
e.g. if SIP is turned off by moving cursur to a number
only edit control, then this flag should be FALSE;
if SIP is turned on/off by user pressing the 'SIP' button
then this flag should be TRUE
default value is FALSE,
Returns (BOOL): indicates success or failure
------------------------------------------------------------------------------*/
BOOL
SoftKeybd_ShowHide(
BOOL Show,
BOOL InvokedByUser = FALSE
)
{
BOOL IsSIPVisible = SoftKeybd_IsVisible();
BOOL Sucess;
// If we want to turn off the Input panel and its current status is off,
// we don't do anything.
if (!Show && !IsSIPVisible)
{
return TRUE;
}
// indicates if the Input panel is turned on/off by user
// default value is FALSE
s_fSoftKeybdInvokedByUser = InvokedByUser;
// If we want to turn on the Input panel and its current status is on,
// send a WM_SETTINGCHANGE message to the top level dialog,
// so that we don't have to turn on the SIP again
if (Show && IsSIPVisible)
{
SendMessage(
GetForegroundWindow(),
WM_SETTINGCHANGE,
SPI_SETSIPINFO,
0
);
Sucess = TRUE;
goto exit;
}
// otherwise, we turn on/off the Input panel according to the Show variable
Sucess = CoredllExports_t::SipShowIM(Show ? SIPF_ON : SIPF_OFF);
exit:
// restore the s_fSoftKeybdInvokedByUser to TRUE;
s_fSoftKeybdInvokedByUser = TRUE;
return Sucess;
}
/*------------------------------------------------------------------------------
SoftKeybd_Initialize
Initialize the Input panel
Parameters:
DefaultScreen: pointer to RECT indicating default screen area
where the SIP can be positioned.
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
SoftKeybd_Initialize(
__in RECT* pDefaultScreen
)
{
HRESULT hr;
if (!pDefaultScreen)
{
ASSERT(0);
return E_INVALIDARG;
}
hr = CoredllExports_t::Initialize();
if (FAILED(hr))
{
return hr;
}
BOOL Sucess = FALSE;
SIPINFO si = {0};
si.cbSize = sizeof(si);
if (CoredllExports_t::SipGetInfo(&si))
{
int SIPWidth = RECTWIDTH(si.rcSipRect);
si.rcSipRect.left = pDefaultScreen->left;
//Get the appropriate top from SIP panel's height and predefined offset
si.rcSipRect.top = pDefaultScreen->bottom - RECTHEIGHT(si.rcSipRect);
si.rcSipRect.bottom = pDefaultScreen->bottom;
if (SIPWidth < RECTWIDTH(*pDefaultScreen))
{
si.rcSipRect.left = (pDefaultScreen->left + pDefaultScreen->right - SIPWidth) / 2;
si.rcSipRect.right = si.rcSipRect.left + SIPWidth;
}
si.fdwFlags |= SIPF_LOCKED;
if (CoredllExports_t::SipSetInfo(&si))
{
Sucess = SoftKeybd_ShowHide(FALSE);
}
}
hr = Sucess ? S_OK : CommonUtilities_t::GetErrorFromWin32();;
return hr;
}
/*------------------------------------------------------------------------------
SoftKeybd_OnSettingChange
Handles the WM_SETTINGCHANGE message
Parameters:
wParam: WPARAM parameter of the WM_SETTINGCHANGE message
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
SoftKeybd_OnSettingChange(
WPARAM wParam
)
{
HRESULT hr = S_OK;
if (wParam != SPI_SETSIPINFO)
{
return S_FALSE;
}
// If the input panel was turned on/off by user, then we set the
// corresponding Input panel status
if (s_fSoftKeybdInvokedByUser)
{
hr = SendMessage(
GetForegroundWindow(),
WM_COMMON_SET_INPUT_PANEL_STATUS,
SoftKeybd_IsVisible(),
0
);
}
return hr;
}
/*------------------------------------------------------------------------------
SoftKeybd_KillFocusedEditCtrl
Handles the edit control's kill focus event
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
SoftKeybd_KillFocusedEditCtrl(
void
)
{
SoftKeybd_ShowHide(FALSE);
return S_OK;
}
/*------------------------------------------------------------------------------
SoftKeybd_SetFocusedEditCtrl
Handles the edit control's set focus event
Parameters:
EditControl: handle of the edit control that just got focus
Returns (HRESULT):
------------------------------------------------------------------------------*/
HRESULT
SoftKeybd_SetFocusedEditCtrl(
HWND EditControl
)
{
// remember the current focused edit control
s_EditControlWithFocus = EditControl;
// Check to see if we should show or hide the Input panel
// we show Input panel only if the current state has the Input panel enabled &&
// edit control is neither readonly nor digits only
if (!(GetWindowLong(EditControl, GWL_STYLE) & (ES_READONLY | ES_NUMBER)))
{
BOOL Show = SendMessage(
GetForegroundWindow(),
WM_COMMON_GET_INPUT_PANEL_STATUS,
0,
0
);
if (Show)
{
SoftKeybd_ShowHide(Show);
}
}
return S_OK;
}
HRESULT
SoftKeybd_ChangeSIPStatus(
BOOL Mode
)
{
return (HRESULT)SendMessage(
GetForegroundWindow(),
WM_COMMON_SET_INPUT_PANEL_STATUS,
Mode,
0
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -