2009-07-21 20 views
6

Tôi đang cố gắng sử dụng Java Access Bridge để nhận thông tin về các thành phần Swing từ bên trong ứng dụng C++. Tuy nhiên, không ai trong số các callbacks tôi đăng ký bao giờ được gọi. Tôi đã thử enuming các cửa sổ một sau đó gọi IsJavaWindow() trên mỗi xử lý, nhưng nó luôn luôn trả về false. Bất kỳ ý tưởng về lý do tại sao nó dường như không hoạt động?Không nhận được cuộc gọi lại từ cầu truy cập Java

Tôi cho rằng đó là sự cố với ứng dụng của tôi thay vì cài đặt cầu vì chương trình demo và chương trình Ferret hoạt động, initializeAccessBridge() trả về true và trình gỡ lỗi cho biết rằng tệp WindowsAccessBridge được tải.

Tôi đang sử dụng Java 6, bản cập nhật 13 trên Windows Vista và tôi nghĩ phiên bản 2.0.1 của cầu truy cập.

JavaAccess::JavaAccess(void) 
{ 
    using namespace std; 

    BOOL isInitialized = initializeAccessBridge(); 
    if(isInitialized) 
    { 
     cout << "Bridge Initialized!" << endl; 
    } 
    else 
    { 
     cout << "Initialization failed!" << endl; 
     return; 
    } 

    EnumWindows((WNDENUMPROC)EnumWndProc, NULL); 

    SetJavaShutdown(OnJavaShutdown); 
    SetFocusGained(OnFocusGained); 
    SetMouseClicked(OnMouseClicked); 
} 

JavaAccess::~JavaAccess(void) 
{ 
    shutdownAccessBridge(); 
} 

void JavaAccess::OnJavaShutdown(long vmID) 
{ 
    using namespace std; 
    cout << "Java shutdown!" << endl; 
} 

void JavaAccess::OnFocusGained(long vmID, FocusEvent event, AccessibleContext context) 
{ 
    using namespace std; 
    cout << "Focus Gained!" << endl; 

    ReleaseJavaObject(vmID, event); 
    ReleaseJavaObject(vmID, context); 
} 

void JavaAccess::OnMouseClicked(long vmID, jobject event, jobject source) 
{ 
    std::cout << "Mouse clicked!" << std::endl; 

    ReleaseJavaObject(vmID, event); 
    ReleaseJavaObject(vmID, source); 
} 

BOOL CALLBACK JavaAccess::EnumWndProc(HWND hwnd, LPARAM lparam) 
{ 
    if (IsJavaWindow(hwnd)) 
    { 
     std::cout << "Found Java Window!" << std::endl; 
     return FALSE; 
    } 
    else 
    { 
     std::cout << "Still looking" << std::endl; 
     return TRUE; 
    } 
} 

Tất cả các cuộc gọi lại là các hàm tĩnh.

Trả lời

10

Tôi cũng đã chiến đấu với vấn đề này và vừa tìm ra giải pháp thực sự hợp lý. Tôi đã phải xây dựng một phiên bản gỡ lỗi của WindowsAccessBridge.dll và sử dụng trình gỡ rối để bước vào nó để xem những gì đang xảy ra.

  • Cuộc gọi tới 'initializeAccessBridge' YÊU CẦU bạn có một máy bơm thông báo cửa sổ đang hoạt động.

Bên trong 'initializeAccessBridge', nó (cuối cùng) tạo cửa sổ hộp thoại ẩn (sử dụng CreateDialog). Khi hộp thoại được tạo, hộp thoại sẽ thực hiện PostMessage với thông báo đã đăng ký. Phía JavaVM của cây truy cập phản hồi thông điệp này và gửi lại một thông điệp khác đến hộp thoại đã được tạo (nó có vẻ là một kiểu bắt tay 'hello' giữa ứng dụng của bạn và máy ảo Java). Như vậy, nếu ứng dụng của bạn không có một máy bơm thông báo hoạt động, thông báo trả về từ JavaVM sẽ không bao giờ nhận được bởi ứng dụng của bạn. Điều này quan trọng cho đến khi nhận được tin nhắn này, cây cầu không bao giờ được khởi tạo đúng cách và như vậy tất cả các cuộc gọi đến 'IsJavaWindow' không thành công (nội bộ, cầu khởi tạo cấu trúc bên trong khi nhận được thông báo - như vậy, không bơm thông điệp hoạt động, không khởi tạo). Tôi đoán rằng đây là lý do tại sao bạn không bao giờ nhận được tin nhắn gọi lại là tốt.

