Recently, we needed to show and hide the SIP (Software Input Panel) inside a full screen Remote Desktop Mobile session.
The first challenge is to control the SIP without having a menu bar with the SIP symbol inside. To get this working, you can assign a hardware keyboard button, it must be an App button, to show the SIP. See Settings>Personal>Buttons and assign “<Input Panel>” to the hardware key.
Unfortunately, the SIP will be hidden immediately after being shown if RDM is started with Full Screen option.
To overcome this, I looked at the Windows Messages inside the RDM window tree and found that there is a Windows Message WM_WININICHANGE
send to the main RDM window every time the SIP is shown. Inside the UIMainClass
window, the SIP show will result in some more messages, Now, if we can suppress the WM_WININICHANGE
message, the SIP may stay until hidden manually, hopefully.
But how can one hook in a foreign Message Pump (WndProc
)? Fortunately, there is a general option provided by Windows CE / Mobile to inject one or more DLLs into every started process. Simply add your DLL to the registry key HKLM\System\Kernel\InjectDLL. The type of InjectDLL
is REG_MULTISZ
.
Now the DLL that I wrote compares the Module File Name of the process that is calling DLL_ATTACH
with the Module File Name of RDM, which is “\Windows\wpctsc.exe” on Windows Mobile/Embedded Handheld. If the Module File Name matches, the code looks for the Windows Class “TSSHELLWND
”. If this is found, the RDM window has been loaded and initialized. Now the DLL code looks for the child window with class “UIMainClass
”. This window marks a remote session has been started. If found, the code uses SetWindowLong
and hooks a custom WndProc
into the main RDM window. This custom WndProc
simply looks for the Window Message that hides the SIP and just returns a TRUE
, as if the message has been processed. The other window messages are forwarded unchanged to the original WndProc
. The message we filter is WM_WININICHANGE
with lParam==133071496
.
Remember that ‘subclassing’ a window is only possible from inside the process that created the window. But using InjectDLL
, the DLL code is part of the RDM process (and all others) and you can subclass the ‘foreign’ window.
The only ‘disadvantage’ here is the position of the SIP. As there is no menu bar, the SIP is floating above the lower border. But there are custom SIPs you can move around, if this is a no-go for you.
The demo RDMinjectDLL.dll has to be copied to \Windows and then you need to edit the registry of the device:
REGEDIT4
[HKEY_LOCAL_MACHINE\System\Kernel]
"InjectDLL"=hex(7):\
5C,57,69,6E,64,6F,77,73,5C,52,44,4D,69,6E,6A,65,63,74,44,6C,6C,2E,64,6C,\
6C,00
The hex codes are nothing other than the string
“\Windows\RDMinjectDLL.dll” (without quotes). After changing the registry, the device needs to be rebooted.
During development, I had to remove the reg entry, reboot, deploy a new version, change the reg back and reboot again to test the new version.