📄 filedlg.c
字号:
/*
* COMMDLG - File Open Dialogs Win95 look and feel
*
* Copyright 1999 Francois Boisvert
* Copyright 1999, 2000 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* FIXME: The whole concept of handling unicode is badly broken.
* many hook-messages expect a pointer to a
* OPENFILENAMEA or W structure. With the current architecture
* we would have to convert the beast at every call to a hook.
* we have to find a better solution but it would likely cause
* a complete rewrite after which we should handle the
* OPENFILENAME structure without any converting (jsch).
*
* FIXME: any hook gets a OPENFILENAMEA structure
*
* FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
*
* FIXME: old style hook messages are not implemented (except FILEOKSTRING)
*
* FIXME: algorithm for selecting the initial directory is too simple
*
* FIXME: add to recent docs
*
* FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
* OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING,
* OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
* OFN_NOTESTFILECREATE, OFN_USEMONIKERS
*
* FIXME: lCustData for lpfnHook (WM_INITDIALOG)
*
*
*/
#include "config.h"
#include "wine/port.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "winnls.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "commdlg.h"
#include "dlgs.h"
#include "cdlg.h"
#include "filedlg31.h"
#include "cderr.h"
#include "shellapi.h"
#include "shlobj.h"
#include "filedlgbrowser.h"
#include "shlwapi.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
#define UNIMPLEMENTED_FLAGS \
(OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
#define IsHooked(fodInfos) \
((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
/***********************************************************************
* Data structure and global variables
*/
typedef struct SFolder
{
int m_iImageIndex; /* Index of picture in image list */
HIMAGELIST hImgList;
int m_iIndent; /* Indentation index */
LPITEMIDLIST pidlItem; /* absolute pidl of the item */
} SFOLDER,*LPSFOLDER;
typedef struct tagLookInInfo
{
int iMaxIndentation;
UINT uSelectedItem;
} LookInInfos;
typedef struct tagFD32_PRIVATE
{
OPENFILENAMEA *ofnA; /* original structure if 32bits ansi dialog */
} FD32_PRIVATE, *PFD32_PRIVATE;
/***********************************************************************
* Defines and global variables
*/
/* Draw item constant */
#define ICONWIDTH 18
#define XTEXTOFFSET 3
/* AddItem flags*/
#define LISTEND -1
/* SearchItem methods */
#define SEARCH_PIDL 1
#define SEARCH_EXP 2
#define ITEM_NOTFOUND -1
/* Undefined windows message sent by CreateViewObject*/
#define WM_GETISHELLBROWSER WM_USER+7
/* NOTE
* Those macros exist in windowsx.h. However, you can't really use them since
* they rely on the UNICODE defines and can't be used inside Wine itself.
*/
/* Combo box macros */
#define CBAddString(hwnd,str) \
SendMessageW(hwnd, CB_ADDSTRING, 0, (LPARAM)(str));
#define CBInsertString(hwnd,str,pos) \
SendMessageW(hwnd, CB_INSERTSTRING, (WPARAM)(pos), (LPARAM)(str));
#define CBDeleteString(hwnd,pos) \
SendMessageW(hwnd, CB_DELETESTRING, (WPARAM)(pos), 0);
#define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
SendMessageW(hwnd, CB_SETITEMDATA, (WPARAM)(iItemId), (LPARAM)(dataPtr));
#define CBGetItemDataPtr(hwnd,iItemId) \
SendMessageW(hwnd, CB_GETITEMDATA, (WPARAM)(iItemId), 0)
#define CBGetLBText(hwnd,iItemId,str) \
SendMessageW(hwnd, CB_GETLBTEXT, (WPARAM)(iItemId), (LPARAM)(str));
#define CBGetCurSel(hwnd) \
SendMessageW(hwnd, CB_GETCURSEL, 0, 0);
#define CBSetCurSel(hwnd,pos) \
SendMessageW(hwnd, CB_SETCURSEL, (WPARAM)(pos), 0);
#define CBGetCount(hwnd) \
SendMessageW(hwnd, CB_GETCOUNT, 0, 0);
#define CBShowDropDown(hwnd,show) \
SendMessageW(hwnd, CB_SHOWDROPDOWN, (WPARAM)(show), 0);
#define CBSetItemHeight(hwnd,index,height) \
SendMessageW(hwnd, CB_SETITEMHEIGHT, (WPARAM)(index), (LPARAM)(height));
#define CBSetExtendedUI(hwnd,flag) \
SendMessageW(hwnd, CB_SETEXTENDEDUI, (WPARAM)(flag), 0)
const char FileOpenDlgInfosStr[] = "FileOpenDlgInfos"; /* windows property description string */
static const char LookInInfosStr[] = "LookInInfos"; /* LOOKIN combo box property */
/***********************************************************************
* Prototypes
*/
/* Internal functions used by the dialog */
static LRESULT FILEDLG95_ResizeControls(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT FILEDLG95_FillControls(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
static BOOL FILEDLG95_OnOpen(HWND hwnd);
static LRESULT FILEDLG95_InitControls(HWND hwnd);
static void FILEDLG95_Clean(HWND hwnd);
/* Functions used by the shell navigation */
static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
static void FILEDLG95_SHELL_Clean(HWND hwnd);
static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd);
/* Functions used by the EDIT box */
static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd, LPWSTR * lpstrFileList, UINT * sizeUsed, char separator);
/* Functions used by the filetype combo box */
static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCWSTR lpstrExt);
static void FILEDLG95_FILETYPE_Clean(HWND hwnd);
/* Functions used by the Look In combo box */
static void FILEDLG95_LOOKIN_Init(HWND hwndCombo);
static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
static void FILEDLG95_LOOKIN_Clean(HWND hwnd);
/* Miscellaneous tool functions */
static HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPWSTR lpstrFileName);
IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
static LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPWSTR lpcstrFileName);
/* Shell memory allocation */
static void *MemAlloc(UINT size);
static void MemFree(void *mem);
static INT_PTR CALLBACK FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPWSTR lpstrFileList, UINT nFileCount, UINT sizeUsed);
static BOOL BrowseSelectedFolder(HWND hwnd);
/***********************************************************************
* GetFileName95
*
* Creates an Open common dialog box that lets the user select
* the drive, directory, and the name of a file or set of files to open.
*
* IN : The FileOpenDlgInfos structure associated with the dialog
* OUT : TRUE on success
* FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
*/
static BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos)
{
LRESULT lRes;
LPCVOID template;
HRSRC hRes;
HANDLE hDlgTmpl = 0;
HRESULT hr;
/* test for missing functionality */
if (fodInfos->ofnInfos->Flags & UNIMPLEMENTED_FLAGS)
{
FIXME("Flags 0x%08x not yet implemented\n",
fodInfos->ofnInfos->Flags & UNIMPLEMENTED_FLAGS);
}
/* Create the dialog from a template */
if(!(hRes = FindResourceW(COMDLG32_hInstance,MAKEINTRESOURCEW(NEWFILEOPENORD),(LPCWSTR)RT_DIALOG)))
{
COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
return FALSE;
}
if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hRes )) ||
!(template = LockResource( hDlgTmpl )))
{
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
return FALSE;
}
/* old style hook messages */
if (IsHooked(fodInfos))
{
fodInfos->HookMsg.fileokstring = RegisterWindowMessageW(FILEOKSTRINGW);
fodInfos->HookMsg.lbselchstring = RegisterWindowMessageW(LBSELCHSTRINGW);
fodInfos->HookMsg.helpmsgstring = RegisterWindowMessageW(HELPMSGSTRINGW);
fodInfos->HookMsg.sharevistring = RegisterWindowMessageW(SHAREVISTRINGW);
}
/* Some shell namespace extensions depend on COM being initialized. */
hr = OleInitialize(NULL);
if (fodInfos->unicode)
lRes = DialogBoxIndirectParamW(COMDLG32_hInstance,
template,
fodInfos->ofnInfos->hwndOwner,
FileOpenDlgProc95,
(LPARAM) fodInfos);
else
lRes = DialogBoxIndirectParamA(COMDLG32_hInstance,
(LPCDLGTEMPLATEA) template,
fodInfos->ofnInfos->hwndOwner,
FileOpenDlgProc95,
(LPARAM) fodInfos);
if (SUCCEEDED(hr))
OleUninitialize();
/* Unable to create the dialog */
if( lRes == -1)
return FALSE;
return lRes;
}
/***********************************************************************
* GetFileDialog95A
*
* Call GetFileName95 with this structure and clean the memory.
*
* IN : The OPENFILENAMEA initialisation structure passed to
* GetOpenFileNameA win api function (see filedlg.c)
*/
BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
{
BOOL ret;
FileOpenDlgInfos fodInfos;
LPSTR lpstrSavDir = NULL;
LPWSTR title = NULL;
LPWSTR defext = NULL;
LPWSTR filter = NULL;
LPWSTR customfilter = NULL;
/* Initialize CommDlgExtendedError() */
COMDLG32_SetCommDlgExtendedError(0);
/* Initialize FileOpenDlgInfos structure */
ZeroMemory(&fodInfos, sizeof(FileOpenDlgInfos));
/* Pass in the original ofn */
fodInfos.ofnInfos = (LPOPENFILENAMEW)ofn;
/* save current directory */
if (ofn->Flags & OFN_NOCHANGEDIR)
{
lpstrSavDir = MemAlloc(MAX_PATH);
GetCurrentDirectoryA(MAX_PATH, lpstrSavDir);
}
fodInfos.unicode = FALSE;
/* convert all the input strings to unicode */
if(ofn->lpstrInitialDir)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, ofn->lpstrInitialDir, -1, NULL, 0 );
fodInfos.initdir = MemAlloc((len+1)*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, ofn->lpstrInitialDir, -1, fodInfos.initdir, len);
}
else
fodInfos.initdir = NULL;
if(ofn->lpstrFile)
{
fodInfos.filename = MemAlloc(ofn->nMaxFile*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, ofn->lpstrFile, -1, fodInfos.filename, ofn->nMaxFile);
}
else
fodInfos.filename = NULL;
if(ofn->lpstrDefExt)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, ofn->lpstrDefExt, -1, NULL, 0 );
defext = MemAlloc((len+1)*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, ofn->lpstrDefExt, -1, defext, len);
}
fodInfos.defext = defext;
if(ofn->lpstrTitle)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, ofn->lpstrTitle, -1, NULL, 0 );
title = MemAlloc((len+1)*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, ofn->lpstrTitle, -1, title, len);
}
fodInfos.title = title;
if (ofn->lpstrFilter)
{
LPCSTR s;
int n, len;
/* filter is a list... title\0ext\0......\0\0 */
s = ofn->lpstrFilter;
while (*s) s = s+strlen(s)+1;
s++;
n = s - ofn->lpstrFilter;
len = MultiByteToWideChar( CP_ACP, 0, ofn->lpstrFilter, n, NULL, 0 );
filter = MemAlloc(len*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, ofn->lpstrFilter, n, filter, len );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -