2013-07-22 3 views
3

자바로 OSK (On-Screen Keyboard)를 작성했습니다. 이것은 장애가있는 사람들을위한 것이며 표준 키보드가 할 수있는 모든 것을 할 수 있어야합니다. 내가 작동하지 않는 것으로 알아챈 한 가지는 컨텍스트 메뉴 - (대부분의) Windows 프로그램입니다. 내 OSK 사용자가 '컨텍스트 메뉴'키 (일반적으로 표준 키보드의 오른쪽 Ctrl 옆)를 클릭하고 화살표 키를 사용하여 해당 메뉴를 탐색 할 수있게하려고합니다. 컨텍스트 메뉴가 잘 나타나지만 화살표 키를 누르기 위해 프레임을 다시 클릭하면 컨텍스트 메뉴가 사라집니다.Java 로봇 및 스윙 버튼을 사용하여 다른 (Windows) 응용 프로그램의 컨텍스트 메뉴를 제어하는 ​​방법

누구나 달성 할 수있는 방법에 대해 아이디어를 얻었습니까? (아마도 상당히 괴물 같은 '해킹'이 필요했을 것입니다)? 마우스 클릭이 화면의 다른 곳에서 발생하기 때문에 컨텍스트가 사라지는 것을 확신합니다. 실제로 뭔가를 클릭해야 할 때 주위를 둘러보기가 어렵습니다.

아래는 테스트 앱입니다. NetBeans의 컨텍스트 메뉴를 탐색하는 데 사용할 수는 있지만 시도한 다른 응용 프로그램 (예 : Windows 탐색기)에서는 탐색 할 수 없습니다.

마지막으로
import java.awt.Robot; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.WindowConstants; 

public class RobotContextMenuTest extends JFrame implements ActionListener 
{ 
    Robot R; 
    JPanel JP; 
    JButton JBmenu, JBdown; 

    public RobotContextMenuTest() 
    { 
     try 
     { 
      R = new Robot(); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 

     JP = new JPanel(); 
     getContentPane().add(JP); 

     JBmenu = new JButton("Menu"); 
     JBmenu.addActionListener(this); 
     JP.add(JBmenu); 

     JBdown = new JButton("Down"); 
     JBdown.addActionListener(this); 
     JP.add(JBdown); 

     setFocusableWindowState(false); 
     setAlwaysOnTop(true); 
     setSize(200,80); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     setVisible(true); 
    } 
    public static void main(String args[]) 
    { 
     new RobotContextMenuTest(); 
    } 

    public void actionPerformed(ActionEvent e) 
    { 
     if(e.getActionCommand().equals("Menu")) 
     { 
      R.keyPress(KeyEvent.VK_CONTEXT_MENU); 
      R.keyRelease(KeyEvent.VK_CONTEXT_MENU); 
     } 
     else if(e.getActionCommand().equals("Down")) 
     { 
      R.keyPress(KeyEvent.VK_DOWN); 
      R.keyRelease(KeyEvent.VK_DOWN); 
     } 
    } 
} 

, 여기에 내가 무엇을 시도했다입니다 : 대신의 ActionListener의 버튼의 MouseListener를 사용

