我目前正在使用SWT进行涉及Eclipse RCP的Java项目,并试图通过在保存时向Windows环境中的用户提供有意义的消息来处理正常关闭。我应该使用ShutdownBlockReasonCreate和ShutdownBLockReasonDestroy API来实现此目的,但是经过一番研究,我不得不用我刚接触的C ++本机代码来实现它们。由于它们在JNA中不可用,因此Eclipse SWT不提供这种功能(不希望知道)。
经过所有的努力,我能够整理一个有效的C ++代码(如下所示)以控制SWT窗口(通过引用另一种实现https://github.com/seraphy/JavaGracefulShutdownForWin7)。但是,我偶然发现了与WindowProc CALLBACK有关的问题。这些语法来自Java背景,花了我一段时间才能理解。但是我有点理解它正在尝试做的事情。因为这是我们需要处理WM_QUERYENDSESSION和WM_ENDSESSION消息的地方。
但是在开始之前,我想在这篇文章中讨论的问题与Windows API SetWindowLongPtr
特别相关,正如您在Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonCreate(JNIEnv *env, jclass cls, jstring title)
函数中看到的那样。如您所见,我将其注释掉了,仅仅是因为在ShutdownBlockReasonCreate(hWnd, SHUTDOWN_REASON)
之后调用此方法时,我的窗口的行为非常奇怪。例如,>是,我需要使用此方法来激活用于接收OS消息的窗口的控件,但是随后它开始与已经构建的Eclipse SWT窗口混淆。有谁知道我是否正确地完成了整个工作?还是我偏离了轨道? SetWindowLongPtr到底能做什么?我找不到任何好的参考资料,也无法从阅读Microsoft文档中受益匪浅。
提前感谢!
#include <jni.h> #include <iostream> #include "com_app_project_winapi_WindowsAPI.h" #include <windows.h> using namespace std; namespace { LPCWSTR SHUTDOWN_REASON = L"Application is still saving ..."; LRESULT CALLBACK AppWndProc( _In_ HWND hWnd, _In_ UINT message, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (message) { // Not doing anything yet } return DefWindowProc(hWnd, message, wParam, lParam); } } JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonCreate(JNIEnv *env, jclass cls, jstring title) { cout << "shutdownblockreason create" << endl; const char *str = NULL; str = (env)->GetStringUTFChars(title, 0); HWND hWnd = FindWindow(NULL, str); (env)->ReleaseStringUTFChars(title, str); if (hWnd == NULL) { return; } ShutdownBlockReasonCreate(hWnd, SHUTDOWN_REASON); //SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(AppWndProc)); return; } JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonDestroy(JNIEnv *env, jclass cls, jstring title) { cout << "shutdownblockreason destroy" << endl; const char *str = NULL; str = (env)->GetStringUTFChars(title, 0); HWND hWnd = FindWindow(NULL, str); (env)->ReleaseStringUTFChars(title, str); if (hWnd == NULL) { return; } ShutdownBlockReasonDestroy(hWnd); return; }
我目前正在使用SWT进行涉及Eclipse RCP的Java项目,并试图通过在保存时向Windows环境中的用户提供有意义的消息来处理正常关闭。我是...
首先,您正在调用ANSI version of FindWindow()
,它不接受UTF-8字符串。请改用FindWindow()
,它接受UTF-16字符串。 Java字符串本身是UTF-16。
第二,您的窗口在调用Unicode version之后无法正确运行,因为您的SetWindowLongPtr()
需要使用SetWindowLongPtr()
而不是AppWndProc()
来调用您替换的上一个窗口过程。另外,使用CallWindowProc()
完成操作后,您将不还原以前的窗口过程。