JNIを介していくつかのネイティブ機能が追加されたJavaSwingアプリケーションがあります。このアプリケーションが行うことの1つは、ファイルシステムのツリービューを表示することです。Windowsシステムで、Windowsの標準ファイルの[プロパティ]ダイアログを表示する[プロパティ...]コンテキストメニュー項目を提供できるように、小さなJNIを作成しようとしていました。
私はこれを行うために必要な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を定義すると、「InvokeCommandsuccessful!」の後にプロパティダイアログがポップアップするようです。メッセージボックス。
もう1つ気付いたのは、DEBUGが定義されていない場合、このメソッドを呼び出すと(プロパティダイアログは表示されません)、別の「ネイティブ」ウィンドウを開くと、後でアプリケーションに表示されます。たとえば、SHFileOperationを介してネイティブの削除ダイアログを開くコードがあります(これは機能します)。そのダイアログを表示するとすぐに、元々表示されていなかったファイルプロパティダイアログが突然表示されます。
おそらく間違ったスレッドで何かをしているようです。EDTは、ネイティブウィンドウを表示したいスレッドではありませんか?しかし、ここでも削除ダイアログが正常に機能しているため、混乱しています。