我有一个 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/