Winapi-用于Eclipse SWT GUI窗口的本地WinProc的JNA实现出现问题

问题描述 投票:0回答:1

作为对我最近一个问题(Winapi - SetWindowLongPtr in ShutdownBlockReasonCreate / Destroy implementation of JNI native code的扩展),我想知道是否有机会使用JNA(最新版本5.5.0-https://github.com/java-native-access/jna)实现相同的功能。

由于我在文档(SetWindowSubclass())中找不到与http://java-native-access.github.io/jna/5.5.0/javadoc/相关的任何内容,因此我不得不使用SetWindowLongPtr()

在网上进行了一些研究之后,以下是我的一些代码片段,它们负责预期的功能:

    private static LONG_PTR baseWndProc;
    private static HWND hWnd;

    public static void initiateWindowsShutdownHook() {
        Display.getDefault().syncExec(()->{
            hWnd = new WinDef.HWND(Pointer.createConstant(Display.getDefault().getActiveShell().handle));
        });

        baseWndProc = IWindowsAPIUtil.WSBINSTANCE.SetWindowLongPtr(
                hWnd, IWindowsAPIUtil.GWL_WNDPROC, new IWindowsAPIUtil.WNDPROC() {

            @Override
            public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) {
                switch(uMsg) {
                case IWindowsAPIUtil.WM_QUERYENDSESSION:
                    Logger.logWarning("Shutdown initiated");
                    IWindowsAPIUtil.WSBINSTANCE.PostMessage(hWnd, User32.WM_CLOSE, wParam, lParam);
                    return new LRESULT(0);
                }
                return IWindowsAPIUtil.WSBINSTANCE.CallWindowProc(baseWndProc, hWnd, uMsg, wParam, lParam);
            }
        });
    }


    public interface IWindowsAPIUtil extends User32 {

        public static final IWindowsAPIUtil WSBINSTANCE = 
                (IWindowsAPIUtil) Native.loadLibrary("user32", IWindowsAPIUtil.class, W32APIOptions.UNICODE_OPTIONS);

        interface WNDPROC extends StdCallCallback{
            LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
        }

        public static final int GWL_WNDPROC = -4;
        public static final int WM_QUERYENDSESSION = 17;

        LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, WNDPROC wndProc);
        LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex);
        LRESULT CallWindowProc(LONG_PTR proc, HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
        void PostMessage(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
    }

我的新c ++本机代码现在看起来像这样:

注意:因为在本练习中,我仅将回调部分(在原始c ++本地代码中)重构为JNA,所以这里不需要SetWindowSubclass()

#include <windows.h>

#include <jni.h>

#include <iostream>
#include "com_app_project_winapi_WindowsAPI.h"


#include <commctrl.h>

using namespace std;

namespace {
    // Default reason text. The actual reason text should be defined by application logic not the native code
    LPCWSTR SHUTDOWN_REASON = L"Application is still saving ...";
}


JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonCreate(JNIEnv *env, jclass cls, jstring title, jstring reasonText) {
    cout << "In shutdownBlockReasonCreate method" << endl;

    const jchar *str = env->GetStringChars(title, NULL);
    HWND hWnd = FindWindowW(NULL, (LPCWSTR)str);
    env->ReleaseStringChars(title, str);
    if (hWnd == NULL) {
        return;
    }

    ShutdownBlockReasonCreate(hWnd, SHUTDOWN_REASON);

    return;
}

JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonDestroy(JNIEnv *env, jclass cls, jstring title) {
    cout << "In shutdownBlockReasonDestroy method" << endl;

    const jchar *str = env->GetStringChars(title, NULL);
    HWND hWnd = FindWindowW(NULL, (LPCWSTR)str);
    env->ReleaseStringChars(title, str);
    if (hWnd == NULL) {
        return;
    }

    ShutdownBlockReasonDestroy(hWnd);

    return;
}

从我的代码中,您可能会看到我将Eclipse SWT用于我的GUI应用程序。保存代码并运行应用程序后,出现以下问题:

  1. 虽然blockReasonCreate在第一次保存应用程序时被激活(此功能的目的是在保存时阻止关机),但在随后的保存中不再激活。原因文本显示为“此应用正在阻止关机”,而不是传入的原因文本。
  2. 作为从上面的扩展行为,我的GUI应用程序冻结,并且直到我从任务管理器中强制关闭该窗口之后,该窗口才能关闭

我尝试了以下操作:

  1. GetWindowLongPtr()中的CallWindowProc()替换“ baseWndProc” LONG_PTR。不幸的是没有用
  2. 我怀疑SetWindowLongPtr()的问题与上次相同。但是如前所述,JNA似乎没有提供匹配的SetWindowSubclass()方法,所以我没主意。

Btw,上一次的本机代码解决方案仍然可以正常工作。但是出于可维护性的目的,使用Java实现所有功能将是理想的。

非常感谢有人花时间在我的问题上!

欢呼声

c++ winapi save jna system-shutdown
1个回答
0
投票

您应始终准备最少的样本,以重现问题并可以由潜在的帮助者来运行。对代码进行推理,这很难从上下文中剥离。

© www.soinside.com 2019 - 2024. All rights reserved.