Không chỉ vậy, nhưng bạn phải gọi initializeAccessBridge tại thời điểm máy bơm tin nhắn có thể xử lý tin nhắn trước khi bạn có thể gọi IsJavaWindow.

Đây là lý do tại sao JavaFerret và JavaMonkey hoạt động - chúng khởi tạo khi khởi động, và sau đó liệt kê theo phản hồi cho thông báo menu, sau khi cây cầu đã nhận được thông báo khởi tạo qua máy bơm thông báo.

Cách tôi có thể giải quyết vấn đề này trong ứng dụng hộp thoại MFC của mình (và ứng dụng dựa trên MFC) của chúng tôi, đảm bảo rằng bạn gọi 'initializeAccessBridge' tại một điểm sao cho máy nhắn tin MFC tích hợp có thể đẩy thông điệp 'hello' trở lại hộp thoại ẩn này TRƯỚC KHI bạn sử dụng nó. Trong hộp thoại MFC đơn giản, nó có nghĩa là gọi initializeAccessBridge trong OnInitDialog, và gọi thủ tục enum để đáp ứng với một cuộc gọi nút (ví dụ). Nếu bạn muốn enum xảy ra ngay khi hộp thoại xuất hiện, bạn có thể sử dụng bộ hẹn giờ để kích hoạt (ví dụ 10ms) sau khi OnInitDialog hoàn thành để cho phép xử lý thông báo khởi tạo.

Nếu bạn dự định sử dụng ứng dụng này trong ứng dụng bảng điều khiển, bạn sẽ cần phải viết máy bơm tùy chỉnh của riêng mình để xử lý thông báo khởi tạo.

Dù sao, tôi hy vọng điều này là đủ rõ ràng! Trong khi không có cách nào để biết liệu đây có phải là cách 'chính xác' (không phải để trả tiền cho một kỹ sư Sun nói với chúng tôi), nó chắc chắn đã giải quyết được vấn đề của tôi.

Chúc mừng - Darren.

oh. và btw tôi đã tìm thấy một trang Sun mơ hồ đã đề cập đến một cái gì đó về AccessBridge chỉ làm việc cho các ứng dụng java dựa trên awt (nhưng cho rằng Sun đã không cập nhật bất kỳ tài liệu nào kể từ năm 2004 điều này có thể đã thay đổi). Tôi không phải là một lập trình viên java - để thử nghiệm, tôi đã lấy một số ứng dụng Java miễn phí (cũng như các ứng dụng Java đi kèm với jdk) và thử ứng dụng thử nghiệm của tôi. Nó làm việc cho tất cả những cái tôi đã thử - YMMV. Chúc may mắn!

+0

Tôi đã bắt đầu nghi ngờ rằng nó yêu cầu một máy bơm tin nhắn, và tôi thích lời giải thích của bạn tại sao. Tôi vừa sửa đổi thử nghiệm của tôi và nó hoạt động ngay bây giờ. Đây là một số điểm thưởng! – James

+0

Cảm ơn điểm trên vòng lặp tin nhắn. Re: giao diện điều khiển ứng dụng. Trong C# Bạn có thể sử dụng [Application.Run()] (https://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx) với no-args để tạo ra một chính đơn giản vòng lặp tin nhắn. Nếu bạn muốn thực hiện bất kỳ cuộc gọi đến dll thì làm như vậy từ một chủ đề khác. Đối với C++, [Tải xuống Java Access Bridge] (http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136191.html) chứa mã nguồn JavaMonkey.cpp có GetMessage chuẩn, TranslateMessage , DispatchMessage loop. – Daniel

0

Bạn có chắc là OnJavaShutdown() là tĩnh không? Tôi tin rằng tuyên bố phải là

static oid JavaAccess::OnJavaShutdown(long vmID) 
Các vấn đề liên quan