gpt4 book ai didi

c++ - Winapi - SetWindowLongPtr 在 ShutdownBlockReasonCreate/Destroy 实现 JNI native 代码

转载 作者:行者123 更新时间:2023-12-02 10:07:08 30 4
gpt4 key购买 nike

我目前正在处理一个涉及使用 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) 之后调用此方法时,我的窗口往往表现得非常奇怪。 .例如,

  • 单击"file"选项,不再显示菜单;
  • 调整窗口大小时,当您尝试调整窗口大小时,一半的窗口会变暗
    重新调整大小
  • 关闭窗口时,底层进程仍在运行

  • 是的,我需要使用此方法来激活窗口控制以接收操作系统消息,但随后它开始与已经构建的 Eclipse SWT 窗口混淆。有谁知道我是否正确实现了这整件事?还是我跑偏了? 是什么意思设置窗口长指针 究竟是做什么的?我找不到任何好的引用资料,也无法从阅读 Microsoft Doc 中得到太多。

    提前致谢!
    #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 ApproachSafer 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/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com