C# 创建一个窗体,该窗体中有多个控件例如 lable textBox richTextBox等,或者是调用一个网页 可能是 jsp 网页或者.net 等多种网页实现这样的效果 ,用钩子 hook 实现虚拟鼠标 当其点击 窗体中textBox  richTextBox (即有焦点可输入的控件) 时弹出一个虚拟键盘  并输入东西谢谢大家顶贴,祝大家工作顺利!

解决方案 »

  1.   

    虚拟键盘?//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 { set; get; }    //鼠标激活时的颜色的属性
            public Color NormalColor { set; get; } //正常状态的颜色的属性
            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;
            }
            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    //为窗体样式添加不激活标识
                      cp.ExStyle = Win32API.WS_EX_NOACTIVATE;
                    return cp;
                }
            }
        }
    }
      

  2.   

    可以用程序调用系统软件盘。
    例子:using System;  using System.Collections.Generic;  using System.ComponentModel;  using System.Data; 
     using System.Drawing;
      using System.Text; 
     using System.Windows.Forms;  
    using System.Runtime.InteropServices; 
      namespace InputLanguageSwitch  {  
    /// <summary> 
    /// 获取系统所有的输入法,并可以程序改变当前输入法;打开关闭软键盘。
     /// </summary> public partial class Form1 : Form  

     public Form1()  {  InitializeComponent();  this.InputLanguageChanged += new InputLanguageChangedEventHandler(Form1_InputLanguageChanged);  }   void Form1_InputLanguageChanged(object sender, InputLanguageChangedEventArgs e)  {  //throw new Exception("The method or operation is not implemented.");  for( int i=0;i<comboBox1.Items.Count;i++)  {  if (InputLanguage.CurrentInputLanguage.LayoutName == comboBox1.Items[i].ToString())  {  comboBox1.SelectedIndex = i;  }   }  }   private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)  {  string strTemp = comboBox1.Items[comboBox1.SelectedIndex].ToString();  InputLanguageCollection collects = InputLanguage.InstalledInputLanguages;  for (int i = 0; i < collects.Count; i++)  {  if (collects[i].LayoutName == strTemp)  InputLanguage.CurrentInputLanguage = collects[i];  }   }   private void Form1_Load(object sender, EventArgs e)  {  InputLanguageCollection collects = InputLanguage.InstalledInputLanguages;  for (int i = 0; i < collects.Count; i++)  {  comboBox1.Items.Add(collects[i].LayoutName);  }  comboBox1.SelectedIndex = collects.IndexOf(InputLanguage.CurrentInputLanguage);  }   private void button1_Click(object sender, EventArgs e)  {  this.textBox1.Focus();  IntPtr hwndInput = ImmGetContext(this.Handle);  IntPtr dw1 = IntPtr.Zero;  IntPtr dw2 = IntPtr.Zero;  bool isSuccess = ImmGetConversionStatus(hwndInput, ref dw1, ref dw2);  if (isSuccess)  {  int intTemp = dw1.ToInt32() & IME_CMODE_SOFTKBD;  if (intTemp > 0)  dw1 = (IntPtr)(dw1.ToInt32() ^ IME_CMODE_SOFTKBD);  else  dw1 = (IntPtr)(dw1.ToInt32() IME_CMODE_SOFTKBD);  }  isSuccess = ImmSetConversionStatus(hwndInput, dw1, dw2);  ImmReleaseContext(this.Handle, hwndInput);  }   public const int IME_CMODE_SOFTKBD = 0x80;   [DllImport("imm32.dll", EntryPoint = "ImmGetContext")]  public static extern IntPtr ImmGetContext(  IntPtr hwnd  );  [DllImport("imm32.dll", EntryPoint = "ImmGetConversionStatus")]  public static extern bool ImmGetConversionStatus(  IntPtr himc,  ref IntPtr lpdw,  ref IntPtr lpdw2  );  [DllImport("imm32.dll", EntryPoint = "ImmSetConversionStatus")]  public static extern bool ImmSetConversionStatus(  IntPtr himc,  IntPtr dw1,  IntPtr dw2  );   [DllImport("imm32.dll", EntryPoint = "ImmReleaseContext")]  public static extern int ImmReleaseContext(  IntPtr hwnd,  IntPtr himc  );   }  } 摘自:http://developer.51cto.com/art/200908/145542.htm
      

  3.   

    控件需要自己添加。一个ComboBox,一个Textbox,一个Button,直接拖进去没有更改name
    回复时没有整理,有点乱。
      

  4.   

    那怎么样判断  虚拟鼠标 是否点击 窗体中textBox richTextBox (即有焦点可输入的控件) ?
      

  5.   

    可以通过WIN32编程来实现                var h = Win32Api.FindWindowEx(PlayerView.Handle, new IntPtr(0), null, null);
                    var hwnd = Win32Api.FindWindowEx(h, new IntPtr(0), "Internet Explorer_Server", null);
                    if (Win32Api.GetFocus() == hwnd)
                    {
                        switch (e.nCode)
                        {
                            case 0x0003:                            var htmlDocument2 = PlayerView.Document as IHTMLDocument2;
                                var element = htmlDocument2.activeElement;
                                if (htmlDocument2 != null)
                                {
                                    while (element != null && element.tagName.ToLower() == "iframe")
                                    {
                                        element =
                                            (CrossFrameIE.GetDocumentFromWindow((element as HTMLIFrameClass).contentWindow)
                                             as IHTMLDocument2).activeElement;
                                    }
                                    var editable = (bool)element.getAttribute("isContentEditable");//判断元素是否可编辑
                                    if (/*!element.isTextEdit && */!editable && e.wParam == 8)
                                    {
                                        e.Handled = true;
                                    }                            }
                                break;
                        }
                    }
    主要判断出是否是可编辑的?然后后面的处理应该知道了吧
      

  6.   


    我想问下你的这些代码  应该放在哪个事件下啊?Form2_MouseClick 、Form2_MouseDown ?  还是其他的啊?