SIP(soft input panel) Overlapping Controls
How to solve input panel overlapping problem
Introduction
This article gives a simple but very effective explanation to overcome the problem when your controls aren't visible when you open the inputpanel
. You can notice in the screenshot that all controls are adapted based on the inputpanel
and available free space.
Using the Code
Add the class to your project. It is a static
class so it can be called from any form. To let this work, you need to add an inputpanel
control to each form. If you are using tabpages, then you pass only the current tab page. For example:
OverLappingInputPanel.Inputpanel(tabControl1.TabPages
[tabControl1.SelectedIndex].Controls, inputPanel1.Enabled,
inputPanel1.VisibleDesktop.Height);
The OverlappingInputPanel
class:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace MFA_Common
{
public static class OverLappingInputPanel
{
private static int oldrest = 0;
private static int oldheight = 0;
private static int oldtop = 0;
private static Control isFocused = null;
/// <summary>
/// Brings the control that has focus on top of the inputpanel
/// </summary>
/// <param name=""controls""></param>
/// <param name=""SIDCollaps""></param>
public static void Inputpanel(Control.ControlCollection controls,
Boolean SIDExpended, int Visualdesktopheight)
{
try
{
if (controls != null)
{
if (SIDExpended == true)
{
//Loop through the controls to determinate which has focus
//this can be avoided if the gotfocus event is fired
//for each control that is beneath the inputpanel if expanded
foreach (Control ctrl in controls)
{
if (ctrl.Focused)
{
isFocused = ctrl;
// if this is not the case calculate the needed space
int rest = Visualdesktopheight - (
ctrl.Top + ctrl.Height);
if (rest < 0)
{
//move each control up with the calculated space
foreach (Control ctrl2 in controls)
{
ctrl2.Top = ctrl2.Top + rest;
}
oldrest = rest;
}
if (ctrl.Height > Visualdesktopheight)
{
oldtop = ctrl.Top;
oldheight = ctrl.Height;
ctrl.Height = Visualdesktopheight;
ctrl.Top = 0;
}
}
}
//escape the current function if the selected control is
//not under the inputpanel
return;
}
else
{
//when the inputpanel is hidden, recalculate the top position
//for each control.
//the old value has to be reversed *-1 to inverse the changes
//if the control was bigger than the available screen, then
//give it back its original value
if (oldheight != 0)
{
isFocused.Top = oldtop;
isFocused.Height = oldheight;
oldheight = 0;
}
foreach (Control ctrl2 in controls)
{
ctrl2.Top = ctrl2.Top + (-1 * oldrest);
}
oldrest = 0;
}
}
}
catch
{
//the ObjectDisposedException is trapped here. This occurs when the user
//doesn't closes the sip before moving to an other screen
//if an inputpanel is closed on an other form,
//then the object that is stored is dispose
//if this is the case, catch the exception and set the object to null;
oldrest = 0;
controls = null;
}
}
}
}
The code can be improved if you pass the object that requires the adjustment of the screen. Just add for each control the gotfocus
event that is overlapped by the inputpanel
and pass it to the function. Then the function doesn't need to loop over each control that is in the control container.
History
- 2nd July, 2008: Initial post