2011-12-06 46 views
10

我在學習如何使用Java和JNA(Java Native Access)與Windows API進行交互,但我在路障。我試圖通過在鼠標輸入流上排隊鼠標事件來使鼠標執行某些操作,並且代碼正常工作,因爲SendInput(...)方法返回1,表示它已成功排隊該事件,但鼠標本身不起作用。如何移動(或做任何事情)鼠標

SSCCE

編輯:編輯填寫的dwFlags領域。我已經嘗試了幾種常量的組合,不管是自己還是比特 - 或者還沒有成功地結合在一起。同樣,SendInput方法返回1,因爲它應該表明一個正常運作的方法,但鼠標不讓步:

import com.sun.jna.Native; 
import com.sun.jna.platform.win32.WinDef.*; 
import com.sun.jna.platform.win32.WinUser.*; 
import com.sun.jna.win32.StdCallLibrary; 

public class MouseUtils { 
    public interface User32 extends StdCallLibrary { 
     public static final long MOUSEEVENTF_MOVE = 0x0001L; 
     public static final long MOUSEEVENTF_VIRTUALDESK = 0x4000L; 
     public static final long MOUSEEVENTF_ABSOLUTE = 0x8000L; 

     User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class); 
     DWORD SendInput(DWORD dWord, INPUT[] input, int cbSize); 
    } 

    public static void main(String[] args) { 
     INPUT input = new INPUT(); 
     input.type = new DWORD(INPUT.INPUT_MOUSE); 

     input.input.mi.dx = new LONG(500); 
     input.input.mi.dy = new LONG(500); 
     input.input.mi.mouseData = new DWORD(0); 
     input.input.mi.dwFlags = new DWORD(User32.MOUSEEVENTF_MOVE 
      | User32.MOUSEEVENTF_VIRTUALDESK | User32.MOUSEEVENTF_ABSOLUTE); 
     // input.input.mi.dwFlags = new DWORD(0x8000L); 
     input.input.mi.time = new DWORD(0); 

     INPUT[] inArray = {input}; 

     int cbSize = input.size(); // mouse input struct size 
     DWORD nInputs = new DWORD(1); // number of inputs 
     DWORD result = User32.INSTANCE.SendInput(nInputs , inArray, cbSize); 
     System.out.println("result: " + result); // return 1 if the 1 event successfully inserted 
    } 
} 

編輯2:

多讀,它似乎是我的理解使用JNA的數組是有缺陷的,我必須從C數組的角度來思考,其中數組只是指向連續內存區域的指針。更多來(我希望!)。

+0

Offtopic:它始終是一個很高興見到你很友好,輕鬆與家人友好。你是我真正在這裏尋找的人之一。節日快樂;和2017年的一個偉大的一年! – GhostCat

+1

@GhostCat:你的第一個陳述有點有趣,但你的第二個太仁慈了。我仰望你,你的能力和你的知識傳播給他人的願望。 –

回答

9

JNA文件Using Structures And Unions寫着:

工會通常與結構可以互換,但需要你指示哪個工會場與setType方法主動,才能正確地傳遞給函數調用。

我想你錯過了setType部分。另外,當使用MOUSEEVENTF_ABSOLUTE時,dxdy被指定爲鼠標的座標,而不是像素。

以下工作:

public interface User32 extends StdCallLibrary { 
    ... 
    public static final int SM_CXSCREEN = 0x0; 
    public static final int SM_CYSCREEN = 0x1; 
    int GetSystemMetrics(int index); 
} 

public static void main(String[] args) {  
    ... 
    input.input.setType("mi"); 
    input.input.mi.dx = new LONG(500 * 65536/User32.INSTANCE.GetSystemMetrics(User32.SM_CXSCREEN)); 
    input.input.mi.dy = new LONG(500 * 65536/User32.INSTANCE.GetSystemMetrics(User32.SM_CYSCREEN)); 
    ... 
} 
+3

聖潔! 'setType(...)'是它!我錯誤地認爲設置輸入變量的類型字段就夠了,但是錯了。隨着你的更正我的代碼的作品。我不能夠感謝你! –

2
input.input.mi.dwFlags = new DWORD(0); 

您沒有指定任何鼠標輸入標誌,所以沒有鼠標輸入。

+0

謝謝!讓我看看! –

+0

請參閱編輯我的問題和更新的代碼。所有幫助非常感謝! –

+0

再次感謝您的偉大建議;他們是最有幫助的! –

3

在您的結構上調用toArray()方法以獲取連續的內存塊。

INPUT input = new INPUT(); 
INPUT[] arg = (INPUT[])input.toArray(1); 

或者,你可以簡單地聲明一個替代方法映射SendInput:(?權限,或許是看到MS便籤UIPI)

DWORD SendInput(int nInputs, INPUT pInputs, int cbSize); 

然而,也有可能是別的事情,因爲你的例子應該工作(至少用一個數組元素)。

編輯:Union.setType()答案確實是正確的。

+0

感謝您寶貴的建議!我非常感謝。我已經投了你的帖子,只希望我能在所有幫助過的人中分出獎金。 –