  • , 다음 다른 응용 프로그램을 등록하지 않을 것이라는 희망으로 된 MouseEvent를 '소모' 컨텍스트 메뉴를 숨 깁니다.
  • 나는 모든 상황에 맞는 메뉴를 보여줄 수있는 스레드 테스트 응용 프로그램을 만들었고 자동으로 그것을 (1 초에 한 번) 검사 할 수는 있지만 실제로 문제를 해결하지는 못합니다! 컨텍스트 메뉴 탐색을 사용자의 마우스 클릭으로 제어하려고합니다.
  • 나는 마우스 클릭을 캡쳐하는 다른 방법으로 JNativeHook을 사용해 보았지만 결과는 같습니다.

오랜 질문에 대해 유감이지만 상당히 복잡한 문제입니다! 덧붙여 말하면, 표준 Windows 7 OSK는 이것을 할 수 없지만 WiViK 수 있습니다. 감사. 대신의 ActionListener의 버튼의 MouseListener를 사용

+0

낮은 레벨에서 마우스 버튼 이벤트를 억제/종료 할 수있는 방법이 있습니까? - MouseEvent.consume()과 비슷하지만 글로벌 수준입니까? JNativeHook에서 이와 같은 작업을 수행합니까? 아마도 마우스 클릭이 상황에 맞는 메뉴를 닫지 못하게 할 수 있습니다 (그러나 위의 예에서 내리기 버튼을 누르는 것). –

답변

3

마지막으로 친구의 도움으로 많은 금이갔습니다 (감사합니다 Chris Gregan!). 많은 실패한 시도 후에, 대답은 비교적 간단했다. JNA와 Windows API를 사용하여 저수준 마우스 이벤트를위한 후크를 만들었습니다. 그것은 모두 here in an answer by 'prunge' 주어진 2 개의 샘플 클래스로 설명했다. 참고 : jna 버전 3.4.0 및 jna 플랫폼 버전 3.4.0 용 jar를 포함해야했습니다 (이 jar의 최신 버전은 오류를 발생 시켰습니다!).

위의 링크 된 MouseHook을 사용하면 LowLevelMouseProc 콜백에서 -1을 반환하여 낮은 수준의 이벤트가 전파되는 것을 방지 할 수 있습니다 (다른 응용 프로그램에 도달). 여기

내가 가로 챌 MouseHook의 콜백 방법에 추가 니펫/마우스 왼쪽 버튼 누름이 억제이다 (이에 사라지는 컨텍스트 메뉴를 방지!)

if(nCode >= 0 && wParam.intValue() == WinUserX.WM_LBUTTONDOWN) 
    return new LRESULT(-1); 

다시 감사 알렉스 바커 해 주셔서 이것을보고 JNA 및 Windows API의 방향으로 나를 가리켜 라.

2
  • , 다른 응용 프로그램 이 등록하고 상황에 맞는 메뉴를 숨길 것이라는 희망에서 다음 '소모'MouseEvent입니다.

자바에서 이벤트를 소모하는 유일한 응용 프로그램에 영향을 미친다 때문에 현재 당신을 위해 작동하지 않습니다, 그것은 기본 시스템에서 이벤트 전파를 막을 수 없습니다. JNativeHook 1.2는 Windows에서이 작업을 수행 할 수있는 문서화되지 않은 메소드가있을 수 있습니다. 실제로 문제가 해결 될지 확신 할 수는 없습니다. 네이티브 시스템에서 클릭 이벤트를 사용하는 경우, jvm은 osk 버튼에서 click 이벤트를 수신하여 화살표 아래로 이벤트를 보내지 않을 것입니다. 네이티브 이벤트를 소비하기 전에 자바 버튼이 클릭되었는지 감지 할 방법이 없습니다. 즉, 소비 메소드를 호출하는 NativeInputEvent는 Java AWT InputEvent보다 먼저 전달됩니다. 자세한 내용은 https://code.google.com/p/jnativehook/issues/detail?id=22을 참조하십시오.

내가 생각할 수있는 유일한 좋은 해결책은 JNA를 사용하여 Windows API를 호출하고 컨텍스트 메뉴 핸들을 잡고 직접 트래버스하는 것입니다. 이런 종류의 일을 할 수있는 API가 있습니다. 단지 그들이 내 머리 꼭대기에서 벗어난 것을 기억하지 못합니다.어쩌면 http://msdn.microsoft.com/en-us/library/windows/desktop/ff468865(v=vs.85).aspx으로 시작하여 작은 테스트 프로그램을 만들어 메뉴를 조작 할 수 있는지 확인하십시오.

* 작은 업데이트 : 좀 더 인터넷 검색 후 나는 거의 ++ C와 함께이 작업을 수행하는 방법을 간략하게 설명 following post를 찾을 수 있었다. 이것을 JNA에 이식하는 것은 상당히 사소한 일입니다.

+0

안녕하세요. 알렉스, 정말 고마워요. 그 아이디어를 시험해보기 전에 아마 하루 이틀 정도 걸릴 것입니다. 어떻게 진행되는지, 그리고 질문이 있으면 알려 드리겠습니다 (JNA의 경험이 거의 없으며 Java 만 말할 수 있기 때문에 분명히 할 것입니다). –