java - Win32 文件属性对话框未通过 JNI 在 Java Swing 应用程序中显示

标签 java winapi java-native-interface

我有一个 Java Swing 应用程序,其中有一些通过 JNI 添加的 native 功能。该应用程序所做的一件事是显示文件系统的 TreeView 。我试图编写一些 JNI,以便在 Windows 系统上,我可以提供一个“属性...”上下文菜单项,显示 Windows 中的标准文件“属性”对话框。

我在互联网上搜索了执行此操作所需的 Win32 代码,并提出了这个:

JNIEXPORT jboolean JNICALL Java_com_foobar_showFilePropertiesDialogImpl
  (JNIEnv *env, jobject obj, jlong hwnd, jstring fileName)
{
    LPITEMIDLIST pidl;
    LPCITEMIDLIST pidlItem;
    HRESULT hr;
    IShellFolder *pFolder;
    IContextMenu *pContextMenu;
    CMINVOKECOMMANDINFO cmi;
    const wchar_t *pszFile;

    if (!coInitialized)
    {
#ifdef DEBUG
        MessageBoxW(NULL, L"Initializing COM (should happen just once)...", L"Initializing COM...", MB_OK);
#endif
        CoInitialize(NULL);
        coInitialized = true;
    }

    /* Get the name of the file. */
    pszFile = (wchar_t *)env->GetStringChars(fileName, NULL);
    if (pszFile==NULL) { /* Exception occurred */
        return JNI_FALSE;
    }

    hr = SHGetDesktopFolder(&pFolder);
    if (FAILED(hr))
    {
        env->ReleaseStringChars(fileName, (const jchar *)pszFile);
        return JNI_FALSE;
    }

    hr = pFolder->ParseDisplayName(HWND_DESKTOP, NULL, (LPTSTR)pszFile, NULL, &pidl, NULL);
    pFolder->Release();
    if (FAILED(hr))
    {
        env->ReleaseStringChars(fileName, (const jchar *)pszFile);
        return JNI_FALSE;
    }

    hr = SHBindToParent(pidl, IID_IShellFolder, (void **)&pFolder, &pidlItem);
    if (FAILED(hr))
    {
        SHFree(pidl);
        env->ReleaseStringChars(fileName, (const jchar *)pszFile);
        return JNI_FALSE;
    }

    hr = pFolder->GetUIObjectOf(HWND_DESKTOP, 1, (LPCITEMIDLIST *)&pidlItem, IID_IContextMenu, NULL, (void **)&pContextMenu);
    pFolder->Release();
    if(SUCCEEDED(hr))
    {
        ZeroMemory(&cmi, sizeof(cmi));
        cmi.cbSize = sizeof(cmi);
        if (hwnd>0)
        {
            cmi.hwnd = (HWND)hwnd;
        }
        cmi.lpVerb = "properties";
        cmi.nShow = SW_SHOWNORMAL;
        hr = pContextMenu->InvokeCommand(&cmi);
#ifdef DEBUG
        if (FAILED(hr))
        {
            wchar_t msg[2048];
            wsprintf(msg, L"InvokeCommand failed: %d - %x", SUCCEEDED(hr), hr);
            MessageBoxW(NULL, pszFile, msg, MB_OK);
        }
        else
        {
            MessageBoxW(NULL, L"InvokeCommand successful!", L"InvokeCommand Status", MB_OK);
        }
#endif
    }

    pContextMenu->Release();
    SHFree(pidl);
    env->ReleaseStringChars(fileName, (const jchar *)pszFile);

    return JNI_TRUE;
}

在 Java 中,我从 EDT 运行此方法。不幸的是,如果未定义 DEBUG,则属性对话框不会显示。看来如果我定义DEBUG,属性对话框会在“InvokeCommand success!”之后弹出。消息框。

我注意到的另一件事是,当未定义 DEBUG 时,我调用此方法(并且不显示属性对话框),如果我打开不同的“,它稍后显示在应用程序中” native ”窗口。例如,我有通过 SHFileOperation 打开 native 删除对话框的代码(有效);一旦我显示该对话框,任何最初未显示的文件属性对话框都会突然出现。

似乎我可能在错误的线程上做事。 EDT 不是我想要显示 native 窗口的线程吗?但我很困惑,因为删除对话框再次工作正常。

最佳答案

不要手动挖掘 Shell 接口(interface),而是尝试使用 ShellExecute()相反,让操作系统为您完成繁重的工作:

JNIEXPORT jboolean JNICALL Java_com_foobar_showFilePropertiesDialogImpl 
  (JNIEnv *env, jobject obj, jlong hwnd, jstring fileName) 
{ 
    /* Get the name of the file. */ 
    const wchar_t *pszFile = (wchar_t *)env->GetStringChars(fileName, NULL); 
    if (pszFile==NULL) { /* Exception occurred */ 
        return JNI_FALSE; 
    } 

    int iErr = (int) ShellExecuteW((HWND)hwnd, L"properties", pszFile, NULL, NULL, SW_SHOWNORMAL);
    env->ReleaseStringChars(fileName, (const jchar *)pszFile); 

    /*
    wchar_t msg[36];
    if (iErr > 32)
        wsprintfW(msg, L"ShellExecute successful!"); 
    else 
        wsprintfW(msg, L"ShellExecute failed: %d", iErr); 
    MessageBoxW((HWND)hwnd, pszFile, msg, MB_OK); 
    */

    return JNI_TRUE; 
} 

关于java - Win32 文件属性对话框未通过 JNI 在 Java Swing 应用程序中显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12531700/

相关文章:

java - Thread Interruptded Exception,释放信号量资源

c - 用于创建我自己的 certmgr.exe 的 API

android - 在带有 Eclipse 的 android 上使用 gdb 调试 native 代码 (C++)。是否可以?

c++ - 自动消失的自定义消息框

java-native-interface - 哪个 native 函数导致 JNI 代码中的 EXCEPTION_ACCESS_VIOLATION?

android - 从 native C/C++ 代码调用 JAVA 类成员

java - 通过 bean 名称编写可选的 bean 依赖注入(inject)

java - 从全局变量中读取和写入

java - JPA:两端都有列表,没有无限循环

c# - 调用的 Win32 错误代码的大写文本标识符是什么?给定错误代码,如何以编程方式确定它们?