1. 程式人生 > >得到Java程式的WIN32視窗控制代碼(轉)

得到Java程式的WIN32視窗控制代碼(轉)

我們知道C++的每個窗體都對應著一個控制代碼HWND,通過這個控制代碼我們可以對這個視窗以及它的資源進行各種操作,比如讓它前端顯示等。那麼作業系統給Java編寫的窗體(Frame或者JFrame的物件或者子類物件)有沒有分配這個唯一的HWND呢?如果存在的話我們怎麼來在Java程式中得到它並利用它來操作這個視窗呢? 
       用spy++檢視一下,Frame或者JFrame的物件或者子類物件確實都是存在這個視窗控制代碼的,那麼我們怎麼來提到它呢?有人可能會問了,得到這個HWND有什麼用呢,它可以幫我們實現什麼JDK還沒有給我們提供的功能呢?JDK1.5為我們提供了窗體最前的方法, JDK1.4為我們提供了視窗最小化到系統托盤的相關API……
       相信大家都用過QQ吧,在你把聊天視窗最小化,當收到訊息時工作列的標題按鈕就會閃一下以提示使用者收到了新的訊息,如果現在讓你用Java來實現這個小小的功能,你要如何做呢?我相信你不用JNI還是辦不到的吧,不光這點,要實現Java的不規則窗體,如果用到JNI的話,那將事半功倍。要在C++中操作Java生成的窗體,就必須先要得到Java應用程式的視窗控制代碼。
       下面我就以用Java實現那個閃爍標題的功能來說一下怎麼在C++中操作Java生成的視窗。這部分用到了JNI,建議你在繼續前先熟悉一下JNI的相關內容。

1: 安裝JDK和VC件並把JDK所帶的標頭檔案(jni.h jni_md.h jawt.h jawt_md.h)全部放入VC的Include目錄裡
2:在一個Java類(JNIWindowUtilProxy.java)中定義兩個方法分別如下

// 閃爍工作列的標題按鈕
public static native void flashTaskTitle(int HWND);

// 得到這個Java窗體的視窗控制代碼HWND
public static native int getWindowHWND(String jawtpath, 
Frame target);

3:編譯上面的java檔案並使用javah JNIWindowUtilProx命令生成其對應的.h標頭檔案

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNIWindowUtilProxy */

#ifndef _Included _JNIWindowUtilProxy
#define _Included _JNIWindowUtilProxy
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     JNIWindowUtilProxy
* Method: flashTaskTitle
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_JNIWindowUtilProxy_flashTaskTitle
   (JNIEnv *, jclass, jint);

/*
* Class:     JNIWindowUtilProxy
* Method: getWindowHWND
* Signature: (Ljava/lang/String;Ljava/awt/Frame;)I
*/
JNIEXPORT jint JNICALL Java_JNIWindowUtilProxy_getWindowHWND
   (JNIEnv *, jclass, jstring, jobject);

#ifdef __cplusplus
}
#endif#endif

4:在VC中新建一個動態連結庫工程並把上一步生成的標頭檔案放到工程裡
5:編寫一個C++原始檔來具體實現標頭檔案中的兩個方法

至於Java_JNIWindowUtilProxy_flashTaskTitle這個方法,只要有一個視窗的HWND做引數,呼叫C++為我們提供的現成的方法FlashWindow就行了, 而這個HWND則可以通過Java_JNIWindowUtilProxy_getWindowHWND這個方法的返回值來取得。所以Java_JNIWindowUtilProxy_flashTaskTitle的具體實現如下

