使用Windows资源管理器查看文件时,我可以选择设置“标记”,“类别”或其他属性。对于JPEG,可以选择不同的属性集(包括“标记”)。我希望能够以编程方式设置它们。
如何使用Delphi(我有Delphi 2010 Pro)以编程方式设置文件标签和其他文件属性?
答案 0 :(得分:5)
JPEG文件中的标签存储为IPTC关键字。有一些图书馆可供阅读和写作,如果这就是你要求的。
Explorer为不同的文件类型显示不同的列,因为它知道这些文件类型支持这些额外的列。您可以定义shell插件以支持您自己的文件类型的自定义列信息。 MSDN provides an overview.
答案 1 :(得分:4)
我认为您想要在资源管理器中按鼠标右键,检索可以接受的文件的所有属性。
您可以使用此单位:
unit u_fsummary;
interface
uses Windows, ComObj, ActiveX, Variants, Sysutils;
procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString);
function GetFileSummaryInfo(const FileName: WideString): String;
function IsNTFS(AFileName : string) : boolean;
implementation
const
FmtID_SummaryInformation: TGUID = '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
FMTID_DocSummaryInformation : TGUID = '{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
FMTID_UserDefinedProperties : TGUID = '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
IID_IPropertySetStorage : TGUID = '{0000013A-0000-0000-C000-000000000046}';
STGFMT_FILE = 3; //Indicates that the file must not be a compound file.
//This element is only valid when using the StgCreateStorageEx
//or StgOpenStorageEx functions to access the NTFS file system
//implementation of the IPropertySetStorage interface.
//Therefore, these functions return an error if the riid
//parameter does not specify the IPropertySetStorage interface,
//or if the specified file is not located on an NTFS file system volume.
STGFMT_ANY = 4; //Indicates that the system will determine the file type and
//use the appropriate structured storage or property set
//implementation.
//This value cannot be used with the StgCreateStorageEx function.
// Summary Information
PID_TITLE = 2;
PID_SUBJECT = 3;
PID_AUTHOR = 4;
PID_KEYWORDS = 5;
PID_COMMENTS = 6;
PID_TEMPLATE = 7;
PID_LASTAUTHOR = 8;
PID_REVNUMBER = 9;
PID_EDITTIME = 10;
PID_LASTPRINTED = 11;
PID_CREATE_DTM = 12;
PID_LASTSAVE_DTM = 13;
PID_PAGECOUNT = 14;
PID_WORDCOUNT = 15;
PID_CHARCOUNT = 16;
PID_THUMBNAIL = 17;
PID_APPNAME = 18;
PID_SECURITY = 19;
// Document Summary Information
PID_CATEGORY = 2;
PID_PRESFORMAT = 3;
PID_BYTECOUNT = 4;
PID_LINECOUNT = 5;
PID_PARCOUNT = 6;
PID_SLIDECOUNT = 7;
PID_NOTECOUNT = 8;
PID_HIDDENCOUNT = 9;
PID_MMCLIPCOUNT = 10;
PID_SCALE = 11;
PID_HEADINGPAIR = 12;
PID_DOCPARTS = 13;
PID_MANAGER = 14;
PID_COMPANY = 15;
PID_LINKSDIRTY = 16;
PID_CHARCOUNT2 = 17;
function IsNTFS(AFileName : string) : boolean;
var
fso, drv : OleVariant;
begin
IsNTFS := False;
fso := CreateOleObject('Scripting.FileSystemObject');
drv := fso.GetDrive(fso.GetDriveName(AFileName));
if drv.FileSystem = 'NTFS' then
IsNTFS := True;
end;
function StgOpenStorageEx (
const pwcsName : POleStr; //Pointer to the path of the
//file containing storage object
grfMode : LongInt; //Specifies the access mode for the object
stgfmt : DWORD; //Specifies the storage file format
grfAttrs : DWORD; //Reserved; must be zero
pStgOptions : Pointer; //Address of STGOPTIONS pointer
reserved2 : Pointer; //Reserved; must be zero
riid : PGUID; //Specifies the GUID of the interface pointer
out stgOpen : //Address of an interface pointer
IStorage ) : HResult; stdcall; external 'ole32.dll';
function GetFileSummaryInfo(const FileName: WideString): String;
var
I: Integer;
PropSetStg: IPropertySetStorage;
PropSpec: array of TPropSpec;
PropStg: IPropertyStorage;
PropVariant: array of TPropVariant;
Rslt: HResult;
S: String;
Stg: IStorage;
PropEnum: IEnumSTATPROPSTG;
HR : HResult;
PropStat: STATPROPSTG;
k : integer;
function PropertyPIDToCaption(const ePID: Cardinal): string;
begin
case ePID of
PID_TITLE:
Result := 'Title';
PID_SUBJECT:
Result := 'Subject';
PID_AUTHOR:
Result := 'Author';
PID_KEYWORDS:
Result := 'Keywords';
PID_COMMENTS:
Result := 'Comments';
PID_TEMPLATE:
Result := 'Template';
PID_LASTAUTHOR:
Result := 'Last Saved By';
PID_REVNUMBER:
Result := 'Revision Number';
PID_EDITTIME:
Result := 'Total Editing Time';
PID_LASTPRINTED:
Result := 'Last Printed';
PID_CREATE_DTM:
Result := 'Create Time/Date';
PID_LASTSAVE_DTM:
Result := 'Last Saved Time/Date';
PID_PAGECOUNT:
Result := 'Number of Pages';
PID_WORDCOUNT:
Result := 'Number of Words';
PID_CHARCOUNT:
Result := 'Number of Characters';
PID_THUMBNAIL:
Result := 'Thumbnail';
PID_APPNAME:
Result := 'Creating Application';
PID_SECURITY:
Result := 'Security';
else
Result := '$' + IntToHex(ePID, 8);
end
end;
begin
Result := '';
try
OleCheck(StgOpenStorageEx(PWideChar(FileName),
STGM_READ or STGM_SHARE_DENY_WRITE,
STGFMT_FILE,
0, nil, nil, @IID_IPropertySetStorage, stg));
PropSetStg := Stg as IPropertySetStorage;
OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));
OleCheck(PropStg.Enum(PropEnum));
I := 0;
hr := PropEnum.Next(1, PropStat, nil);
while hr = S_OK do
begin
inc(I);
SetLength(PropSpec,I);
PropSpec[i-1].ulKind := PRSPEC_PROPID;
PropSpec[i-1].propid := PropStat.propid;
hr := PropEnum.Next(1, PropStat, nil);
end;
SetLength(PropVariant,i);
Rslt := PropStg.ReadMultiple(i, @PropSpec[0], @PropVariant[0]);
if Rslt = S_FALSE then Exit;
for k := 0 to i -1 do
begin
S := '';
if PropVariant[k].vt = VT_LPSTR then
if Assigned(PropVariant[k].pszVal) then
S := PropVariant[k].pszVal;
S := Format(PropertyPIDToCaption(PropSpec[k].Propid)+ ' %s',[s]);
if S <> '' then Result := Result + S + #13;
end;
finally
end;
end;
procedure SetFileSummaryInfo(const FileName : WideString; Author, Title, Subject, Keywords, Comments : WideString);
var
PropSetStg: IPropertySetStorage;
PropSpec: array of TPropSpec;
PropStg: IPropertyStorage;
PropVariant: array of TPropVariant;
Stg: IStorage;
begin
OleCheck(StgOpenStorageEx(PWideChar(FileName), STGM_SHARE_EXCLUSIVE or STGM_READWRITE, STGFMT_ANY, 0, nil, nil, @IID_IPropertySetStorage, stg));
PropSetStg := Stg as IPropertySetStorage;
OleCheck(PropSetStg.Create(FmtID_SummaryInformation, FmtID_SummaryInformation, PROPSETFLAG_DEFAULT,STGM_CREATE or STGM_READWRITE or STGM_SHARE_EXCLUSIVE, PropStg));
Setlength(PropSpec,6);
PropSpec[0].ulKind := PRSPEC_PROPID;
PropSpec[0].propid := PID_AUTHOR;
PropSpec[1].ulKind := PRSPEC_PROPID;
PropSpec[1].propid := PID_TITLE;
PropSpec[2].ulKind := PRSPEC_PROPID;
PropSpec[2].propid := PID_SUBJECT;
PropSpec[3].ulKind := PRSPEC_PROPID;
PropSpec[3].propid := PID_KEYWORDS;
PropSpec[4].ulKind := PRSPEC_PROPID;
PropSpec[4].propid := PID_COMMENTS;
PropSpec[5].ulKind := PRSPEC_PROPID;
PropSpec[5].propid := 99;
SetLength(PropVariant,6);
PropVariant[0].vt:=VT_LPWSTR;
PropVariant[0].pwszVal:=PWideChar(Author);
PropVariant[1].vt:=VT_LPWSTR;
PropVariant[1].pwszVal:=PWideChar(Title);
PropVariant[2].vt:= VT_LPWSTR;
PropVariant[2].pwszVal:=PWideChar(Subject);
PropVariant[3].vt:= VT_LPWSTR;
PropVariant[3].pwszVal:=PWideChar(Keywords);
PropVariant[4].vt:= VT_LPWSTR;
PropVariant[4].pwszVal:=PWideChar(Comments);
PropVariant[5].vt:= VT_LPWSTR;
PropVariant[5].pwszVal:=PWideChar(Comments);
OleCheck(PropStg.WriteMultiple(6, @PropSpec[0], @PropVariant[0], 2 ));
PropStg.Commit(STGC_DEFAULT);
end;
end.
这不是我的代码,但我已成功使用它。它工作正常。 要检索属性,您可以执行以下操作:
mmProps2.Lines.Text := GetFileSummaryInfo(edtFile.Text);
问候
Neftalí
答案 2 :(得分:2)
我知道没有标准方法来存储其他元数据信息。每个应用程序都可以注册自己的属性选项卡,并可以以任何方式存储此元数据信息。
我相信你在谈论Windows Photo Gallery的图像标记功能。
信息存储在两个文件中:pictures.pd4和NavTree.state 由Gail Bjork person who wanted to remove this information确定。
存储在:C:\ Users \ YourUser \ AppData \ Local \ Microsoft \ Windows Photo Gallery。
Some people已经找到了文件格式。但我没有找到微软或外部任何人发布的规范。
您还询问了可以通过
设置的其他文件属性FileSetAttr(FileName,Attribute)
可以设置的属性:
//The following sets test.txt to a readonly and hidden file.
FileSetAttr('C:\Test.txt',faReadOnly or faHidden);
该函数有一个布尔结果,您可以检查操作是否成功完成。
答案 3 :(得分:0)
我正在开发一个标记应用程序,似乎最好的答案是Windows Imaging Component API,它具有读取和编写各种图像格式元数据的实现(Exif,IPTC等)。应区分文件系统中文件的元数据和文件本身内的元数据 - 这是引用后者的。
Getty Images also has a good article on programming with the WIC API.