Shell32 File Property Dialog
Johannes Anderwald
johannes.anderwald at student.tugraz.at
Wed Dec 7 09:09:04 CST 2005
This patch adds file property dialog to shell32
affected files: shell32_En.rc
shlexec.c
shv_item_cmenu.c
fprop.c (implementation file dialog)
Name: Johannes Anderwald
--
Johannes Anderwald
-------------- next part --------------
Index: dlls/shell32/shell32_En.rc
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_En.rc,v
retrieving revision 1.21
diff -u -p -r1.21 shell32_En.rc
--- dlls/shell32/shell32_En.rc 6 May 2005 15:44:32 -0000 1.21
+++ dlls/shell32/shell32_En.rc 7 Dec 2005 12:08:39 -0000
@@ -131,6 +131,33 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP
}
+SHELL_FILE_GENERAL_DLG DIALOGEX 0, 0, 240, 130
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "General"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+{
+ ICON "", 14000, 10, 5, 30, 30, WS_VISIBLE
+ EDITTEXT 14001, 70, 5, 100, 10, ES_LEFT | ES_READONLY
+ LTEXT "Type of file:", 14004, 10, 30, 50, 10
+ LTEXT "%s File", 14005, 70, 30, 150, 10
+ LTEXT "Opens with:", 14006, 10, 40, 50, 10
+ LTEXT "", 14007, 70, 40, 150, 10
+ LTEXT "Location:", 14008, 10, 55, 45, 10
+ LTEXT "", 14009, 70, 55, 150, 10
+ LTEXT "Size:",14010, 10, 65, 45, 10
+ LTEXT "", 14011, 70, 65, 150, 10
+ LTEXT "Created:", 14014, 10, 80, 45, 10
+ LTEXT "", 14015, 70, 80, 150, 10
+ LTEXT "Modied:", 14016, 10, 90, 45, 10
+ LTEXT "", 14017, 70, 90, 150, 10
+ LTEXT "Accessed:", 14018, 10, 100, 45, 10
+ LTEXT "", 14019, 70, 100, 150, 10
+ LTEXT "Attributes:", 14020, 10, 115, 45, 10
+ CHECKBOX "&Read-only", 14021, 70, 115, 45, 10
+ CHECKBOX "&Hidden", 14022, 130, 115, 50, 10
+ CHECKBOX "&Archive", 14023, 180, 115, 45, 10
+}
+
STRINGTABLE DISCARDABLE
{
/* columns in the shellview */
Index: dlls/shell32/shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.78
diff -u -p -r1.78 shlexec.c
--- dlls/shell32/shlexec.c 30 Nov 2005 20:54:46 -0000 1.78
+++ dlls/shell32/shlexec.c 7 Dec 2005 12:08:39 -0000
@@ -1185,6 +1185,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW
static const WCHAR wFile[] = {'f','i','l','e',0};
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
+ static const WCHAR wProperties[] = {'p','r','o','p','e','r','t','i','e','s',0};
static const DWORD unsupportedFlags =
SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
@@ -1275,7 +1276,11 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW
sei->hInstApp = (HINSTANCE) 33;
return TRUE;
}
-
+ if (sei_tmp.lpVerb)
+ {
+ if (!strcmpW(sei_tmp.lpVerb,wProperties))
+ return SH_ShowPropertiesDialog(sei_tmp.lpFile);
+ }
if (sei_tmp.fMask & SEE_MASK_CLASSALL)
{
/* launch a document by fileclass like 'WordPad.Document.1' */
Index: dlls/shell32/shv_item_cmenu.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shv_item_cmenu.c,v
retrieving revision 1.35
diff -u -p -r1.35 shv_item_cmenu.c
--- dlls/shell32/shv_item_cmenu.c 2 Sep 2005 11:32:17 -0000 1.35
+++ dlls/shell32/shv_item_cmenu.c 7 Dec 2005 12:08:40 -0000
@@ -384,6 +384,34 @@ static BOOL DoCopyOrCut(
}
return TRUE;
}
+
+/**************************************************************************
+ * DoProperties
+ *
+ * shows the file property dialog
+ */
+static void DoProperties(
+ IContextMenu2 *iface,
+ HWND hwnd)
+{
+ ItemCmImpl *This = (ItemCmImpl *)iface;
+
+ LPITEMIDLIST pidlFQ;
+ SHELLEXECUTEINFOA sei;
+
+ pidlFQ = ILCombine(This->pidl, This->apidl[0]);
+
+ ZeroMemory(&sei, sizeof(sei));
+ sei.cbSize = sizeof(sei);
+ sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
+ sei.lpIDList = pidlFQ;
+ sei.hwnd = hwnd;
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = "properties";
+ ShellExecuteExA(&sei);
+ SHFree(pidlFQ);
+}
+
/**************************************************************************
* ISvItemCm_fnInvokeCommand()
*/
@@ -432,8 +460,12 @@ static HRESULT WINAPI ISvItemCm_fnInvoke
TRACE("Verb FCIDM_SHVIEW_CUT\n");
DoCopyOrCut(iface, lpcmi->hwnd, TRUE);
break;
+ case FCIDM_SHVIEW_PROPERTIES:
+ TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
+ DoProperties(iface,lpcmi->hwnd);
+ break;
default:
- FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
+ FIXME("Unhandled Verb %x\n",LOWORD(lpcmi->lpVerb));
}
}
else
--- NUL ?
+++ dlls\shell32\fprop.c Wed Dec 07 13:07:33 2005
@@ -0,0 +1,418 @@
+/*
+ * Shell Library Functions
+ *
+ * Copyright 2005 Johannes Anderwald
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commdlg.h"
+#include "wine/debug.h"
+
+#include "shellapi.h"
+#include <shlwapi.h>
+#include "shlobj.h"
+#include "shell32_main.h"
+#include "shresdef.h"
+#include "undocshell.h"
+#include <prsht.h>
+
+
+#define MAX_PROPERTY_SHEET_PAGE 32
+#define TIMER_INTERVAL 100
+
+/*************************************************************************
+ *
+ * SH_CreatePropertySheetPage [Internal]
+ *
+ * creates a property sheet page from an resource name
+ *
+ */
+
+HPROPSHEETPAGE
+SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPFNPSPCALLBACKW pfnCallback, LPARAM lParam)
+{
+ HRSRC hRes;
+ LPVOID lpsztemplate;
+ PROPSHEETPAGEW ppage;
+
+ if (resname == NULL)
+ return (HPROPSHEETPAGE)0;
+
+ hRes = FindResourceA(shell32_hInstance, resname, (LPSTR)RT_DIALOG);
+
+ if (hRes == NULL)
+ return (HPROPSHEETPAGE)0;
+
+ lpsztemplate = LoadResource(shell32_hInstance, hRes);
+ if (lpsztemplate == NULL)
+ return (HPROPSHEETPAGE)0;
+
+ memset(&ppage, 0x0, sizeof(PROPSHEETPAGE));
+ ppage.dwSize = sizeof(PROPSHEETPAGE);
+ ppage.dwFlags = PSP_DLGINDIRECT | PSP_USECALLBACK;
+ ppage.pResource = lpsztemplate;
+ ppage.pfnDlgProc = dlgproc;
+ ppage.lParam = lParam;
+ ppage.pfnCallback = pfnCallback;
+
+ return CreatePropertySheetPageW(&ppage);
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralFileType [Internal]
+ *
+ * retrieves file extension description from registry and sets it in dialog
+ *
+ * TODO: retrieve file extension default icon and load it
+ * find executable name from registry, retrieve description from executable
+ */
+
+BOOL
+SH_FileGeneralSetFileType(HWND hwndDlg, WCHAR * filext)
+{
+ WCHAR name[MAX_PATH];
+ WCHAR value[MAX_PATH];
+ DWORD lname = MAX_PATH;
+ DWORD lvalue = MAX_PATH;
+
+ HKEY hKey;
+ LONG result;
+ HWND hDlgCtrl;
+
+
+ if (filext == NULL)
+ return FALSE;
+
+ hDlgCtrl = GetDlgItem(hwndDlg, 14005);
+
+ if (hDlgCtrl == NULL)
+ return FALSE;
+
+ memset(name, 0x0, sizeof(WCHAR) * MAX_PATH);
+ memset(value, 0x0, sizeof(WCHAR) * MAX_PATH);
+ if (RegOpenKeyW(HKEY_CLASSES_ROOT, filext, &hKey) != ERROR_SUCCESS)
+ {
+ /* the fileextension is unknown, so default to string "FileExtension File" */
+ SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)value);
+ sprintfW(name, value, &filext[1]);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)name);
+ return TRUE;
+ }
+
+ result = RegEnumValueW(hKey, 0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
+ RegCloseKey(hKey);
+
+ if (result != ERROR_SUCCESS)
+ return FALSE;
+
+ if (RegOpenKeyW(HKEY_CLASSES_ROOT, value, &hKey) == ERROR_SUCCESS)
+ {
+ lvalue = lname = MAX_PATH;
+ memset(name, 0x0, sizeof(TCHAR) * MAX_PATH);
+ memset(value, 0x0, sizeof(TCHAR) * MAX_PATH);
+ result = RegEnumValueW(hKey,0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
+ RegCloseKey(hKey);
+ }
+
+ /* file extension type */
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)value);
+
+ return TRUE;
+}
+/*************************************************************************
+ *
+ * SHFileGeneralGetFileTimeString [Internal]
+ *
+ * formats a given LPFILETIME struct into readable user format
+ */
+
+BOOL
+SHFileGeneralGetFileTimeString(LPFILETIME lpFileTime, WCHAR * lpResult)
+{
+ FILETIME ft;
+ SYSTEMTIME dt;
+ WORD wYear;
+ static const WCHAR wFormat[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
+
+ if (lpFileTime == NULL || lpResult == NULL)
+ return FALSE;
+
+ if (!FileTimeToLocalFileTime(lpFileTime, &ft))
+ return FALSE;
+
+ FileTimeToSystemTime(&ft, &dt);
+
+ wYear = dt.wYear;
+ /* ddmmyy */
+ sprintfW (lpResult, wFormat, dt.wDay, dt.wMonth, wYear, dt.wHour, dt.wMinute);
+
+ TRACE("result %s\n",debug_strw(lpResult));
+ return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralSetText [Internal]
+ *
+ * sets file path string and filename string
+ *
+ */
+
+BOOL
+SH_FileGeneralSetText(HWND hwndDlg, WCHAR * lpstr)
+{
+ int flength;
+ int plength;
+ WCHAR * lpdir;
+ WCHAR buff[MAX_PATH];
+ HWND hDlgCtrl;
+
+ if (lpstr == NULL)
+ return FALSE;
+
+ lpdir = strrchrW(lpstr, '\\'); /* find the last occurence of '\\' */
+
+ plength = strlenW(lpstr);
+ flength = strlenW(lpdir);
+
+ if (lpdir)
+ {
+ /* location text field */
+ strncpyW(buff, lpstr, plength - flength);
+ buff[plength - flength] = UNICODE_NULL;
+ hDlgCtrl = GetDlgItem(hwndDlg, 14009);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
+ }
+
+ if(flength > 1)
+ {
+ /* text filename field */
+ strncpyW(buff, &lpdir[1], flength);
+ hDlgCtrl = GetDlgItem(hwndDlg, 14001);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
+ }
+
+ return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralSetFileSizeTime [Internal]
+ *
+ * retrieves file information from file and sets in dialog
+ *
+ */
+
+BOOL
+SH_FileGeneralSetFileSizeTime(HWND hwndDlg, WCHAR * lpfilename, PULARGE_INTEGER lpfilesize)
+{
+ BOOL result;
+ HANDLE hFile;
+ FILETIME create_time;
+ FILETIME accessed_time;
+ FILETIME write_time;
+ WCHAR resultstr[MAX_PATH];
+ HWND hDlgCtrl;
+ LARGE_INTEGER file_size;
+
+ if (lpfilename == NULL)
+ return FALSE;
+
+ hFile = CreateFileW(lpfilename,
+ GENERIC_READ,
+ FILE_SHARE_READ,NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ WARN("failed to open file\n");
+ return FALSE;
+ }
+
+ result = GetFileTime(hFile, &create_time, &accessed_time, &write_time);
+
+ if (!result)
+ {
+ WARN("GetFileTime failed\n");
+ return FALSE;
+ }
+ if (SHFileGeneralGetFileTimeString(&create_time,resultstr))
+ {
+ hDlgCtrl = GetDlgItem(hwndDlg, 14015);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+ }
+
+ if (SHFileGeneralGetFileTimeString(&accessed_time, resultstr))
+ {
+ hDlgCtrl = GetDlgItem(hwndDlg, 14017);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+ }
+
+ if (SHFileGeneralGetFileTimeString(&write_time, resultstr))
+ {
+ hDlgCtrl = GetDlgItem(hwndDlg, 14019);
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+ }
+
+ if (!GetFileSizeEx(hFile, &file_size))
+ {
+ WARN("GetFileSize failed\n");
+ CloseHandle(hFile);
+ return FALSE;
+ }
+ CloseHandle(hFile);
+
+ if (!StrFormatByteSizeW(file_size.QuadPart, resultstr, sizeof(resultstr)))
+ return FALSE;
+
+ hDlgCtrl = GetDlgItem(hwndDlg, 14011);
+ TRACE("result %s\n", debug_strw(resultstr));
+ SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+
+ if (lpfilesize)
+ lpfilesize->QuadPart = (ULONGLONG)file_size.QuadPart;
+
+ return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralDlgProc
+ *
+ * wnd proc of 'General' property sheet page
+ *
+ */
+
+INT_PTR
+CALLBACK
+SH_FileGeneralDlgProc(
+ HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ LPPROPSHEETPAGEW ppsp;
+ WCHAR * lpstr;
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ ppsp = (LPPROPSHEETPAGEW)lParam;
+ if (ppsp == NULL)
+ break;
+
+ TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n",hwndDlg, lParam, ppsp->lParam);
+
+ lpstr = (WCHAR *)ppsp->lParam;
+
+ if (lpstr == NULL)
+ break;
+
+ /* set general text properties filename filelocation and icon */
+ SH_FileGeneralSetText(hwndDlg, lpstr);
+ /* enumerate file extension from registry and application which opens it*/
+ SH_FileGeneralSetFileType(hwndDlg, strrchrW(lpstr, '.'));
+ /* set file time create/modfied/accessed */
+ SH_FileGeneralSetFileSizeTime(hwndDlg, lpstr, NULL);
+
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+ *
+ * SH_ShowPropertiesDialog
+ *
+ * called from ShellExecuteExW32
+ *
+ * lpf contains (quoted) path of folder/file
+ *
+ * TODO: provide button change application type if file has registered type
+ * make filename field editable and apply changes to filename on close
+ */
+
+BOOL
+SH_ShowPropertiesDialog(WCHAR * lpf)
+{
+ PROPSHEETHEADERW pinfo;
+ HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
+ HPROPSHEETPAGE hpage;
+ WCHAR wFileName[MAX_PATH];
+
+ TRACE("SH_ShowPropertiesDialog entered\n");
+
+ if (lpf== NULL)
+ return FALSE;
+
+ memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
+
+ if (lpf[0] == '"')
+ {
+ /* remove quotes from lpf */
+ LPWSTR src = lpf + 1;
+ LPWSTR dst = wFileName;
+
+ while(*src && *src!='"')
+ *dst++ = *src++;
+
+ *dst = '\0';
+ }
+ else
+ strcpyW(wFileName, lpf);
+
+
+ if (PathIsDirectoryW(wFileName) || strlenW(wFileName) == 3)
+ {
+ FIXME("directory / drive resources are missing\n");
+ return FALSE;
+ }
+
+ hpage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, NULL, (LPARAM)wFileName);
+
+ if (hpage == NULL)
+ return FALSE;
+
+ hppages[0] = hpage;
+
+ memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
+ pinfo.dwSize = sizeof(PROPSHEETHEADERW);
+ pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
+ pinfo.nPages = 1;
+ pinfo.phpage = hppages;
+ pinfo.pszCaption = wFileName;
+
+ return (PropertySheetW(&pinfo) != -1);
+}
+/*EOF */
More information about the wine-patches
mailing list