- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在处理一个涉及使用 SWT 的 Eclipse RCP 的 Java 项目,并试图通过在保存时向 Windows 环境中的用户提供有意义的消息来处理正常关闭。我应该使用 ShutdownBlockReasonCreate 和 ShutdownBLockReasonDestroy APIs 来实现这一点,但经过一些研究后,我不得不在 C++ native 代码中实现它们,我对这些代码很陌生。因为它们在 JNA 中不可用,并且 Eclipse SWT 不提供这种现成的功能(很想知道)
经过所有的努力,我能够将一个工作 C++ 代码(如下)组合在一起来控制 SWT 窗口(通过引用另一个实现 https://github.com/seraphy/JavaGracefulShutdownForWin7 )。但是我偶然发现了一个与 WindowProc CALLBACK 相关的问题。来自 Java 背景,这些语法花了我一段时间才理解。但我有点明白它想要做什么。因为这是我们需要处理 WM_QUERYENDSESSION 和 WM_ENDSESSION 消息的地方。
但在此之前,我想在这篇文章中讨论的问题具体与 windows API 相关。设置窗口长指针 正如您在 Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonCreate(JNIEnv *env, jclass cls, jstring title)
中看到的那样功能。如您所见,我将其注释掉,只是因为在 ShutdownBlockReasonCreate(hWnd, SHUTDOWN_REASON)
之后调用此方法时,我的窗口往往表现得非常奇怪。 .例如,
#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;
}
最佳答案
首先,您调用ANSI version of FindWindow()
,它不接受 UTF-8 字符串。使用 Unicode version相反,它接受 UTF-16 字符串。 Java 字符串本身使用 UTF-16 作为其公共(public)接口(interface),因此您无需浪费时间将它们不必要地转换为 UTF-8。
二、调用 SetWindowLongPtr()
后你的窗口不能正常运行因为你的AppWndProc()
需要使用 CallWindowProc()
而不是 DefWindowProc()
调用您替换的前一个窗口过程。此外,当您使用 AppWndProc()
完成后,您不会恢复之前的窗口过程。 .
第三,您应该使用 SetWindowSubclass()
而不是 SetWindowLongPtr()
.见 Disadvantages of the Old Subclassing Approach和 Safer subclassing .
话虽如此,请尝试更像这样的东西:
#include <jni.h>
#include <iostream>
#include "com_app_project_winapi_WindowsAPI.h"
#include <windows.h>
#include <commctrl.h>
namespace {
LPCWSTR SHUTDOWN_REASON = L"Application is still saving ...";
/*
WNDPROC PrevWndProc = NULL;
LRESULT CALLBACK AppWndProc(
_In_ HWND hWnd,
_In_ UINT message,
_In_ WPARAM wParam,
_In_ LPARAM lParam
) {
*/
LRESULT CALLBACK AppWndProc(
_In_ HWND hWnd,
_In_ UINT message,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ DWORD_PTR dwRefData
) {
switch (message) {
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, AppWndProc, uIdSubclass);
break;
//...
}
//return CallWindowProc(PrevWndProc, hWnd, message, wParam, lParam);
return DefSubclassProc(hWnd, message, wParam, lParam);
}
}
JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonCreate(JNIEnv *env, jclass cls, jstring title) {
std::cout << "shutdownblockreason create" << std::endl;
const jchar *str = env->GetStringChars(title, NULL);
HWND hWnd = FindWindowW(NULL, (LPCWSTR) str);
env->ReleaseStringChars(title, str);
if (!hWnd) {
return;
}
ShutdownBlockReasonCreate(hWnd, SHUTDOWN_REASON);
//PrevWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(AppWndProc));
SetWindowSubclass(hWnd, &AppWndProc, 1, 0);
}
JNIEXPORT void JNICALL Java_com_app_project_winapi_WindowsAPI_shutdownBlockReasonDestroy(JNIEnv *env, jclass cls, jstring title) {
std::cout << "shutdownblockreason destroy" << std::endl;
const jchar *str = env->GetStringChars(title, NULL);
HWND hWnd = FindWindowW(NULL, (LPCWSTR) str);
env->ReleaseStringChars(title, str);
if (!hWnd) {
return;
}
//SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(PrevWndProc));
RemoveWindowSubclass(hWnd, &AppWndProc, 1);
ShutdownBlockReasonDestroy(hWnd);
}
关于c++ - Winapi - SetWindowLongPtr 在 ShutdownBlockReasonCreate/Destroy 实现 JNI native 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59658987/
我尝试子类化另一个窗口(在另一个进程中),因此我注入(inject)了一个 dll,它调用 SetWindowLongPtr,但它失败并且 GetLastError 返回 5。 BOOL APIENT
我想在我的程序中继承 RichEdit(这里是 C++ 代码:http://dumpz.org/46182/)。 _native_log 是richedit 的一个hwnd。起初一切正常,LogWin
我一直在努力学习如何使用 SetWindowLongPtr() 并将其理解如下: 您可以使用以下函数获取当前消息并将其发送到自定义协议(protocol):LONG_PTR Some_Ptr = Se
我还在为钩子(Hook)而苦苦挣扎。 我的目标是: 在notepad.exe中设置一个钩子(Hook) 对其进行子类化(我的最终目标是将 Edit 类子类化并在我自己的窗口中显示内容) 免责声明:我知
前阵子,我用 Win32 API 编写了一个 C++ 程序,它会显示一个对话框,然后收听它生成的消息。有一次,我对将一段数据与对话窗口相关联很感兴趣。如果我手动创建窗口并附加一个窗口过程,我只需使用
关于 MSDN网站,我发现以下内容: Calling SetWindowLongPtr with the GWLP_WNDPROC index creates a subclass of the wi
我知道可以使用 SetWindowLongPtr + GWLP_USERDATA 来存储指向某些数据的指针。但是是否可以直接存储数据,例如“句柄”、“ bool 值”、“整数”或其他更大的数据。 来自
我需要为桌面上的一些应用程序窗口创建一个水印窗口(markHwnd),水印窗口样式为: uint dwStyle = Win32API.WS_CLIPSIBLINGS |
我正在编写一个自定义 Win32 UI 控件,我想在其中加入视觉主题。我将主题加载到它的 WM_NCCREATE 中: case WM_NCCREATE: { HTHEME hTheme =
我想 P/Invoke 到 GetWindowLongPtr和 SetWindowLongPtr ,而且我看到了关于它们的相互矛盾的信息。 一些消息称,在 32 位平台上,GetWindowLongP
我目前正在处理一个涉及使用 SWT 的 Eclipse RCP 的 Java 项目,并试图通过在保存时向 Windows 环境中的用户提供有意义的消息来处理正常关闭。我应该使用 ShutdownBlo
我是一名优秀的程序员,十分优秀!