C#獲取當前活動視窗控制代碼
c# 獲取當前活動視窗控制代碼,獲取視窗大小及位置
2018年04月26日 13:48:21 漂泊_人生 閱讀數:1889需呼叫API函式
需在開頭引入名稱空間
using System.Runtime.InteropServices;
獲取當前視窗控制代碼:GetForegroundWindow()
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
返回值型別是IntPtr,即為當前獲得焦點視窗的控制代碼
使用方法 : IntPtr myPtr=GetForegroundWindow();
獲取到該視窗控制代碼後,可以對該視窗進行操作.比如,關閉該視窗或在該視窗隱藏後,使其顯示
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
其中ShowWindow(IntPtr hwnd, int nCmdShow);
nCmdShow的含義
0 關閉視窗
1 正常大小顯示視窗
2 最小化視窗
3 最大化視窗
使用例項: ShowWindow(myPtr, 0);
獲取視窗大小及位置:需要呼叫方法GetWindowRect(IntPtr hWnd, ref RECT lpRect)
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; //最左座標
public int Top; //最上座標
public int Right; //最右座標
public int Bottom; //最下座標
}
示例:
InPtr awin = GetForegroundWindow(); //獲取當前視窗控制代碼
RECT rect = new RECT();
GetWindowRect(awin, ref rect);
int width = rc.Right - rc.Left; //視窗的寬度
int height = rc.Bottom - rc.Top; //視窗的高度
int x = rc.Left;
int y = rc.Top;
------------------------------------------------------------------------
C#中的FindWindow
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint="FindWindow")]
public static extern int FindWindow (
string lpClassName,
string lpWindowName
);
已知視窗標題"abc",怎麼得到視窗控制代碼?
IntPtr hWnd = FindWindow(null, "abc");
-------------------------------------------------------
C#使用FindWindow()函式:
[DllImport("coredll.dll", EntryPoint = "FindWindow")]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
這個函式有兩個引數,第一個是要找的視窗的類,第二個是要找的視窗的標題。在搜尋的時候不一定兩者都知道,但至少要知道其中的一個。有的視窗的標題是比較容易得到的,如"計算器",所以搜尋時應使用標題進行搜尋。但有的軟體的標題不是固定的,如"記事本",如果開啟的檔案不同,視窗標題也不同,這時使用視窗類搜尋就比較方便。如果找到了滿足條件的視窗,這個函式返回該視窗的控制代碼,否則返回0。 看例子
IntPtr ParenthWnd = new IntPtr(0);
ParenthWnd = FindWindow(null,"Word Mobile");
//判斷這個窗體是否有效
if (ParenthWnd != IntPtr.Zero)
{
MessageBox.Show("找到視窗");
}
else
MessageBox.Show("沒有找到視窗");
從上面的討論中可以看出,如果要搜尋的外部程式的視窗標題比較容易得到,問題是比較簡單的。可如果視窗的標題不固定或者根本就沒有標題,怎麼得到視窗的類呢?如果你安裝了Visual C++,你可以使用其中的Spy,在Spy++中有一個FindWindow工具,它允許你使用滑鼠選擇視窗,然後Spy++會顯示這個視窗的類。
在Win32 API中還有一個FindWindowEx,它非常適合尋找子視窗。
FindWindowEx用法
函式功能:該函式獲得一個視窗的控制代碼,該視窗的類名和視窗名與給定的字串相匹配。這個函式查詢子視窗,從排在給定的子視窗後面的下一個子視窗開始。在查詢時不區分大小寫。
函式原型:HWND FindWindowEx(HWND hwndParent,HWND hwndChildAfter,LPCTSTR lpszClass,LPCTSTR lpszWindow);
引數:
hwndParent:要查詢子視窗的父視窗控制代碼。
如果hwnjParent為NULL,則函式以桌面視窗為父視窗,查詢桌面視窗的所有子視窗。
Windows NT5.0 and later:如果hwndParent是HWND_MESSAGE,函式僅查詢所有訊息視窗。
hwndChildAfter :子視窗控制代碼。查詢從在Z序中的下一個子視窗開始。子視窗必須為hwndPareRt視窗的直接子視窗而非後代視窗。如果HwndChildAfter為NULL,查詢從hwndParent的第一個子視窗開始。如果hwndParent 和 hwndChildAfter同時為NULL,則函式查詢所有的頂層視窗及訊息視窗。
lpszClass:指向一個指定了類名的空結束字串,或一個標識類名字串的成員的指標。如果該引數為一個成員,則它必須為前次呼叫theGlobaIAddAtom函式產生的全域性成員。該成員為16位,必須位於lpClassName的低16位,高位必須為0。
lpszWindow:指向一個指定了視窗名(視窗標題)的空結束字串。如果該引數為 NULL,則為所有視窗全匹配。返回值:如果函式成功,返回值為具有指定類名和視窗名的視窗控制代碼。如果函式失敗,返回值為NULL。
C#中使用該函式首先匯入名稱空間:
01.using System.Runtime.InteropServices;
然後寫API引用部分的程式碼,放入 class 內部
01.[DllImport("user32.dll", EntryPoint = "FindWindow")]
02.private static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow )
例如:
01.const int BM_CLICK = 0xF5;
02.IntPtr maindHwnd = FindWindow(null, "QQ使用者登入"); //獲得QQ登陸框的控制代碼
03.if (maindHwnd != IntPtr.Zero)
04.{
05. IntPtr childHwnd = FindWindowEx(maindHwnd, IntPtr.Zero, null, "登入"); //獲得按鈕的控制代碼
06. if (childHwnd != IntPtr.Zero)
07. {
08. SendMessage(childHwnd, BM_CLICK, 0, 0); //傳送點選按鈕的訊息
09. }
10. else
11. {
12. MessageBox.Show("沒有找到子視窗");
13. }
14.}
15.else
16.{
17. MessageBox.Show("沒有找到視窗");
18.}
從此學習網 http://item.congci.com/item/findwindowfindwindowex
---------------------------------------------------------------------------------------
DllImport("user32", SetLastError = true)]
public static extern int GetWindowText(
IntPtr hWnd,//視窗控制代碼
StringBuilder lpString,//標題
int nMaxCount //最大值
);
//獲取類的名字
[DllImport("user32.dll")]
private static extern int GetClassName(
IntPtr hWnd,//控制代碼
StringBuilder lpString, //類名
int nMaxCount //最大值
);
//根據座標獲取視窗控制代碼
[DllImport("user32")]
private static extern IntPtr WindowFromPoint(
Point Point //座標
);
private void timer1_Tick(object sender, EventArgs e)
{
int x = Cursor.Position.X;
int y = Cursor.Position.Y;
Point p = new Point(x, y);
IntPtr formHandle = WindowFromPoint(p);//得到視窗控制代碼
StringBuilder title = new StringBuilder(256);
GetWindowText(formHandle, title, title.Capacity);//得到視窗的標題
StringBuilder className = new StringBuilder(256);
GetClassName(formHandle, className, className.Capacity);//得到視窗的控制代碼
this.textBox1.Text = title.ToString();
this.textBox2.Text = formHandle.ToString();
this.textBox3.Text = className.ToString();
}
--------------------------------------
文章不錯,收藏備用。
設計初衷:
公司為了安全性考慮,不讓密碼被太多人知道,所以想實現一個自動登入的模組。
設計思想:
主要是通過呼叫Windows API中的一些方法,找到目標視窗和程序之後把儲存在資料庫中的使用者名稱密碼自動填入輸入框中,並登入。
設計步驟:
一、呼叫Windows API。
C#下呼叫Windows API方法如下:
1、引入名稱空間:using System.Runtime.InteropServices;
2、引用需要使用的方法,格式:[DllImport("DLL檔案")]方法的宣告;
[DllImport("user32.dll")]private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]private static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[DllImport("user32.dll")]private static extern int SendMessage(IntPtr hWnd,int Msg,int wParam,int lParam);
[DllImport("user32.dll")]private static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[DllImport("user32.dll")]private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
[DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);
//ShowWindow引數
private const int SW_SHOWNORMAL = 1;
private const int SW_RESTORE = 9;
private const int SW_SHOWNOACTIVATE = 4;
//SendMessage引數
private const int WM_KEYDOWN = 0X100;
private const int WM_KEYUP = 0X101;
private const int WM_SYSCHAR = 0X106;
private const int WM_SYSKEYUP = 0X105;
private const int WM_SYSKEYDOWN = 0X104;
private const int WM_CHAR = 0X102;
二、找到目標視窗
1)、根據視窗的標題得到控制代碼
IntPtr myIntPtr = FindWindow(null,"視窗名"); //null為類名,可以用Spy++得到,也可以為空
ShowWindow(myIntPtr, SW_RESTORE); //將視窗還原
SetForegroundWindow(myIntPtr); //如果沒有ShowWindow,此方法不能設定最小化的視窗
2)、遍歷所有視窗得到控制代碼
1 定義委託方法CallBack,列舉視窗API(EnumWindows),得到視窗名API(GetWindowTextW)和得到視窗類名API(GetClassNameW)
public delegate bool CallBack(int hwnd, int lParam);
[DllImport("user32")]public static extern int EnumWindows(CallBack x, int y);
[DllImport("user32.dll")]private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
2 呼叫EnumWindows遍歷視窗
CallBack myCallBack = new CallBack(Recall);
EnumWindows(myCallBack, 0);
3 回撥方法Recall
public bool Recall(int hwnd, int lParam)
{
StringBuilder sb = new StringBuilder(256);
IntPtr PW = new IntPtr(hwnd);
GetWindowTextW(PW,sb,sb.Capacity); //得到視窗名並儲存在strName中
string strName = sb.ToString();
GetClassNameW(PW,sb,sb.Capacity); //得到視窗類名並儲存在strClass中
string strClass = sb.ToString();
if (strName.IndexOf("視窗名關鍵字") >= 0 && strClass.IndexOf("類名關鍵字") >= 0)
{
return false; //返回false中止EnumWindows遍歷
}
else
{
return true; //返回true繼續EnumWindows遍歷
}
}
3)、開啟視窗得到控制代碼
1 定義設定活動視窗API(SetActiveWindow),設定前臺視窗API(SetForegroundWindow)
[DllImport("user32.dll")]static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]static extern bool SetForegroundWindow(IntPtr hWnd);
2 開啟視窗
Process proc = Process.Start(@"目標程式路徑");
SetActiveWindow(proc.MainWindowHandle);
SetForegroundWindow(proc.MainWindowHandle);
三、向指定的視窗輸入資料
1 利用傳送訊息API(SendMessage)向視窗傳送資料
InputStr(myIntPtr, _GameID); //輸入遊戲ID
SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X09, 0); //輸入TAB(0x09)
SendMessage(myIntPtr, WM_SYSKEYUP, 0X09, 0);
InputStr(myIntPtr, _GamePass); //輸入遊戲密碼
SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X0D, 0); //輸入ENTER(0x0d)
SendMessage(myIntPtr, WM_SYSKEYUP, 0X0D, 0);
/// <summary>
/// 傳送一個字串
/// </summary>
/// <param name="myIntPtr">視窗控制代碼</param>
/// <param name="Input">字串</param>
public void InputStr(IntPtr myIntPtr, string Input)
{
byte[] ch = (ASCIIEncoding.ASCII.GetBytes(Input));
for (int i = 0; i < ch.Length; i++)
{
SendMessage(PW, WM_CHAR, ch, 0);
}
}
2 利用滑鼠和鍵盤模擬向視窗傳送資料
SetWindowPos(PW, (IntPtr)(-1), 0, 0, 0, 0, 0x0040 | 0x0001); //設定視窗位置
SetCursorPos(476, 177); //設定滑鼠位置
mouse_event(0x0002, 0, 0, 0, 0); //模擬滑鼠按下操作
mouse_event(0x0004, 0, 0, 0, 0); //模擬滑鼠放開操作
SendKeys.Send(_GameID); //模擬鍵盤輸入遊戲ID
SendKeys.Send("{TAB}"); //模擬鍵盤輸入TAB
SendKeys.Send(_GamePass); //模擬鍵盤輸入遊戲密碼
SendKeys.Send("{ENTER}"); //模擬鍵盤輸入ENTER
另:上面還提到了keybd_event方法,用法和mouse_event方法類似,作用和SendKeys.Send一樣。
C# 別人軟體裡邊做好的文字框,我如何給他賦值並且提交,最好有原始碼可供參考,如有合適的,將高額追加分
可以用WINDOWS api函式實現。
下面的WINDIWS API引用部分的程式碼,放入 class 內部
[DllImport ( "user32.dll", EntryPoint = "FindWindow", SetLastError = true )]
private static extern IntPtr FindWindow( string lpClassName, string lpWindowName );//查詢視窗控制代碼
[DllImport ( "user32.dll", EntryPoint = "FindWindowEx", SetLastError = true )]
private static extern IntPtr FindWindowEx( IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow );//查詢視窗內控制元件控制代碼
[DllImport ( "user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto )]
private static extern int SendMessage( IntPtr hwnd, uint wMsg, int wParam, int lParam );//傳送訊息
[DllImport ( "user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true )]
private static extern void SetForegroundWindow( IntPtr hwnd );// 設定視窗為啟用狀態
哈哈,現在可以開工了。我就用QQ的自動登入為列子
下面是你winfrom視窗的按鈕事件:
private void button1_Click( object sender, EventArgs e )
{
const uint WM_SETTEXT = 0x000C;//設定文字框內容的訊息
const uint BM_CLICK = 0xF5; //滑鼠點選的訊息,對於各種訊息的數值,你還是得去查查API手冊
IntPtr hwndCalc = FindWindow ( null, "QQ2011" ); //查詢QQ2011的視窗控制代碼
if ( hwndCalc != IntPtr.Zero )//找到啦
{
IntPtr hwndLogin= FindWindowEx ( hwndCalc, 0, null, "安全登入" ); //獲取登陸按鈕的控制代碼
IntPtr hwndQ = FindWindowEx ( hwndCalc, 0, “ComboBox”, "" ); //獲取QQ號碼輸入框的控制元件控制代碼
IntPtr hwndP = FindWindowEx ( hwndCalc, 0,"Edit", “” ); //獲取密碼輸入框的控制元件控制代碼 SetForegroundWindow ( hwndCalc ); //將QQ視窗設定為啟用
System.Threading.Thread.Sleep ( 1000 ); //暫停1秒讓你看到效果
SendMessage ( hwndQ, WM_SETTEXT, TextBox1.Text, 0 );//傳送文字框1裡面的內容(QQ號啦)
System.Threading.Thread.Sleep ( 1000 ); //暫停1秒讓你看到效果
SendMessage( hwndP, WM_SETTEXT, TextBox2.Text, 0 );//傳送文字框2裡面的內容(QQpassword)
System.Threading.Thread.Sleep ( 1000); //暫停1秒讓你看到效果
SendMessage ( hwndLogin, BM_CLICK, 0, 0 );//點選登入
}
else
{
MessageBox.Show ("沒有啟動 [QQ2011]");
}
}
---------------------------------------------------
C#查詢指定視窗的子視窗的控制代碼
2009年更新
通過實驗得知,FindWindowEx可以通過classname或caption(也就是視窗的title)查詢視窗,且如果第一個引數傳IntPtr.Zero的話,將從Windows最頂層視窗開始查詢,但是視窗很多的話這樣會非常的慢,所以加入Timeout的判斷,如果超時還沒找到,返回false。
用法:FindWindow fw = new FindWindow(IntPtr.Zero, null, "ThunderDFrame", 10);//查詢Title為ThunderDFrame的視窗,如果10秒內還沒找到,返回false
程式碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace Util { class FindWindow { [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] //IMPORTANT : LPARAM must be a pointer (InterPtr) in VS2005, otherwise an exception will be thrown private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); //the callback function for the EnumChildWindows private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); //if found return the handle , otherwise return IntPtr.Zero [DllImport("user32.dll", EntryPoint = "FindWindowEx")] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); private string m_classname; // class name to look for private string m_caption; // caption name to look for private DateTime start; private int m_timeout;//If exceed the time. Indicate no windows found. private IntPtr m_hWnd; // HWND if found public IntPtr FoundHandle { get { return m_hWnd; } } private bool m_IsTimeOut; public bool IsTimeOut { get{return m_IsTimeOut;} set { m_IsTimeOut = value; } } // ctor does the work--just instantiate and go public FindWindow(IntPtr hwndParent, string classname, string caption, int timeout) { m_hWnd = IntPtr.Zero; m_classname = classname; m_caption = caption; m_timeout = timeout; start = DateTime.Now; FindChildClassHwnd(hwndParent, IntPtr.Zero); } /**/ /// <summary> /// Find the child window, if found m_classname will be assigned /// </summary> /// <param name="hwndParent">parent's handle</param> /// <param name="lParam">the application value, nonuse</param> /// <returns>found or not found</returns> //The C++ code is that lParam is the instance of FindWindow class , if found assign the instance's m_hWnd private bool FindChildClassHwnd(IntPtr hwndParent, IntPtr lParam) { EnumWindowProc childProc = new EnumWindowProc(FindChildClassHwnd); IntPtr hwnd = FindWindowEx(hwndParent, IntPtr.Zero, m_classname, m_caption); if (hwnd != IntPtr.Zero) { this.m_hWnd = hwnd; // found: save it m_IsTimeOut = false; return false; // stop enumerating } DateTime end = DateTime.Now; if (start.AddSeconds(m_timeout) < end) { m_IsTimeOut = true; return false; } EnumChildWindows(hwndParent, childProc, IntPtr.Zero); // recurse redo FindChildClassHwnd return true;// keep looking }