/*
* Class: JNIWindowUtilProxy
* Method: flashTaskTitle
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_caokai_jni_JNIWindowUtilProxy_flashTaskTitle
(JNIEnv *, jclass, jint hwnd)
{
       HWND h = (HWND) hwnd;
       FlashWindow(h, true);
}

下面關鍵就是得到Java窗體的視窗控制代碼HWND,也就是方法JNICALL Java_JNIWindowUtilProxy_getWindowHWND的具體實現了。要實現這個功能所需要的程式碼量比較大,但是如果分為以下幾步就變得很簡單了。
1:分別定義下面四個結構體(與圖形繪製相關)的一個物件以備後面之用

JAWT awt;
JAWT_DrawingSurface *ds;
JAWT_DrawingSurfaceInfo *dsi;
JAWT_Win32DrawingSurfaceInfo *win;
2:載入jawt.dll這個動態連結庫(採用執行時載入的方式)

載入動態連結庫時而要提供它的路徑,也就是Java檔案中的jawtpath那個引數,而在C++中對應的是jstring,由於jawt.dll是位於JRE目錄的bin目錄裡,所以我們的jawtpath應該用下面的方法來賦值

jawtpath = System.getProperty("java.home")
+ System.getProperty("file.separator") 
+ "bin"
+ System.getProperty("file.separator") 
+ "jawt.dll";

而載入動態連結庫的具體程式碼如下
// Load the jawt dynamic library.
const char *path = env -> GetStringUTFChars(jawtpath, JNI_FALSE);
HMODULE HJAWT = LoadLibrary(path);
env -> ReleaseStringUTFChars(jawtpath, path);
if(HJAWT == NULL)
{
return -1;
}

3:得到動態連結庫中JAWT_GetAWT這個函式以初始化JAWT

// Get the function address from jawt.dll
GETAWT JAWT_GetAWT = 
(GETAWT) GetProcAddress(HJAWT, "[email protected]");
if (JAWT_GetAWT == NULL) 
{
return -1;
}

4:利用上一步提到的函式來初始化JAWT

// Get the JAWT
awt.version = JAWT_VERSION_1_3;
result = JAWT_GetAWT(env, &awt);
if (result == JNI_FALSE) 
{
return -1;
}

5:得到與圖形繪製相關的物件

ds = awt.GetDrawingSurface(env, window);
ds -> Lock(ds);
dsi = ds -> GetDrawingSurfaceInfo(ds);

6:得到JAWT_Win32DrawingSurfaceInfo 員hwnd的值

HWND hwnd = win -> hwnd;

7:釋放所用的資源

ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
FreeLibrary(HJAWT);

8:返回剛才得到的HWND物件

return (int)hwnd;

通過上面的幾步就可以得到Java視窗的控制代碼了,得到了之後就可以通過它來操作這個視窗了,比如來實現我上面提到的閃爍標題的功能等等。下面是我的程式執行時的螢幕截圖
1:閃爍標題欄按鈕
      
2:得到視窗控制代碼的值
   
2:使視窗成為橢圓形狀
   
注:1:這裡的40788是十六進位制的整數,與spy++所查出的結果是一致的。
2:如果你的VC工程編譯失敗,請在前面加上下面一行程式碼

typedef jboolean (JNICALL *GETAWT)(JNIEnv*, JAWT*);


1:HWND與jint之間的轉換會損失精度,所以應該把它與jlong進行轉換
2:由於Visual Studio 2005的工程預設是支援國際化的,也就是說,它採用的是和Java一樣的Unicode字符集,因此LoadLibrary函式的引數如果是const char *則編譯不能通過,更正的程式碼如下:

path = env->GetStringUTFChars(jstr, &isCopy);
CString re = path;
HMODULE HJAWT = LoadLibrary(re);

要用到CString類的話,要引入atlstr.h這個標頭檔案。

相關推薦

得到Java程式WIN32視窗控制

我們知道C++的每個窗體都對應著一個控制代碼HWND,通過這個控制代碼我們可以對這個視窗以及它的資源進行各種操作,比如讓它前端顯示等。那麼作業系統給Java編寫的窗體(Frame或者JFrame的物件或者子類物件)有沒有分配這個唯一的HWND呢?如果存在的話我們怎麼來在J

C# 根據程序獲取程式視窗控制包括最小化和隱藏程式

namespace Applications.UI {     class CurrentProcess     {             private static Hashtable processWnd = null;             public del

獲取控制檯視窗控制hWnd

作者:Defanive 部落格:Console.Dec.Cn(Hi.Baidu.Com/Console_App) ——————— 【 謝謝合作 】 ——————— 測試環境:VC++ 6.0 視窗,都有其唯一的控制代碼(hWnd)。得到了視窗控制代碼,能夠做很多事情。控制

.NET物件與Windows控制控制分類和.NET控制洩露的例子

上一篇文章介紹了控制代碼的基本概念,也描述了C#中建立檔案控制代碼的過程。我們已經知道控制代碼代表Windows內部物件,檔案物件就是其中一種,但顯然系統中還有更多其它型別的物件。本文將簡單介紹Windows物件的分類。 控制代碼可以代表的Windows物件分為三類,核心物件(Kernel Object)、

案例——檔案控制pipe增多tomcat模組定位方法

問題描述:tomcat檔案控制代碼數持續增長 定位方法: 定位檔案控制代碼洩漏前需要收集的必要資訊: tomcat初始啟動時的檔案控制代碼數、對tomcat的詳細lsof結果、以及tomcat的記憶體dump; 按時間段對tomcat的檔案控制代碼數進行統計(每小時、

究竟什麼是控制handle

當初學windows程式設計的時候搞不清什麼是控制代碼,有人說其實就是個值,有人說它是個特殊的指標。什麼值?特殊在哪?沒人對我說明白。 今天剛看了《windows程式設計》第三章,由於知識所限,我不敢說看完了就能全面認識什麼是控制代碼,但是,至少明白了它的概念,它在widn

Matlab中的圖形控制轉載

在matlab中,每一個物件都有一個數字來標識,叫做控制代碼.當每次建立一個物件時,matlab就為它建立一個唯一的控制代碼 控制代碼中包含有該物件的相關資訊引數,可以在後續程式中進行操作,改變其中的引數,以便達到不同的效果 例如:gcf 是返回當前被啟用的視窗的控制

IOS推送之PHP

推送消息 獲取 option code bsp 包含 connect 手機 pan 準備工作 1.獲取手機註冊應用的deviceToken(iphone手機註冊應用時返回唯一值deviceToken) 2.獲取ck.pem文件(做手機端的給) 3.獲取pass phrase

java程式中如何能獲取到另一個程式的windows控制,又如何使用這個控制向這個視窗傳送訊息

import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.platform.win32.W

mfc獲取其它程式視窗控制

const char *getWindowTitle(HWND hWnd){ char WindowTitle[1000]={0}; ::GetWindowText(hWnd,WindowTitle,1000); std::string *ti

如何通過視窗控制來獲得一個程式視窗的大小

首先通過FindWindow函式取得視窗控制代碼,當然也可以用GetForegroundWindow()函式取得自己的程式的控制代碼。RECT rctA; //定義一個RECT結構體,儲存視窗的長寬高HWND lhwnd=::FindWindow(NULL,L"微信");  

WPF 視窗控制獲取和設定

WPF 視窗控制代碼設定和獲取 1、控制代碼類 WHwnd.cs public class WHwnd { /// <summary> /// 主窗體控制代碼 /// </summar

MFC 獲取當前視窗控制,或者父子視窗控制

父子視窗 在子視窗中,需要用到父視窗的控制代碼: AfxGetMainWnd()->m_hWnd 注:在父視窗中,也可以這麼用來呼叫自己視窗的控制代碼 在子視窗中,需要用到自己視窗的控制代碼 ChildDlg *pChildDlg ; pChildDlg->m_h

按鍵精靈 -獲取視窗控制

MessageBox "視窗右下角座標:" get_window_pos //得到當前最前面的視窗控制代碼-就是把需要的視窗啟用在最前面 Hwnd = Plugin.Window.Foreground() //得到滑鼠指向的視窗控制代碼Hwnd = Plugin.Window.Mo

web自動化-視窗控制及位置變化

在進行web自動化時,很容易會遇到多視窗進行切換測試,下面就對多視窗的一些控制代碼和切換及視窗控制代碼順序簡單總結一下 1 from selenium import webdriver 2 driver = webdriver.Firefox() 3 driver.get("https://www.b

python爬蟲丨Selenium切換視窗控制及呼叫Chrome瀏覽器

  一. 呼叫Chrome瀏覽器 首先,假設通過Firefox()瀏覽器定向爬取CSDN首頁導航欄資訊,審查元素程式碼如下圖所示,在div class="menu"路徑的ul、li、a下,同時可以定位ul class="clearfix"。  

獲取ArcMap視窗控制,通過WinAPI獲取工作空間中點選要素的系統桌面座標

這裡用了個“桌面座標”,是希望區分一下ArcGis的“螢幕座標”(與之對應的還有一個“地理座標”)。 什麼是“螢幕座標”呢?使用ITool介面的OnMouseDown方法獲取的“x,y”值即是,其原點值在“工作空間”窗體左上角。 什麼是我所稱謂的“工作空間”呢?它是資料編輯區域,用Spy++檢視一下其窗體

C#獲取當前活動視窗控制

c# 獲取當前活動視窗控制代碼,獲取視窗大小及位置 2018年04月26日 13:48:21 漂泊_人生 閱讀數:1889   需呼

GetWindow、GetTopWindow和GetNextWindow視窗控制獲取!!!

GetWindow //uCmd 可選值:   GW_HWNDFIRST = 0; {同級別第一個}   GW_HWNDLAST  = 1; {同級別最後一個}   GW_HWNDNEXT  = 2; {同級別下一個}   GW_HWNDPREV  = 3;

VC 各種情況下的視窗控制的獲取

AfxGetMainWnd AfxGetMainWnd獲取自身視窗控制代碼 HWND hWnd = AfxGetMainWnd()->m_hWnd; GetTopWindow 函式功能:該函式檢查與特定父視窗相聯的子視窗z序(Z序:垂直螢幕的方向,即疊放