zoukankan      html  css  js  c++  java
  • C# WinForm 下的虚拟键盘

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
     
    namespace VirtualKeyboard
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new vkForm());
            }
        }
     
        public class vkButton : Label
        {
     
            public vkButton(string text)
            {
                New(text, new Size(30, 30), new Font("tahoma", 12, FontStyle.Bold));
            }
     
            public vkButton(string text, Size size, Font font)
            {
                New(text, size, font);
            }
     
            public void New(string text, Size size, Font font)
            {
                this.Text = text;   //设置控件的 Text 属性
                this.Font = font;  //控件所使用的字体
                this.Size = size;  //控件呈现的大小尺寸
                //定义控件为自绘模式并使用双缓存
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint
                                | ControlStyles.OptimizedDoubleBuffer, true);
                //添加鼠标事件响应事件
                this.MouseUp += new MouseEventHandler(btnNormal);
                this.MouseDown += new MouseEventHandler(btnPressed);
                this.MouseLeave += new EventHandler(btnNormal);
                this.MouseHover += new EventHandler(btnHover);
                //实例化后默认常规状态的颜色
                this.NormalColor = Color.LightSteelBlue;
                this.HoverColor = Color.Orange;
                this.PressedColor = Color.Red;
            }
     
            public Color HoverColor { setget; }    //鼠标激活时的颜色的属性
            public Color NormalColor { setget; } //正常状态的颜色的属性
            public Color PressedColor { set; get; } //鼠标按下时的颜色的属性
     
            private void btnNormal(object o, EventArgs e)
            {
                //这里绘画常规状态的控件界面
                Graphics graphic = this.CreateGraphics(); //创建绘图对象
                btnPaint(graphic, this.ForeColor, NormalColor); //绘画界面
                graphic.Dispose(); //及时释放对象资源
            }
     
            private void btnHover(object o, EventArgs e)
            {
                //这里绘画鼠标激活时的控件界面
                Graphics graphic = this.CreateGraphics();
                btnPaint(graphic, this.ForeColor, HoverColor);
                graphic.Dispose();
            }
     
            private void btnPressed(object o, EventArgs e)
            {
                //这里绘画鼠标按下后的控件界面
                Graphics graphic = this.CreateGraphics();
                btnPaint(graphic, this.ForeColor, PressedColor);
                graphic.Dispose();
            }
     
            protected override void OnPaint(PaintEventArgs e)
            {
                btnPaint(e.Graphics, this.ForeColor, this.NormalColor);
            }
     
            /* 此方法用于根据传入的参数绘制控件界面*/
            private void btnPaint(Graphics graphic, Color foreColor, Color backgroundColor)
            {
                graphic.Clear(this.BackColor);  //以背景色清除图象
                Color lightColor, darkColor;    //定义高亮和暗部分的颜色
                StringFormat textFormat = new StringFormat(); //用于设置文字格式
                LinearGradientBrush brush; //定义渐变笔刷
                Rectangle rect = new Rectangle(0, 0, this.Width - 1, this.Height - 1); //获取矩型区域
                lightColor = Color.FromArgb(0, backgroundColor);  //获取高亮颜色
                darkColor = Color.FromArgb(255, backgroundColor); //获取暗颜色
                //生成渐变笔刷实例
                brush = new LinearGradientBrush(rect, lightColor, darkColor,
                                                                LinearGradientMode.BackwardDiagonal);
     
                graphic.FillRectangle(brush, rect); //使用渐变画笔刷填充 
                graphic.DrawRectangle(new Pen(foreColor), rect); //使用前景色画边框
                textFormat.Alignment = StringAlignment.Center; //设置文字垂直对齐方式          
                textFormat.LineAlignment = StringAlignment.Center; //设置文字水平对齐方式
                //绘画控件显示的正文
                graphic.DrawString(this.Text, this.Font, new SolidBrush(foreColor), rect, textFormat);
            }
        }
     
        public static class Win32API
        {
            [DllImport("user32.dll", EntryPoint = "SendMessageW")]
            public static extern int SendMessage(
                 int hwnd,
                 int wMsg,
                 int wParam,
                 int lParam);
     
            [DllImport("user32.dll", EntryPoint = "PostMessageW")]
            public static extern int PostMessage(
                 int hwnd,
                 int wMsg,
                 int wParam,
                 int lParam);
     
            [DllImport("user32.dll")]
            public static extern int GetForegroundWindow();
     
            [DllImport("user32.dll")]
            public static extern int GetFocus();
     
            [DllImport("user32.dll")]
            public static extern int AttachThreadInput(
                 int idAttach,
                 int idAttachTo,
                 int fAttach);
     
            [DllImport("user32.dll")]
            public static extern int GetWindowThreadProcessId(
                 int hwnd,
                 int lpdwProcessId);
     
            [DllImport("kernel32.dll")]
            public static extern int GetCurrentThreadId();
     
            public const int WM_MOUSEACTIVATE = 0x21;
            public const int WM_KEYDOWN = 0x100;
            public const int MA_NOACTIVATE = 3;
            public const int WS_EX_NOACTIVATE = 0x8000000;
        }
     
        public class vkForm : Form
        {
            private vkButton[] vk = new vkButton[36];
            private vkButton btnExit;
            private Point offset;
     
            protected override void OnLoad(EventArgs e)
            {
                btnExit = new vkButton("Exit Sample");
                btnExit.Dock = DockStyle.Bottom;
                btnExit.Size = new Size(130, 30);
                //先添加26个字母的虚拟按键
                for (int i = 0; i < 26; i++)
                {
                    //使用刚才建立的按钮类实例化每个虚拟按钮
                    //字母A对应ASCII代码为 65,即B为 66,如此类推
                    vk[i] = new vkButton(((char)(i + 65)).ToString());
                }
                //继续添加0-9的数字键
                for (int i = 0; i < 10; i++)
                {
                    //实例化各个数字的虚拟按钮,0 对应ASCII代码为 48
                    vk[26 + i] = new vkButton(((char)(i + 48)).ToString());
                }
                this.TopMost = true;
                this.ControlBox = false;
                this.Size = new Size(330, 180);
                this.Controls.AddRange(vk);    //加入所有的虚拟按键
                this.Controls.Add(btnExit);  //加入一个退出程序的按钮
                int x = 10;
                int y = 10;
                for (int i = 0; i < vk.Length; i++)
                {
                    vk[i].Click += btnCommon_Click;  //为按钮添加事件响应
                    vk[i].Location = new Point(x, y);
                    x += 32 + 2;
                    if (x + 32 >= this.Width)
                    {
                        y += 32;
                        x = 10;
                    }
                }
                btnExit.Click += btnExit_Click; //为退出按钮添加事件响应
            }
     
            protected override void OnMouseMove(MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Left)
                {
                    Point offset = e.Location;
                    offset = this.PointToScreen(e.Location);
                    this.Left = offset.X - this.offset.X;
                    this.Top = offset.Y - this.offset.Y;
                }
            }
     
            protected override void OnMouseDown(MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Left)
                {
                    offset = e.Location;
                }
            }
     
            private void AttachThreadInput(bool b)
            {
                //设置线程亲和,附到前台窗口所在线程,只有在线程内才可以获取线程内控件的焦点
                //线程亲和: AttachThreadInput(目标线程标识, 当前线程标识, 非零值关联) 零表示取消
                //窗口所在的线程的标识: GetWindowThreadProcessId(窗体句柄, 这里返回进程标识)
                //当前的前台窗口的句柄: GetForegroundWindow()
                //当前程序所在的线程标识: GetCurrentThreadId()
                Win32API.AttachThreadInput(
                       Win32API.GetWindowThreadProcessId(
                                Win32API.GetForegroundWindow(), 0),
                       Win32API.GetCurrentThreadId(), Convert.ToInt32(b));
            }
     
            private void btnCommon_Click(object o, EventArgs e)
            {
                AttachThreadInput(true); //设置线程亲和的关联
                int getFocus = Win32API.GetFocus();
                //o为object类型,使用强制转换成vkButton
                char keyvalue = ((vkButton)o).Text.ToCharArray()[0];
                //向前台窗口发送按键消息
                Win32API.PostMessage(getFocus, Win32API.WM_KEYDOWN, (byte)keyvalue, 0);
                AttachThreadInput(false); //取消线程亲和的关联
            }
     
            private void btnExit_Click(object o, EventArgs e)
            {
                Application.Exit();
            }
     
            protected override void WndProc(ref Message m)
            {
                base.WndProc(ref m);
                //若在窗体上产生鼠标点击事件的消息则使消息返回值标记为不激活
                //程序内部的窗口切换仅需返回 MA_NOACTIVATE 即可,若相对其它
                //的程序窗口切换时 还需要设置 WS_EX_NOACTIVATE 样式
                if (m.Msg == Win32API.WM_MOUSEACTIVATE)
                    m.Result = (IntPtr)Win32API.MA_NOACTIVATE;
                    //MA_ACTIVATE 激活窗体,但不删除鼠标消息。
                    //MA_NOACTIVATE 不激活窗体,也不删除鼠标消息。
                    //MA_ACTIVATEANDEAT 激活窗体,删除鼠标消息。
                    //MA_NOACTIVATEANDEAT 不激活窗体,但删除鼠标消息。
            }
     
            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    //为窗体样式添加不激活标识
                    cp.ExStyle = Win32API.WS_EX_NOACTIVATE;
                    return cp;
                }
            }
        }
    }
  • 相关阅读:
    Redis分布式锁的正确实现方式
    Redis+Jedis封装工具类
    MyCat配置文件详解--server.xml
    linux buff/cache释放
    mycat中间件--schema.xml配置文件详解
    mycat中间件--linux安装mycat1.6版本
    如何查找SHELL的进程号并杀死
    dubbo常用配置及注意事项
    xxxx
    解决docker镜像无法下载的问题
  • 原文地址:https://www.cnblogs.com/s115/p/4096128.html
Copyright © 2011-2022 走看看