其實關鍵就只是利用C# SendKeys 的功能而已(這篇有寫過)
但如果要寫一個完整模擬鍵盤的APP,會有些比較複雜的功能。
一開始會打算先用字串陣列的方式,順序就依照鍵盤的設計去準備每個按鍵的圖案跟Keycode。
首先是鍵盤圖檔所有的檔名,包含大小寫轉換的圖案。
路徑的部分依照按下的狀態分為兩個資料夾來放(Keyup and Keydown),Keydown 是按下去時反白的圖案,圖檔格式為.png:
private String FileType = ".png"; private String FilePathKeyUp = "Image/KeyUp/keyup_"; private String FilePathKeyDown = "Image/KeyDown/keydown_"; private String[] CapsLetterFileName = {"q","w","e","r","t","y","u","i","o","p","delete","one","two","three", "a","s","d","f","g","h","j","k","l","double_quote","enter","four","five","six", "shift","z","x","c","v","b","n","m","semicolon","colon","exclamation_mark_screamer","shift2","seven","eight","nine", "ctrl","alt","windows","spacebar","left","right","keyboard","zero","lperiod_full_stop"}; private String[] SmallLetterFileName = {"lq","lw","le","lr","lt","ly","lu","li","lo","lp","delete","one","two","three", "la","ls","ld","lf","lg","lh","lj","lk","ll","lsingle_quote","enter","four","five","six", "shift","lz","lx","lc","lv","lb","ln","lm","lcomma","lperiod_full_stop","lquestion_mark","shift2","seven","eight","nine", "ctrl","alt","windows","spacebar","left","right","keyboard","zero","lperiod_full_stop"};
再來是Keycode的部分,對應到上面的陣列位置,分別準備大、小寫的陣列。
private String[] KeyCodeCapsLetter = {"Q","W","E","R","T","Y","U","I","O","P", "{backspace}","1","2","3", "A","S","D","F","G","H","J","K","L","\"","{enter}","4","5","6", "shift","Z","X","C","V","B","N","M",";",":","!","shift","7","8","9", "^","%","^" + "{esc}"," ","{left}","{right}","keyboard","0","."}; private String[] KeyCodeSmallLetter = {"q","w","e","r","t","y","u","i","o","p", "{backspace}","1","2","3", "a","s","d","f","g","h","j","k","l","'","{enter}","4","5","6", "shift","z","x","c","v","b","n","m",",",".","?","shift","7","8","9", "^","%","^" + "{esc}"," ","{left}","{right}","keyboard","0","."};
這樣之後程式碼寫輸入的部分,就可以用for 迴圈搭配if 判斷陣列位置這樣來寫:
for (int i = 0; i < key_amount; i++) { if (mImage.Name == CapsLetterFileName[i]) { if (isCaps) { SendKeys.SendWait(KeyCodeCapsLetter[i]); } else { SendKeys.SendWait(KeyCodeSmallLetter[i]); } } }
寫到這邊先來講一個問題,一般APP 出現在螢幕上的時候,視窗一定要Focus 才能用,但是要模擬鍵盤功能的話,是要針對APP 以外的其他視窗打字。
所以這邊的作法是先把APP 設定為Topmost (在xaml 中的Window 物件 > 屬性 > 一般 > Topmost)。
然後在cs 程式碼中宣告的地方import 需要的dll :
// import dll to control on Topmost [DllImport("user32", SetLastError = true)] private extern static int GetWindowLong(IntPtr hwnd, int nIndex); [DllImport("user32", SetLastError = true)] private extern static int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewValue);
在程式碼中建立一個函式 initTopmostControl() :
private void initTopmostControl() { WindowInteropHelper wih = new WindowInteropHelper(this); int exstyle = GetWindowLong(wih.Handle, -20); exstyle |= 0x08000000; SetWindowLong(wih.Handle, -20, exstyle); }
這邊也讓Keyboard APP 模擬真實的鍵盤,可以在右下角看到APP 的圖示,甚至可以點它來開啟/隱藏Keyboard。
可以參考之前寫過的NotifyIcon 寫法(參考這篇):
建立一個函式 initNotifyIcon():
// init NotifyIcon private void initNotifyIcon() { notifyIcon = new NotifyIcon(); Stream iconStream = System.Windows.Application.GetResourceStream(new Uri(@"Image/icon2.ico", UriKind.Relative)).Stream; notifyIcon.Icon = new System.Drawing.Icon(iconStream); System.Windows.Forms.ContextMenu notifyIconMenu = new System.Windows.Forms.ContextMenu(); System.Windows.Forms.MenuItem notifyIconMenuItem = new System.Windows.Forms.MenuItem(); notifyIconMenuItem.Index = 0; notifyIconMenuItem.Text = "Exit"; notifyIconMenuItem.Click += new EventHandler(notifyIconMenuItem_Click); notifyIconMenu.MenuItems.Add(notifyIconMenuItem); notifyIcon.ContextMenu = notifyIconMenu; notifyIcon.Visible = true; notifyIcon.Click += new EventHandler(TouckKeyboard_state); }
這邊NotifyIcon 想要加入的功能是,在icon 上點右鍵選擇Exit 來關閉APP。
notifyIconMenuItem.Click += new EventHandler(notifyIconMenuItem_Click);
其中notifyIconMenuItem_Click就是寫直接關閉APP
private void notifyIconMenuItem_Click(object sender, EventArgs e) { this.Close(); }
另外,可以在右下角的icon 上,點左鍵來顯示/隱藏APP,
notifyIcon.Click += new EventHandler(TouckKeyboard_state);
其中TouckKeyboard_state 就是來控制Keyboard APP 視窗顯示的位置,判斷isShow 然後利用Top 值來設定式窗位置,所以程式碼還要加入:
// show or hide keyboard private void TouckKeyboard_state(object sender, EventArgs e) { isShow = !isShow; TouckKeyboard_position(); } // show or hide keyboard position private void TouckKeyboard_position() { if (!isShow) { while (this.Top < workArea.Height + 50) { this.Top++; } } else { while (this.Top >= workArea.Height - this.Height + 1) { this.Top--; } } }
workArea 的部分是建立一個Rect 來抓系統中,整個螢幕的範圍,可以透過它來設定視窗位置,或是做APP 等比例的縮放:
private Rect workArea; workArea = System.Windows.SystemParameters.WorkArea;
以上三個函式initTopmostControl()、initNotifyIcon()、TouckKeyboard_position() 建議寫在Window_Loaded() 裡面比較保險。
在xaml 中的Window 物件 > 屬性 > 事件 > Loaded 點開產生函式:
private void Window_Loaded(object sender, RoutedEventArgs e) { initTopmostControl(); initNotifyIcon(); TouckKeyboard_position(); }
目前是寫針對APP 方面前提的一些基本的功能,接下來是比較重要的部分,就是每個按鍵的設定跟功能寫法。
在MainWindow() 先利用前面寫的workArea 來設定APP是窗的位置跟大小:
public MainWindow() { InitializeComponent(); // set keyboard window x,y,w,h by workArea workArea = System.Windows.SystemParameters.WorkArea; this.Left = 0; this.Top = workArea.Height; this.Width = workArea.Width; this.Height = workArea.Height * 0.435; }
這邊補上一個Layout 的參數來參考一下(參考圖檔來源的 spec.jpg):
建立一個函式initKeyImage() 來設定所有的按鍵圖案,包括圖檔、大小、位置:
private void initKeyImage() { key_amount = CapsLetterFileName.Length; LetterFileName = new String[key_amount]; imageLetter = new Image[key_amount]; for (int i = 0; i < key_amount; i++) { // create key image imageLetter[i] = new Image(); imageLetter[i].Name = CapsLetterFileName[i]; imageLetter[i].Source = new BitmapImage(new Uri(@FilePathKeyUp + CapsLetterFileName[i] + FileType, UriKind.Relative)); imageLetter[i].Stretch = Stretch.Fill; imageLetter[i].MouseDown += new MouseButtonEventHandler(imageLetterMouseDown); imageLetter[i].MouseUp += new MouseButtonEventHandler(imageLetterMouseUp); imageLetter[i].MouseLeave += new System.Windows.Input.MouseEventHandler(imageLetterMouseLeave); CanvasWindow.Children.Add(imageLetter[i]); // set left of each key image if (imageLetter[i].Name == "q" || imageLetter[i].Name == "shift" || imageLetter[i].Name == "ctrl") { Canvas.SetLeft(imageLetter[i], workArea.Width * 0.04); } else if (imageLetter[i].Name == "a") { Canvas.SetLeft(imageLetter[i], workArea.Width * 0.053); } else { Canvas.SetLeft(imageLetter[i], Canvas.GetLeft(imageLetter[i - 1]) + imageLetter[i - 1].Width + 10); } // set top of each key image if (i >= 0 && i <= 13) { Canvas.SetTop(imageLetter[i], workArea.Width * 0.01); } else if (i >= 14 && i <= 27) { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 1)); } else if (i >= 28 && i <= 42) { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 2)); } else { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 3)); } // set width of each key iamge if (imageLetter[i].Name == "delete" || imageLetter[i].Name == "zero") { imageLetter[i].Width = workArea.Width * 0.111; } else if (imageLetter[i].Name == "enter") { imageLetter[i].Width = workArea.Width * 0.098; } else if (imageLetter[i].Name == "spacebar") { imageLetter[i].Width = workArea.Width * 0.345; } else { imageLetter[i].Width = workArea.Width * 0.053; } // set height of each key iamge imageLetter[i].Height = workArea.Height * 0.091; } }
建立滑鼠按下事件函式,圖案會呈現反白的樣子:
private void imageLetterMouseDown(object sender, RoutedEventArgs e) { isDown = true; Image mImage = (Image) sender; // set key pressed for (int i = 0; i < key_amount; i++) { if (mImage.Name == CapsLetterFileName[i]) { key_pressed = i; } } // set the keydown status and image setKeyStatus("down"); // set long press if (mImage.Name != "shift" && mImage.Name != "shift2") { SetLongPressTimer(true); } }
建立滑鼠移開事件函式,做類似 mouse up的功能,但不要做任何事情:
private void imageLetterMouseLeave(object sender, RoutedEventArgs e) { Image mImage = (Image)sender; // set the keyup status and image setKeyStatus("up"); SetLongPressTimer(false); }
建立滑鼠放開事件函式,在這裡就要寫判斷按了哪一個按鍵,做出對應的Keycode 功能:
private void imageLetterMouseUp(object sender, RoutedEventArgs e) { Image mImage = (Image)sender; // set the keyup status and image setKeyStatus("up"); // send key function if (isDown) { // shift function if (mImage.Name == "shift" || mImage.Name == "shift2") { isCaps = !isCaps; setLetterCaps(isCaps); } // keyboard show function else if (mImage.Name == "keyboard") { isShow = !isShow; TouckKeyboard_position(); } // letter function else { for (int i = 0; i < key_amount; i++) { if (mImage.Name == CapsLetterFileName[i]) { if (isCaps) { SendKeys.SendWait(KeyCodeCapsLetter[i]); } else { SendKeys.SendWait(KeyCodeSmallLetter[i]); } } } } SetLongPressTimer(false); } }
在以上滑鼠事件中,down 跟up 事件裡有狀態切換的函式setKeyStatus(),跟計時器的函式SetLongPressTimer()。
在setKeyStatus() 裡面做的就是鍵盤沒按/按下的狀態切換,按下會反白,寫一個setKeyImage()函式來切換不同狀態的圖案。
// set key status private void setKeyStatus(String status) { if(status == "down") { setKeyImage(imageLetter[key_pressed], FilePathKeyDown + LetterFileName[key_pressed] + FileType); } else if (status == "up") { setKeyImage(imageLetter[key_pressed], FilePathKeyUp + LetterFileName[key_pressed] + FileType); } } // set key image source private void setKeyImage(Image image, String filepath) { image.Source = new BitmapImage(new Uri(@filepath, UriKind.Relative)); }
另外就是函式SetLongPressTimer() 來控制長按用的計時器LongPressTimer 開啟/結束:
private void SetLongPressTimer(bool isStart) { if (isStart) { LongPressTimer.Start(); } else { LongPressTimer.Stop(); pressed_count = 0; isDown = false; } }
當按下shift 時會切換大小寫模式,所以要建立一個函式setLetterCaps() 來切換大小寫模式:
private void setLetterCaps(bool isCaps) { for (int i = 0; i < key_amount; i++) { if (isCaps) { LetterFileName[i] = CapsLetterFileName[i]; } else { LetterFileName[i] = SmallLetterFileName[i]; } setKeyImage(imageLetter[i], FilePathKeyUp + LetterFileName[i] + FileType); } }
MainWindow() 加入initKeyImage() 跟 setLetterCaps(true),另外也加入長按功能:
private bool isCaps = true; private DispatcherTimer LongPressTimer; public MainWindow() { InitializeComponent(); // set keyboard window x,y,w,h by workArea workArea = System.Windows.SystemParameters.WorkArea; this.Left = 0; this.Top = workArea.Height; this.Width = workArea.Width; this.Height = workArea.Height * 0.435; // set long press timer LongPressTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.01) }; LongPressTimer.Tick += LongPressTimerTick; initKeyImage(); setLetterCaps(isCaps); }
在程式碼中加入計時器函式 LongPressTimerTick(),當長按時會一直輸入:
private void LongPressTimerTick(object sender, EventArgs e) { pressed_count ++; if (pressed_count > 15) { if (isCaps) { SendKeys.SendWait(KeyCodeCapsLetter[key_pressed]); } else { SendKeys.SendWait(KeyCodeSmallLetter[key_pressed]); } } }
APP 執行的時候,可以從工具列的右下角看程式有沒有打開。
最後附上全部完整的程式碼:
MainWindow.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Forms; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Runtime.InteropServices; using System.IO; using System.Windows.Threading; using System.Windows.Input; namespace TouchKeyboard { public partial class MainWindow : Window { private bool isShow = true, isCaps = true, isDown = false; private int key_amount, key_pressed, pressed_count = 0; private String FileType = ".png"; private String FilePathKeyUp = "Image/KeyUp/keyup_"; private String FilePathKeyDown = "Image/KeyDown/keydown_"; private String[] CapsLetterFileName = {"q","w","e","r","t","y","u","i","o","p","delete","one","two","three", "a","s","d","f","g","h","j","k","l","double_quote","enter","four","five","six", "shift","z","x","c","v","b","n","m","semicolon","colon","exclamation_mark_screamer","shift2","seven","eight","nine", "ctrl","alt","windows","spacebar","left","right","keyboard","zero","lperiod_full_stop"}; private String[] SmallLetterFileName = {"lq","lw","le","lr","lt","ly","lu","li","lo","lp","delete","one","two","three", "la","ls","ld","lf","lg","lh","lj","lk","ll","lsingle_quote","enter","four","five","six", "shift","lz","lx","lc","lv","lb","ln","lm","lcomma","lperiod_full_stop","lquestion_mark","shift2","seven","eight","nine", "ctrl","alt","windows","spacebar","left","right","keyboard","zero","lperiod_full_stop"}; private String[] KeyCodeCapsLetter = {"Q","W","E","R","T","Y","U","I","O","P", "{backspace}","1","2","3", "A","S","D","F","G","H","J","K","L","\"","{enter}","4","5","6", "shift","Z","X","C","V","B","N","M",";",":","!","shift","7","8","9", "^","%","^" + "{esc}"," ","{left}","{right}","keyboard","0","."}; private String[] KeyCodeSmallLetter = {"q","w","e","r","t","y","u","i","o","p", "{backspace}","1","2","3", "a","s","d","f","g","h","j","k","l","'","{enter}","4","5","6", "shift","z","x","c","v","b","n","m",",",".","?","shift","7","8","9", "^","%","^" + "{esc}"," ","{left}","{right}","keyboard","0","."}; private String[] LetterFileName; private Image[] imageLetter; private Rect workArea; private NotifyIcon notifyIcon; private DispatcherTimer LongPressTimer; // import dll to control on Topmost [DllImport("user32", SetLastError = true)] private extern static int GetWindowLong(IntPtr hwnd, int nIndex); [DllImport("user32", SetLastError = true)] private extern static int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewValue); public MainWindow() { InitializeComponent(); // set keyboard window x,y,w,h by workArea workArea = System.Windows.SystemParameters.WorkArea; this.Left = 0; this.Top = workArea.Height; this.Width = workArea.Width; this.Height = workArea.Height * 0.435; // set long press timer LongPressTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.01) }; LongPressTimer.Tick += LongPressTimerTick; initKeyImage(); setLetterCaps(isCaps); } private void Window_Loaded(object sender, RoutedEventArgs e) { initTopmostControl(); initNotifyIcon(); TouckKeyboard_position(); } // control on Topmost private void initTopmostControl() { WindowInteropHelper wih = new WindowInteropHelper(this); int exstyle = GetWindowLong(wih.Handle, -20); exstyle |= 0x08000000; SetWindowLong(wih.Handle, -20, exstyle); } // init NotifyIcon private void initNotifyIcon() { notifyIcon = new NotifyIcon(); Stream iconStream = System.Windows.Application.GetResourceStream(new Uri(@"Image/icon2.ico", UriKind.Relative)).Stream; notifyIcon.Icon = new System.Drawing.Icon(iconStream); System.Windows.Forms.ContextMenu notifyIconMenu = new System.Windows.Forms.ContextMenu(); System.Windows.Forms.MenuItem notifyIconMenuItem = new System.Windows.Forms.MenuItem(); notifyIconMenuItem.Index = 0; notifyIconMenuItem.Text = "Exit"; notifyIconMenuItem.Click += new EventHandler(notifyIconMenuItem_Click); notifyIconMenu.MenuItems.Add(notifyIconMenuItem); notifyIcon.ContextMenu = notifyIconMenu; notifyIcon.Visible = true; notifyIcon.Click += new EventHandler(TouckKeyboard_state); } // init key image object private void initKeyImage() { key_amount = CapsLetterFileName.Length; LetterFileName = new String[key_amount]; imageLetter = new Image[key_amount]; for (int i = 0; i < key_amount; i++) { // create key image imageLetter[i] = new Image(); imageLetter[i].Name = CapsLetterFileName[i]; imageLetter[i].Source = new BitmapImage(new Uri(@FilePathKeyUp + CapsLetterFileName[i] + FileType, UriKind.Relative)); imageLetter[i].Stretch = Stretch.Fill; imageLetter[i].MouseDown += new MouseButtonEventHandler(imageLetterMouseDown); imageLetter[i].MouseUp += new MouseButtonEventHandler(imageLetterMouseUp); imageLetter[i].MouseLeave += new System.Windows.Input.MouseEventHandler(imageLetterMouseLeave); CanvasWindow.Children.Add(imageLetter[i]); // set left of each key image if (imageLetter[i].Name == "q" || imageLetter[i].Name == "shift" || imageLetter[i].Name == "ctrl") { Canvas.SetLeft(imageLetter[i], workArea.Width * 0.04); } else if (imageLetter[i].Name == "a") { Canvas.SetLeft(imageLetter[i], workArea.Width * 0.053); } else { Canvas.SetLeft(imageLetter[i], Canvas.GetLeft(imageLetter[i - 1]) + imageLetter[i - 1].Width + 10); } // set top of each key image if (i >= 0 && i <= 13) { Canvas.SetTop(imageLetter[i], workArea.Width * 0.01); } else if (i >= 14 && i <= 27) { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 1)); } else if (i >= 28 && i <= 42) { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 2)); } else { Canvas.SetTop(imageLetter[i], (workArea.Width * 0.01 + (workArea.Height * 0.091 + workArea.Width * 0.004) * 3)); } // set width of each key iamge if (imageLetter[i].Name == "delete" || imageLetter[i].Name == "zero") { imageLetter[i].Width = workArea.Width * 0.111; } else if (imageLetter[i].Name == "enter") { imageLetter[i].Width = workArea.Width * 0.098; } else if (imageLetter[i].Name == "spacebar") { imageLetter[i].Width = workArea.Width * 0.345; } else { imageLetter[i].Width = workArea.Width * 0.053; } // set height of each key iamge imageLetter[i].Height = workArea.Height * 0.091; } } private void imageLetterMouseDown(object sender, RoutedEventArgs e) { isDown = true; Image mImage = (Image) sender; // set key pressed for (int i = 0; i < key_amount; i++) { if (mImage.Name == CapsLetterFileName[i]) { key_pressed = i; } } // set the keydown status and image setKeyStatus("down"); // set long press if (mImage.Name != "shift" && mImage.Name != "shift2") { SetLongPressTimer(true); } } private void imageLetterMouseLeave(object sender, RoutedEventArgs e) { Image mImage = (Image)sender; // set the keyup status and image setKeyStatus("up"); SetLongPressTimer(false); } private void imageLetterMouseUp(object sender, RoutedEventArgs e) { Image mImage = (Image)sender; // set the keyup status and image setKeyStatus("up"); // send key function if (isDown) { // shift function if (mImage.Name == "shift" || mImage.Name == "shift2") { isCaps = !isCaps; setLetterCaps(isCaps); } // keyboard show function else if (mImage.Name == "keyboard") { isShow = !isShow; TouckKeyboard_position(); } // letter function else { for (int i = 0; i < key_amount; i++) { if (mImage.Name == CapsLetterFileName[i]) { if (isCaps) { SendKeys.SendWait(KeyCodeCapsLetter[i]); } else { SendKeys.SendWait(KeyCodeSmallLetter[i]); } } } } SetLongPressTimer(false); } } // set all letter caps or little private void setLetterCaps(bool isCaps) { for (int i = 0; i < key_amount; i++) { if (isCaps) { LetterFileName[i] = CapsLetterFileName[i]; } else { LetterFileName[i] = SmallLetterFileName[i]; } setKeyImage(imageLetter[i], FilePathKeyUp + LetterFileName[i] + FileType); } } // set key status private void setKeyStatus(String status) { if(status == "down") { setKeyImage(imageLetter[key_pressed], FilePathKeyDown + LetterFileName[key_pressed] + FileType); } else if (status == "up") { setKeyImage(imageLetter[key_pressed], FilePathKeyUp + LetterFileName[key_pressed] + FileType); } } // set key image source private void setKeyImage(Image image, String filepath) { image.Source = new BitmapImage(new Uri(@filepath, UriKind.Relative)); } // show or hide keyboard private void TouckKeyboard_state(object sender, EventArgs e) { isShow = !isShow; TouckKeyboard_position(); } // show or hide keyboard position private void TouckKeyboard_position() { if (!isShow) { while (this.Top < workArea.Height + 50) { this.Top++; } } else { while (this.Top >= workArea.Height - this.Height + 1) { this.Top--; } } } private void SetLongPressTimer(bool isStart) { if (isStart) { LongPressTimer.Start(); } else { LongPressTimer.Stop(); pressed_count = 0; isDown = false; } } private void LongPressTimerTick(object sender, EventArgs e) { pressed_count ++; if (pressed_count > 15) { if (isCaps) { SendKeys.SendWait(KeyCodeCapsLetter[key_pressed]); } else { SendKeys.SendWait(KeyCodeSmallLetter[key_pressed]); } } } private void notifyIconMenuItem_Click(object sender, EventArgs e) { this.Close(); } private void Window_Closed(object sender, EventArgs e) { notifyIcon.Dispose(); } } }
xaml:
<Window x:Class="TouchKeyboard.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TouchKeyboard" mc:Ignorable="d" Title="MainWindow" Topmost="True" Loaded="Window_Loaded" Left="0" Top="0" Height="296" Width="1280" WindowStyle="None" Visibility="Visible" AllowsTransparency="True" Closed="Window_Closed" ResizeMode="NoResize" Focusable="False" ShowInTaskbar="False" Background="Black"> <Grid> <Canvas x:Name="CanvasWindow"> </Canvas> </Grid> </Window>
END
沒有留言:
張貼留言