|
Java example source code file (awt_FileDialog.cpp)
The awt_FileDialog.cpp Java example source code/* * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "awt.h" #include "awt_FileDialog.h" #include "awt_Dialog.h" #include "awt_Toolkit.h" #include "ComCtl32Util.h" #include <commdlg.h> #include <cderr.h> #include <shlobj.h> /************************************************************************ * AwtFileDialog fields */ /* WFileDialogPeer ids */ jfieldID AwtFileDialog::parentID; jfieldID AwtFileDialog::fileFilterID; jmethodID AwtFileDialog::setHWndMID; jmethodID AwtFileDialog::handleSelectedMID; jmethodID AwtFileDialog::handleCancelMID; jmethodID AwtFileDialog::checkFilenameFilterMID; jmethodID AwtFileDialog::isMultipleModeMID; /* FileDialog ids */ jfieldID AwtFileDialog::modeID; jfieldID AwtFileDialog::dirID; jfieldID AwtFileDialog::fileID; jfieldID AwtFileDialog::filterID; /* Localized filter string */ #define MAX_FILTER_STRING 128 static TCHAR s_fileFilterString[MAX_FILTER_STRING]; /* Non-localized suffix of the filter string */ static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0"); // Default limit of the output buffer. #define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1 #define MULTIPLE_MODE_BUFFER_LIMIT 32768 // The name of the property holding the pointer to the OPENFILENAME structure. static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN"); /***********************************************************************/ void AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription) { int length = env->GetStringLength(filterDescription); DASSERT(length + 1 < MAX_FILTER_STRING); LPCTSTR tmp = JNU_GetStringPlatformChars(env, filterDescription, NULL); _tcscpy_s(s_fileFilterString, MAX_FILTER_STRING, tmp); JNU_ReleaseStringPlatformChars(env, filterDescription, tmp); //AdditionalString should be terminated by two NULL characters (Windows //requirement), so we have to organize the following cycle and use memcpy //unstead of, for example, strcat. LPTSTR s = s_fileFilterString; while (*s) { ++s; DASSERT(s < s_fileFilterString + MAX_FILTER_STRING); } DASSERT(s + sizeof(s_additionalString) < s_fileFilterString + MAX_FILTER_STRING); memcpy(s, s_additionalString, sizeof(s_additionalString)); } LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); switch (message) { case WM_COMMAND: { if (LOWORD(wParam) == IDCANCEL) { // Unlike Print/Page dialogs, we only handle IDCANCEL here and // don't handle IDOK. This is because user can press OK button // when no file is selected, and the dialog is not closed. So // OK button is handled in the CDN_FILEOK notification handler // (see FileDialogHookProc below) jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); } break; } } WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); } static UINT_PTR CALLBACK FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); TRY; HWND parent = ::GetParent(hdlg); switch(uiMsg) { case WM_INITDIALOG: { OPENFILENAME *ofn = (OPENFILENAME *)lParam; jobject peer = (jobject)(ofn->lCustData); env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)parent); ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer)); // fix for 4508670 - disable CS_SAVEBITS DWORD style = ::GetClassLong(hdlg,GCL_STYLE); ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS); // set appropriate icon for parentless dialogs jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID); if (awtParent == NULL) { ::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); } else { env->DeleteLocalRef(awtParent); } // subclass dialog's parent to receive additional messages WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent, FileDialogWndProc); ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); ::SetProp(parent, OpenFileNameProp, (void *)lParam); break; } case WM_DESTROY: { HIMC hIMC = ::ImmGetContext(hdlg); if (hIMC != NULL) { ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); ::ImmReleaseContext(hdlg, hIMC); } WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp)); ComCtl32Util::GetInstance().UnsubclassHWND(parent, FileDialogWndProc, lpfnWndProc); ::RemoveProp(parent, ModalDialogPeerProp); ::RemoveProp(parent, NativeDialogWndProcProp); ::RemoveProp(parent, OpenFileNameProp); break; } case WM_NOTIFY: { OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam; if (notifyEx) { jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp)); if (notifyEx->hdr.code == CDN_INCLUDEITEM) { LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl; // Get the filename and directory TCHAR szPath[MAX_PATH]; if (!::SHGetPathFromIDList(pidl, szPath)) { return TRUE; } jstring strPath = JNU_NewStringPlatform(env, szPath); // Call FilenameFilter.accept with path and filename UINT uRes = (env->CallBooleanMethod(peer, AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE); env->DeleteLocalRef(strPath); return uRes; } else if (notifyEx->hdr.code == CDN_FILEOK) { // This notification is sent when user selects some file and presses // OK button; it is not sent when no file is selected. So it's time // to unblock all the windows blocked by this dialog as it will // be closed soon env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); } else if (notifyEx->hdr.code == CDN_SELCHANGE) { // reallocate the buffer if the buffer is too small LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp); UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) + CommDlg_OpenSave_GetFolderPath(parent, NULL, 0); if (lpofn->nMaxFile < nLength) { // allocate new buffer LPTSTR newBuffer = new TCHAR[nLength]; if (newBuffer) { memset(newBuffer, 0, nLength * sizeof(TCHAR)); LPTSTR oldBuffer = lpofn->lpstrFile; lpofn->lpstrFile = newBuffer; lpofn->nMaxFile = nLength; // free the previously allocated buffer if (oldBuffer) { delete[] oldBuffer; } } } } } break; } } return FALSE; CATCH_BAD_ALLOC_RET(TRUE); } void AwtFileDialog::Show(void *p) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject peer; LPTSTR fileBuffer = NULL; LPTSTR currentDirectory = NULL; jint mode = 0; BOOL result = FALSE; DWORD dlgerr; jstring directory = NULL; jstring title = NULL; jstring file = NULL; jobject fileFilter = NULL; jobject target = NULL; jobject parent = NULL; AwtComponent* awtParent = NULL; jboolean multipleMode = JNI_FALSE; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); /* * There's a situation (see bug 4906972) when InvokeFunction (by which this method is called) * returnes earlier than this method returnes. Probably it's caused due to ReplyMessage system call. * So for the avoidance of this mistiming we need to make new global reference here * (not local as it's used by the hook) and then manage it independently of the calling thread. */ peer = env->NewGlobalRef((jobject)p); try { DASSERT(peer); target = env->GetObjectField(peer, AwtObject::targetID); parent = env->GetObjectField(peer, AwtFileDialog::parentID); if (parent != NULL) { awtParent = (AwtComponent *)JNI_GET_PDATA(parent); } // DASSERT(awtParent); title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID); HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; if (title == NULL || env->GetStringLength(title)==0) { title = JNU_NewStringPlatform(env, L" "); } JavaStringBuffer titleBuffer(env, title); directory = (jstring)env->GetObjectField(target, AwtFileDialog::dirID); JavaStringBuffer directoryBuffer(env, directory); multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID); UINT bufferLimit; if (multipleMode == JNI_TRUE) { bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT; } else { bufferLimit = SINGLE_MODE_BUFFER_LIMIT; } LPTSTR fileBuffer = new TCHAR[bufferLimit]; memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR)); file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID); if (file != NULL) { LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL); _tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string JNU_ReleaseStringPlatformChars(env, file, tmp); } else { fileBuffer[0] = _T('\0'); } ofn.lStructSize = sizeof(ofn); ofn.lpstrFilter = s_fileFilterString; ofn.nFilterIndex = 1; /* Fix for 6488834. To disable Win32 native parent modality we have to set hwndOwner field to either NULL or some hidden window. For parentless dialogs we use NULL to show them in the taskbar, and for all other dialogs AwtToolkit's HWND is used. */ if (awtParent != NULL) { ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd(); } else { ofn.hwndOwner = NULL; } ofn.lpstrFile = fileBuffer; ofn.nMaxFile = bufferLimit; ofn.lpstrTitle = titleBuffer; ofn.lpstrInitialDir = directoryBuffer; ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING; fileFilter = env->GetObjectField(peer, AwtFileDialog::fileFilterID); if (!JNU_IsNull(env,fileFilter)) { ofn.Flags |= OFN_ENABLEINCLUDENOTIFY; } ofn.lCustData = (LPARAM)peer; ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc; if (multipleMode == JNI_TRUE) { ofn.Flags |= OFN_ALLOWMULTISELECT; } // Save current directory, so we can reset if it changes. currentDirectory = new TCHAR[MAX_PATH+1]; VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0); mode = env->GetIntField(target, AwtFileDialog::modeID); AwtDialog::CheckInstallModalHook(); // show the Win32 file dialog if (mode == java_awt_FileDialog_LOAD) { result = AwtFileDialog::GetOpenFileName(&ofn); } else { result = AwtFileDialog::GetSaveFileName(&ofn); } // Fix for 4181310: FileDialog does not show up. // If the dialog is not shown because of invalid file name // replace the file name by empty string. if (!result) { dlgerr = ::CommDlgExtendedError(); if (dlgerr == FNERR_INVALIDFILENAME) { _tcscpy_s(fileBuffer, bufferLimit, TEXT("")); if (mode == java_awt_FileDialog_LOAD) { result = AwtFileDialog::GetOpenFileName(&ofn); } else { result = AwtFileDialog::GetSaveFileName(&ofn); } } } AwtDialog::CheckUninstallModalHook(); DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); AwtDialog::ModalActivateNextWindow(NULL, target, peer); VERIFY(::SetCurrentDirectory(currentDirectory)); // Report result to peer. if (result) { jint length = multipleMode ? (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile) : (jint)_tcslen(ofn.lpstrFile); jcharArray jnames = env->NewCharArray(length); env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile); env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames); env->DeleteLocalRef(jnames); } else { env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID); } DASSERT(!safe_ExceptionOccurred(env)); } catch (...) { env->DeleteLocalRef(target); env->DeleteLocalRef(parent); env->DeleteLocalRef(title); env->DeleteLocalRef(directory); env->DeleteLocalRef(file); env->DeleteLocalRef(fileFilter); env->DeleteGlobalRef(peer); delete[] currentDirectory; if (ofn.lpstrFile) delete[] ofn.lpstrFile; throw; } env->DeleteLocalRef(target); env->DeleteLocalRef(parent); env->DeleteLocalRef(title); env->DeleteLocalRef(directory); env->DeleteLocalRef(file); env->DeleteLocalRef(fileFilter); env->DeleteGlobalRef(peer); delete[] currentDirectory; if (ofn.lpstrFile) delete[] ofn.lpstrFile; } BOOL AwtFileDialog::GetOpenFileName(LPOPENFILENAME data) { return static_cast<BOOL>(reinterpret_cast Other Java examples (source code examples)Here is a short list of links related to this Java awt_FileDialog.cpp source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.