公司給客戶開發的web程式A,有個表單里面是專案資訊,客戶有另一個web程式B(另一個公司開發的),也有一個表單里面是專案資訊,現在客戶要求,填寫A時要把比較長的內容(比如專案名稱)自動填寫到B的表單上,由于瀏覽器的同源策略以及對剪切板訪問的限制,顧通過js操作剪切板這個思路基本走不通。
后來上網查閱相關內容改用如下思路:
1.程式A中通過JS操作剪切板將專案資訊存放到剪切板
2.C#開發一個winform程式,該程式加了一個定時器,每秒取一次剪切板,將專案資訊讀取存放到一個陣列中,在該程式中通過鍵盤鉤子監聽ALT+P按鍵,先點擊程式B的表單使獲得焦點,按下ALT+P按鍵時,將陣列內容通過剪切板和模擬鍵盤ctrl+v和tab操作,依次復制到目標表單中。
目前遇到的問題是當按下ALT+P時,程式B的表單立刻失去焦點(我把表單換成一個空的文本檔案用記事本打開測驗,記事本也失去焦點),由于失去焦點,模擬按鍵ctrl+v和tab操作也無法完成后續動作,我在回應函式加了System.Windows.Forms.MessageBox.Show彈窗,當點擊彈窗確認按鈕時卻運行正常,請問大神這是什么原因
因為字數限制只能截取部分代碼了,后面會貼出來的,謝謝大家
//3.判斷輸入鍵值(實作KeyDown事件)
private void hook_KeyDown(object sender, KeyEventArgs e)
{
//判斷按下的鍵(Alt + P)
if (e.KeyValue == (int)Keys.P && (int)Control.ModifierKeys == (int)Keys.Alt)
{
//System.Windows.Forms.MessageBox.Show("按下了指定快捷鍵組合");
strArr[0] = this.textBox1.Text;
strArr[1] = this.textBox2.Text;
strArr[2] = this.textBox3.Text;
strArr[3] = this.textBox4.Text;
//radioButton1對應公開招標單選按鈕
if (this.radioButton1.Checked)
{
publicBid();
}
////radioButton2對應競價采購單選按鈕
if (this.radioButton2.Checked) {
priceBid();
}
}
}
[System.Runtime.InteropServices.DllImport("user32")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
//移動滑鼠
const int MOUSEEVENTF_MOVE = 0x0001;
//模擬滑鼠左鍵按下
const int MOUSEEVENTF_LEFTDOWN = 0x0002;
//模擬滑鼠左鍵抬起
const int MOUSEEVENTF_LEFTUP = 0x0004;
//模擬滑鼠右鍵按下
const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
//模擬滑鼠右鍵抬起
const int MOUSEEVENTF_RIGHTUP = 0x0010;
//模擬滑鼠中鍵按下
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
//模擬滑鼠中鍵抬起
const int MOUSEEVENTF_MIDDLEUP = 0x0040;
//標示是否采用絕對坐標
const int MOUSEEVENTF_ABSOLUTE = 0x8000;
private void publicBid()
{
//mouse_event模擬滑鼠單擊是為了強制讓表單B獲取焦點,實際上加了也沒用
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
foreach (string v in strArr)
{
//System.Windows.Forms.MessageBox.Show(v);
Clipboard.SetText(v);
ctrlVClick();
tabClick();
}
}
private void priceBid()
{
//mouse_event模擬滑鼠單擊是為了強制讓表單B獲取焦點,實際上加了也沒用
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
for (int i = 0; i < hitNumbers; i++)
{
//System.Windows.Forms.MessageBox.Show(strArr[i]);
Clipboard.SetText(strArr[i]);
ctrlVClick();
tabClick();
if (i == 2)
{
tabClick();
}
}
}
下面是程式運行截圖
uj5u.com熱心網友回復:
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Macros
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
var k_hook = new KeyboardHook();
k_hook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);
k_hook.Start();//安裝鍵盤鉤子
}
//3.判斷輸入鍵值(實作KeyDown事件)
private void hook_KeyDown(object sender, KeyEventArgs e)
{
//判斷按下的鍵(Alt + P)
if (e.KeyValue == (int)Keys.P && (int)Control.ModifierKeys == (int)Keys.Alt)
{
//System.Windows.Forms.MessageBox.Show("按下了指定快捷鍵組合");
strArr[0] = this.textBox1.Text;
strArr[1] = this.textBox2.Text;
strArr[2] = this.textBox3.Text;
strArr[3] = this.textBox4.Text;
if (this.radioButton1.Checked)
{
publicBid();
}
if (this.radioButton2.Checked) {
priceBid();
}
}
}
public String[] strArr=new String[4];
public const int hitNumbers=4;
#region bVk引數 常量定義
public const byte vbKeyLButton = 0x1; // 滑鼠左鍵
public const byte vbKeyRButton = 0x2; // 滑鼠右鍵
public const byte vbKeyCancel = 0x3; // CANCEL 鍵
public const byte vbKeyMButton = 0x4; // 滑鼠中鍵
public const byte vbKeyBack = 0x8; // BACKSPACE 鍵
public const byte vbKeyTab = 0x9; // TAB 鍵
public const byte vbKeyClear = 0xC; // CLEAR 鍵
public const byte vbKeyReturn = 0xD; // ENTER 鍵
public const byte vbKeyShift = 0x10; // SHIFT 鍵
public const byte vbKeyControl = 0x11; // CTRL 鍵
public const byte vbKeyAlt = 18; // Alt 鍵 (鍵碼18)
public const byte vbKeyMenu = 0x12; // MENU 鍵
public const byte vbKeyPause = 0x13; // PAUSE 鍵
public const byte vbKeyCapital = 0x14; // CAPS LOCK 鍵
public const byte vbKeyEscape = 0x1B; // ESC 鍵
public const byte vbKeySpace = 0x20; // SPACEBAR 鍵
public const byte vbKeyPageUp = 0x21; // PAGE UP 鍵
public const byte vbKeyEnd = 0x23; // End 鍵
public const byte vbKeyHome = 0x24; // HOME 鍵
public const byte vbKeyLeft = 0x25; // LEFT ARROW 鍵
public const byte vbKeyUp = 0x26; // UP ARROW 鍵
public const byte vbKeyRight = 0x27; // RIGHT ARROW 鍵
public const byte vbKeyDown = 0x28; // DOWN ARROW 鍵
public const byte vbKeySelect = 0x29; // Select 鍵
public const byte vbKeyPrint = 0x2A; // PRINT SCREEN 鍵
public const byte vbKeyExecute = 0x2B; // EXECUTE 鍵
public const byte vbKeySnapshot = 0x2C; // SNAPSHOT 鍵
public const byte vbKeyDelete = 0x2E; // Delete 鍵
public const byte vbKeyHelp = 0x2F; // HELP 鍵
public const byte vbKeyNumlock = 0x90; // NUM LOCK 鍵
//常用鍵 字母鍵A到Z
public const byte vbKeyA = 65;
public const byte vbKeyB = 66;
public const byte vbKeyC = 67;
public const byte vbKeyD = 68;
public const byte vbKeyE = 69;
public const byte vbKeyF = 70;
public const byte vbKeyG = 71;
public const byte vbKeyH = 72;
public const byte vbKeyI = 73;
public const byte vbKeyJ = 74;
public const byte vbKeyK = 75;
public const byte vbKeyL = 76;
public const byte vbKeyM = 77;
public const byte vbKeyN = 78;
public const byte vbKeyO = 79;
public const byte vbKeyP = 80;
public const byte vbKeyQ = 81;
public const byte vbKeyR = 82;
public const byte vbKeyS = 83;
public const byte vbKeyT = 84;
public const byte vbKeyU = 85;
public const byte vbKeyV = 86;
public const byte vbKeyW = 87;
public const byte vbKeyX = 88;
public const byte vbKeyY = 89;
public const byte vbKeyZ = 90;
//數字鍵盤0到9
public const byte vbKey0 = 48; // 0 鍵
public const byte vbKey1 = 49; // 1 鍵
public const byte vbKey2 = 50; // 2 鍵
public const byte vbKey3 = 51; // 3 鍵
public const byte vbKey4 = 52; // 4 鍵
public const byte vbKey5 = 53; // 5 鍵
public const byte vbKey6 = 54; // 6 鍵
public const byte vbKey7 = 55; // 7 鍵
public const byte vbKey8 = 56; // 8 鍵
public const byte vbKey9 = 57; // 9 鍵
public const byte vbKeyNumpad0 = 0x60; //0 鍵
public const byte vbKeyNumpad1 = 0x61; //1 鍵
public const byte vbKeyNumpad2 = 0x62; //2 鍵
public const byte vbKeyNumpad3 = 0x63; //3 鍵
public const byte vbKeyNumpad4 = 0x64; //4 鍵
public const byte vbKeyNumpad5 = 0x65; //5 鍵
public const byte vbKeyNumpad6 = 0x66; //6 鍵
public const byte vbKeyNumpad7 = 0x67; //7 鍵
public const byte vbKeyNumpad8 = 0x68; //8 鍵
public const byte vbKeyNumpad9 = 0x69; //9 鍵
public const byte vbKeyMultiply = 0x6A; // MULTIPLICATIONSIGN(*)鍵
public const byte vbKeyAdd = 0x6B; // PLUS SIGN(+) 鍵
public const byte vbKeySeparator = 0x6C; // ENTER 鍵
public const byte vbKeySubtract = 0x6D; // MINUS SIGN(-) 鍵
public const byte vbKeyDecimal = 0x6E; // DECIMAL POINT(.) 鍵
public const byte vbKeyDivide = 0x6F; // DIVISION SIGN(/) 鍵
//F1到F12按鍵
public const byte vbKeyF1 = 0x70; //F1 鍵
public const byte vbKeyF2 = 0x71; //F2 鍵
public const byte vbKeyF3 = 0x72; //F3 鍵
public const byte vbKeyF4 = 0x73; //F4 鍵
public const byte vbKeyF5 = 0x74; //F5 鍵
public const byte vbKeyF6 = 0x75; //F6 鍵
public const byte vbKeyF7 = 0x76; //F7 鍵
public const byte vbKeyF8 = 0x77; //F8 鍵
public const byte vbKeyF9 = 0x78; //F9 鍵
public const byte vbKeyF10 = 0x79; //F10 鍵
public const byte vbKeyF11 = 0x7A; //F11 鍵
public const byte vbKeyF12 = 0x7B; //F12 鍵
#endregion
#region
[System.Runtime.InteropServices.DllImport("user32")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
//移動滑鼠
const int MOUSEEVENTF_MOVE = 0x0001;
//模擬滑鼠左鍵按下
const int MOUSEEVENTF_LEFTDOWN = 0x0002;
//模擬滑鼠左鍵抬起
const int MOUSEEVENTF_LEFTUP = 0x0004;
//模擬滑鼠右鍵按下
const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
//模擬滑鼠右鍵抬起
const int MOUSEEVENTF_RIGHTUP = 0x0010;
//模擬滑鼠中鍵按下
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
//模擬滑鼠中鍵抬起
const int MOUSEEVENTF_MIDDLEUP = 0x0040;
//標示是否采用絕對坐標
const int MOUSEEVENTF_ABSOLUTE = 0x8000;
#endregion
#region 參考win32api方法
/// <summary>
/// 匯入模擬鍵盤的方法
/// </summary>
/// <param name="bVk" >按鍵的虛擬鍵值</param>
/// <param name= "bScan" >掃描碼,一般不用設定,用0代替就行</param>
/// <param name= "dwFlags" >選項標志:0:表示按下,2:表示松開</param>
/// <param name= "dwExtraInfo">一般設定為0</param>
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
#endregion
private void tabClick()
{
keybd_event(vbKeyTab, 0, 0, 0);
keybd_event(vbKeyTab, 0, 2, 0);
}
private void ctrlVClick()
{
keybd_event(vbKeyControl, 0, 0, 0);
keybd_event(vbKeyV, 0, 0, 0);
keybd_event(vbKeyControl, 0, 2, 0);
keybd_event(vbKeyV, 0, 2, 0);
}
private void publicBid()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
foreach (string v in strArr)
{
//System.Windows.Forms.MessageBox.Show(v);
Clipboard.SetText(v);
ctrlVClick();
tabClick();
}
}
private void priceBid()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
for (int i = 0; i < hitNumbers; i++)
{
//System.Windows.Forms.MessageBox.Show(strArr[i]);
Clipboard.SetText(strArr[i]);
ctrlVClick();
tabClick();
if (i == 2)
{
tabClick();
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
// GetDataObject檢索當前剪貼板上的資料
IDataObject iData = Clipboard.GetDataObject();
//將資料與指定的格式進行匹配,回傳bool
if (iData.GetDataPresent(DataFormats.Text))
{
// GetData檢索資料并指定一個格式
//this.textBox1.Text = (string)iData.GetData(DataFormats.Text);
String myStr = (string)iData.GetData(DataFormats.Text);
if (!string.IsNullOrEmpty(myStr))
{
if(myStr.Contains("|")){
strArr = myStr.Split(new Char[] { '|' });
if (strArr.Length == 4)
{
this.textBox1.Text = strArr[0] == "NULL" ? "" : strArr[0];
this.textBox2.Text = strArr[1] == "NULL" ? "" : strArr[1];
this.textBox3.Text = strArr[2] == "NULL" ? "" : strArr[2];
this.textBox4.Text = strArr[3] == "NULL" ? "" : strArr[3];
uj5u.com熱心網友回復:
上面是主程式代碼uj5u.com熱心網友回復:
using System;using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Reflection;
namespace Macros
{
class KeyboardHook
{
public event KeyEventHandler KeyDownEvent;
public event KeyPressEventHandler KeyPressEvent;
public event KeyEventHandler KeyUpEvent;
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
static int hKeyboardHook = 0; //宣告鍵盤鉤子處理的初始值
//值在Microsoft SDK的Winuser.h里查詢
//轉載自http://www.bianceng.cn/Programming/csharp/201410/45484.htm
public const int WH_KEYBOARD_LL = 13; //執行緒鍵盤鉤子監聽滑鼠訊息設為2,全域鍵盤監聽滑鼠訊息設為13
HookProc KeyboardHookProcedure; //宣告KeyboardHookProcedure作為HookProc型別
//鍵盤結構
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode; //定一個虛擬鍵碼。該代碼必須有一個價值的范圍1至254
public int scanCode; // 指定的硬體掃描碼的關鍵
public int flags; // 鍵標志
public int time; // 指定的時間戳記的這個訊息
public int dwExtraInfo; // 指定額外資訊相關的資訊
}
//使用此功能,安裝了一個鉤子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
//呼叫此函式卸載鉤子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//使用此功能,通過資訊鉤子繼續下一個鉤子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
// 取得當前執行緒編號(執行緒鉤子需要用到)
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
//使用WINDOWS API函式代替獲取當前實體的函式,防止鉤子失效
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
public void Start()
{
// 安裝鍵盤鉤子
if (hKeyboardHook == 0)
{
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);
//hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
//************************************
//鍵盤執行緒鉤子
//SetWindowsHookEx( 2,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());//指定要監聽的執行緒idGetCurrentThreadId(),
//鍵盤全域鉤子,需要參考空間(using System.Reflection;)
//SetWindowsHookEx( 13,MouseHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
//
//關于SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId)函式將鉤子加入到鉤子鏈表中,說明一下四個引數:
//idHook 鉤子型別,即確定鉤子監聽何種訊息,上面的代碼中設為2,即監聽鍵盤訊息并且是執行緒鉤子,如果是全域鉤子監聽鍵盤訊息應設為13,
//執行緒鉤子監聽滑鼠訊息設為7,全域鉤子監聽滑鼠訊息設為14。lpfn 鉤子子程的地址指標。如果dwThreadId引數為0 或是一個由別的行程創建的
//執行緒的標識,lpfn必須指向DLL中的鉤子子程。 除此以外,lpfn可以指向當前行程的一段鉤子子程代碼。鉤子函式的入口地址,當鉤子鉤到任何
//訊息后便呼叫這個函式。hInstance應用程式實體的句柄。標識包含lpfn所指的子程的DLL。如果threadId 標識當前行程創建的一個執行緒,而且子
//程代碼位于當前行程,hInstance必須為NULL。可以很簡單的設定其為本應用程式的實體句柄。threaded 與安裝的鉤子子程相關聯的執行緒的識別符號
//如果為0,鉤子子程與所有的執行緒關聯,即為全域鉤子
//************************************
//如果SetWindowsHookEx失敗
if (hKeyboardHook == 0)
{
Stop();
throw new Exception("安裝鍵盤鉤子失敗");
}
}
}
public void Stop()
{
bool retKeyboard = true;
if (hKeyboardHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
}
if (!(retKeyboard)) throw new Exception("卸載鉤子失敗!");
}
//ToAscii職能的轉換指定的虛擬鍵碼和鍵盤狀態的相應字符或字符
[DllImport("user32")]
public static extern int ToAscii(int uVirtKey, //[in] 指定虛擬關鍵代碼進行翻譯。
int uScanCode, // [in] 指定的硬體掃描碼的關鍵須翻譯成英文。高階位的這個值設定的關鍵,如果是(不壓)
byte[] lpbKeyState, // [in] 指標,以256位元組陣列,包含當前鍵盤的狀態。每個元素(位元組)的陣列包含狀態的一個關鍵。如果高階位的位元組是一套,關鍵是下跌(按下)。在低位元,如果設定表明,關鍵是對切換。在此功能,只有肘位的CAPS LOCK鍵是相關的。在切換狀態的NUM個鎖和滾動鎖定鍵被忽略。
byte[] lpwTransKey, // [out] 指標的緩沖區收到翻譯字符或字符。
int fuState); // [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise.
//獲取按鍵的狀態
[DllImport("user32")]
public static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern short GetKeyState(int vKey);
private const int WM_KEYDOWN = 0x100;//KEYDOWN
private const int WM_KEYUP = 0x101;//KEYUP
private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN
private const int WM_SYSKEYUP = 0x105;//SYSKEYUP
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
// 偵聽鍵盤事件
if ((nCode >= 0) && (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null))
{
KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
// raise KeyDown
if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyDownEvent(this, e);
}
//鍵盤按下
if (KeyPressEvent != null && wParam == WM_KEYDOWN)
{
byte[] keyState = new byte[256];
GetKeyboardState(keyState);
byte[] inBuffer = new byte[2];
if (ToAscii(MyKeyboardHookStruct.vkCode, MyKeyboardHookStruct.scanCode, keyState, inBuffer, MyKeyboardHookStruct.flags) == 1)
{
KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);
KeyPressEvent(this, e);
}
}
// 鍵盤抬起
if (KeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyUpEvent(this, e);
}
}
//如果回傳1,則結束訊息,這個訊息到此為止,不再傳遞。
//如果回傳0或呼叫CallNextHookEx函式則訊息出了這個鉤子繼續往下傳遞,也就是傳給訊息真正的接受者
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
~KeyboardHook()
{
Stop();
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/146942.html
標籤:C#
