标准Windows桌面应用程序使用情况与Windows平板电脑使用情况之间鼠标事件的影响有何不同?
我们创建了一个应用程序,可在某些文本字段获得焦点时创建弹出式虚拟键盘。然后可以单击此虚拟键盘以键入文本字段,而不会导致文本字段失去焦点。
在标准台式PC上使用鼠标时,此可正常工作。但是,在Windows平板电脑等移动设备上运行并使用触摸命令时,键盘的行为会有所不同,从而失去焦点。
我们一直认为移动触控命令很大程度上模拟了鼠标点击事件,尽管这似乎并非如此。 为什么这两种输入法的工作方式不同?我们如何才能使键盘在两种平台上都能完全相同?
一个小的测试程序如下:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class KeyboardEventTest {
private Kbd kbd = null;
protected Shell shell;
private Label lblNoEvent;
private Text txtNoEvent;
private Label lblYesEvent;
private Text txtYesEvent;
private ControlListener _parentControlListener = new ControlListener() {
@Override
public void controlResized(ControlEvent e) {
}
@Override
public void controlMoved(ControlEvent e) {
if(kbd != null)
kbd.positionRelativeToControl();
}
};
public static void main(String[] args) {
try {
KeyboardEventTest window = new KeyboardEventTest();
window.open();
}
catch (Exception e) {
e.printStackTrace();
}
}
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while(!shell.isDisposed()) {
if(!display.readAndDispatch()) {
display.sleep();
}
}
}
protected void createContents() {
shell = new Shell();
shell.setSize(450, 300);
shell.setText("Keyboard Event Test");
GridLayout gl_shell = new GridLayout();
gl_shell.numColumns = 2;
shell.setLayout(gl_shell);
lblNoEvent = new Label(shell, SWT.NONE);
lblNoEvent.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblNoEvent.setText("No Event");
txtNoEvent = new Text(shell, SWT.BORDER);
txtNoEvent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
lblYesEvent = new Label(shell, SWT.NONE);
lblYesEvent.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblYesEvent.setText("Event");
txtYesEvent = new Text(shell, SWT.BORDER);
txtYesEvent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
txtYesEvent.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
showKeyboard();
}
@Override
public void focusLost(FocusEvent e) {
closeKeyboard();
}
});
}
protected void closeKeyboard() {
if(kbd != null) {
if(!kbd.isDisposed())
kbd.close();
kbd = null;
}
}
protected void showKeyboard() {
Control ctrlFocus = shell.getDisplay().getFocusControl();
if(!(ctrlFocus instanceof Text))
return;
Text txt = (Text) ctrlFocus;
if(kbd == null && txt.isEnabled() && txt.getEditable()) {
kbd = new Kbd(shell, txt);
kbd.positionRelativeToControl();
kbd.setVisible(true);
Composite parent = txt.getParent();
do {
parent.addControlListener(_parentControlListener);
} while((parent = parent.getParent()) != null);
}
}
private class Kbd extends Shell {
private static final int XMARGIN = 5;
private static final int YMARGIN = 5;
private Display _display;
private Text _txt;
private Point _ptKey;
private Color _clrInfoFG;
private Color _clrInfoBG;
public Kbd(Shell parent, Text associatedCtrl) {
super(parent, SWT.ON_TOP | SWT.NO_TRIM | SWT.TOOL | SWT.NO_FOCUS | SWT.NO_BACKGROUND);
_txt = associatedCtrl;
_display = getDisplay();
_clrInfoFG = _display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
_clrInfoBG = _display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
onPaint(e);
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if(_txt.isEnabled() && _txt.getEditable()) {
char c = getItemMouseIsOn(e);
if(c != '\0') {
sendKeyEvent(c, SWT.KeyDown);
sendKeyEvent(c, SWT.KeyUp);
}
}
}
});
GC gc = new GC(_display);
_ptKey = new Point(0,0);
for(char c = 'A' ; c <= 'Z' ; c++) {
Point ptChar = gc.textExtent(Character.toString(c));
_ptKey.x = Math.max(_ptKey.x, ptChar.x);
_ptKey.y = Math.max(_ptKey.y, ptChar.y);
}
gc.dispose();
setSize(26 * (_ptKey.x + 2 * XMARGIN), _ptKey.y + 2 * YMARGIN);
}
public void positionRelativeToControl() {
Rectangle rc = _txt.getBounds();
Point ptTxt = new Point(rc.x, rc.y + rc.height);
Point ptNewPosition = _display.map(_txt.getParent(), null, ptTxt);
Point ptCurrentShellPosition = getLocation();
if(!ptNewPosition.equals(ptCurrentShellPosition))
setLocation(ptNewPosition);
}
private void sendKeyEvent(char c, int eventType) {
Event event = new Event();
event.type = eventType;
event.character = c;
_display.post(event);
}
private char getItemMouseIsOn(MouseEvent e) {
Rectangle rc = getClientArea();
if ((rc.x <= e.x) && (e.x <= rc.x + rc.width)) {
int key = e.x / (2 * XMARGIN + _ptKey.x);
if(0 <= key && key <= 25) {
char c = (char) ('A' + key);
return c;
}
}
return '\0';
}
protected void onPaint(PaintEvent e) {
Rectangle rc = getClientArea();
Image img = new Image(_display, rc.width, rc.height);
GC gc = new GC(img);
Color clrFG = gc.getForeground();
Color clrBG = gc.getBackground();
gc.setBackground(_clrInfoBG);
gc.fillRectangle(rc);
gc.setForeground(_clrInfoFG);
int x = rc.x + XMARGIN;
int y = rc.y + YMARGIN;
for(char c = 'A' ; c <= 'Z' ; c++) {
gc.drawText(Character.toString(c), x, y);
x += _ptKey.x + XMARGIN;
gc.drawLine(x, rc.y, x, rc.y + rc.height);
x += XMARGIN;
}
gc.setForeground(clrFG);
gc.setBackground(clrBG);
e.gc.drawImage(img, 0, 0);
gc.dispose();
img.dispose();
}
@Override
protected void checkSubclass() {
}
}
}