一个WPF下的虚拟键盘实现
给上位机触摸屏做一个虚拟键盘,这玩意儿不就是一排的网格里面放满button嘛 。说归这样说 依然还是有一堆细节需要你去处理的。不论如何 先画个键盘吧。
简单的从网上找个键盘位图做参照使用 4行Grid 布局一下 是不是有模有样。主要是按键的样式要想好看的话的花一些功夫。然后所有的button需要绑定同一个事件,由于WPF里的事件是路由事件 我们直接在最外面的Grid上写 ButtonBase.Click="ButtonGrid_Click" 即可 ,以前竟然没发现还可以这样ButtonBase 了解了。然后有几个蓝色的Fun按键需要做特殊处理和定义, 还有就算我们做成的userControl控件,需要把事件暴露给外部 让按特定键的时候外部写自己的处理逻辑。
按键和事件定义
1 public Action<object> MyKeyDown; 2 private String valueString; 3 4 internal String ValueString 5 { 6 get { return valueString; } 7 } 8 public enum EKeyitem 9 { 10 DEl, 11 AC, 12 OK, 13 Shift, 14 A 15 }
事件触发
1 private void ButtonGrid_Click(object sender, RoutedEventArgs e) 2 { 3 Button clickedButton = (Button)e.OriginalSource; //获取click事件触发源,即按了的按钮 4 if ((String)clickedButton.Content == "DEL") 5 { 6 MyKeyDown(EKeyitem.DEl); 7 } 8 else if ((String)clickedButton.Content == "AC") 9 { 10 MyKeyDown(EKeyitem.AC); 11 } 12 else if ((String)clickedButton.Content == "确认") 13 { 14 MyKeyDown(EKeyitem.OK); 15 //this.Close(); 16 } 17 else if ((String)clickedButton.Content == "A/a") 18 { 19 for (int j = 1; j < 4; j++) 20 { 21 Grid grd = ButtonGrid.Children[j] as Grid; 22 int count2 = grd.Children.Count; 23 for (int i = 0; i < count2; i++) 24 { 25 Button buttonTemp = grd.Children[i] as Button; 26 String contentTemp = buttonTemp.Content as String; 27 if (contentTemp == "AC" || contentTemp == "A/a") 28 continue; 29 buttonTemp.Content = contentTemp[0] > 90 ? contentTemp.ToUpper() : contentTemp.ToLower(); 30 } 31 } 32 33 } 34 else 35 { 36 MyKeyDown((String)clickedButton.Content); 37 } 38 }
外部使用,常规usercontrol一样使用,先是引入命名空间xmlns:local="clr-namespace:xxx,由于虚拟键盘有一个特性 ,比如我们点击文本框那么它应该出现,且出现的位置刚好在文本框下方,我点回车虚拟键盘消失,那么这里有一丁丁的奇技淫巧,那就是可以进行绝对定位的canvas组件。
1 <Grid> 2 <TextBox Width="300" Height="50" FontSize="25" Name="tbx_QueryCode" Text="" PreviewMouseDown="tbx_QueryCode_PreviewMouseDown" KeyDown="tbx_QueryCode_KeyDown" GotFocus="tbx_QueryCode_GotFocus"></TextBox> 3 <Canvas Name="vkContext" Focusable="False" > 4 <local:VKeyBoard Canvas.Left="50" Focusable="False" Canvas.Top="100" Visibility="Hidden" x:Name="myvk"></local:VKeyBoard> 5 </Canvas> 6 </Grid>
文本框获取焦点时
1 private void tbx_QueryCode_GotFocus(object sender, RoutedEventArgs e) 2 { 3 myvk.Visibility = Visibility.Visible; 4 focusTbx = tbx_QueryCode; 5 RePointKeyBoard(); 6 }
虚拟键盘的聚焦
1 public void RePointKeyBoard() 2 { 3 if (focusTbx != null) 4 { 5 Point p = focusTbx.TranslatePoint(new Point(0, 0), windContent); 6 7 this.myvk.SetValue(Canvas.LeftProperty, p.X); 8 this.myvk.SetValue(Canvas.TopProperty, p.Y + focusTbx.Height); 9 } 10 11 }
还有就是虚拟键盘外露给我们事件的处理。
开始时绑定事件
1 private void Window_Loaded(object sender, RoutedEventArgs e) 2 { 3 myvk.MyKeyDown = MyKeyDown; 4 5 }
外露事件处理
1 //虚拟键盘事件 2 private void MyKeyDown(object _key) 3 { 4 if (focusTbx == null) 5 { 6 myvk.Visibility = Visibility.Hidden; 7 return; 8 } 9 EKeyitem key = EKeyitem.A; 10 if (_key.GetType() == typeof(EKeyitem)) 11 key = (EKeyitem)_key; 12 13 if (key == EKeyitem.DEl) 14 { 15 if (focusTbx.Text.Length > 0) 16 { 17 focusTbx.Text = focusTbx.Text.Substring(0, focusTbx.Text.Length - 1); 18 } 19 } 20 else if (key == EKeyitem.AC) 21 { 22 focusTbx.Text = ""; 23 } 24 else if (key == EKeyitem.OK) 25 { 26 27 myvk.Visibility = Visibility.Hidden; 28 if (vm.LoginOK == true && focusTbx == tbx_QueryCode) 29 { 30 valueString = focusTbx.Text; 31 //this.Close(); 32 BarCodeInputKeyDown(); 33 } 34 } 35 else if (key == EKeyitem.Shift) 36 { 37 38 } 39 else 40 { 41 focusTbx.Text += _key.ToString(); 42 } 43 }