Когда я увидел это| Цитата | | а я бы попробовал вариант Girder | я решил обождать с ответом, но почему-то ни кто так и недогадался.
Стандартным(цивилизованным) способом, заставить принимать Result(а также Malloc.Free(POFNotifyEx(LParam)^.pidl)) на врядли удастся. Но эту ОС писали(и пишут) обычные люди и как всегда(если очень хочется ) можно все это обойти.
Предположения для решения: 1)CDN_INCLUDEITEM - выдается до наложения фильтра на имя файла. 2)* и *.* в понимании программистов из microsoft одно и тоже и более того - имя файла может быть пустым. Вывод: 1)Можем использовать CDN_INCLUDEITEM для использования фильтра. 2)Заменить * и *.* на одну из этих масок: ?* или *? или *?* - т.е имя файла должно иметь хотя бы один символ.
Код с использованием API:| Код | unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses ShlObj,CommDlg;
function FileExists(const eFile:string;var sHigh,SLow:cardinal):integer; var sf:string; fesr:TSearchRec; sfAttr:integer; begin sf:=trim(eFile); Result:=3; if (Length(sf)=0)or(sf[Length(sf)]='\') then exit; sfAttr:=$FFE7; Result:=FindFirst(sf,sfAttr,fesr); if Result=0 then begin Result:=2; repeat if (((fesr.Attr and $10)<>$10)and((fesr.Attr and $8)<>$8)) then begin Result:=0; sHigh:=fesr.FindData.nFileSizeHigh; sLow:=fesr.FindData.nFileSizeLow; end; until (Result=0)or(FindNext(fesr)<>0); FindClose(fesr); end; end;
function fHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall; var FileName:string; sr:TStrRet; sHigh,sLow:cardinal; IDL:PItemIDList; P:PChar; {function NextPIDL(nIDL:PItemIDList):PItemIDList; begin Result:=nIDL; Inc(PChar(Result),nIDL^.mkid.cb); end; function GetCount(cIDL:PItemIDList):integer; begin Result:=0; while cIDL^.mkid.cb<>0 do begin Inc(Result); cIDL:=NextPIDL(cIDL); end; end; } begin Result:=0; //На всяк пожарный if (Msg=WM_NOTIFY) then if (POFNotify(LParam)^.hdr.code)=CDN_INCLUDEITEM then begin Result:=1; //На всяк пожарный if LParam<>0 then begin IDL:=POFNotifyEx(LParam)^.pidl; POFNotifyEx(LParam)^.psf.GetDisplayNameOf(POFNotifyEx(LParam)^.pidl,SHGDN_FORPARSING,sr); case sr.uType of STRRET_CSTR:FileName:=sr.cStr; STRRET_WSTR:FileName:=sr.pOleStr; STRRET_OFFSET: begin P:=@IDL.mkid.abID[sr.uOffset-SizeOf(IDL.mkid.cb)]; SetString(FileName,P,IDL.mkid.cb-sr.uOffset); end; end; if (FileExists(FileName,sHigh,sLow)=0)and((sHigh>0)or(sLow>12*1024)) then //12*12024 - размер на 12Kb begin Result:=0; //На всяк пожарный //IDL^.mkid.cb:=0; //приводит к утечкам IDL^.mkid.abID[0]:=0; end; end; end; end;
procedure TForm1.Button1Click(Sender: TObject); var ofn:OPENFILENAME; szFile:array [1..1024] of char; begin FillChar(ofn,SizeOf(ofn),#0); FillChar(szFile,SizeOf(szFile),#0); ofn.lStructSize:=SizeOf(ofn); ofn.hwndOwner:=Handle; ofn.lpstrFile:=@szFile; ofn.nMaxFile:=sizeof(szFile); ofn.lpstrFilter:='Dat'+#0+'*.dat'+#0+'Все файлы'+#0+'*?*'+#0+#0; ofn.nFilterIndex:=2; ofn.lpstrFileTitle:=nil; ofn.nMaxFileTitle:=0; ofn.lpstrInitialDir:=nil; ofn.Flags:=OFN_ENABLEINCLUDENOTIFY or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER or OFN_ENABLEHOOK; ofn.lpfnHook:=fHook; if GetOpenFileName(ofn)=true then Caption:=ofn.lpstrFile; end;
end.
|
Код с использованием компонента| Код | unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; OpenDialog1: TOpenDialog; procedure Button1Click(Sender: TObject); procedure OpenDialog1IncludeItem(const OFN: TOFNotifyEx; var Include: Boolean); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses ShlObj;
function FileExists(const eFile:string;var sHigh,SLow:cardinal):integer; var sf:string; fesr:TSearchRec; sfAttr:integer; begin sf:=trim(eFile); Result:=3; if (Length(sf)=0)or(sf[Length(sf)]='\') then exit; sfAttr:=$FFE7; Result:=FindFirst(sf,sfAttr,fesr); if Result=0 then begin Result:=2; repeat if (((fesr.Attr and $10)<>$10)and((fesr.Attr and $8)<>$8)) then begin Result:=0; sHigh:=fesr.FindData.nFileSizeHigh; sLow:=fesr.FindData.nFileSizeLow; end; until (Result=0)or(FindNext(fesr)<>0); FindClose(fesr); end; end;
procedure TForm1.Button1Click(Sender: TObject); var o:TOpenOptions; begin o:=OpenDialog1.Options; Include(o,ofEnableIncludeNotify); Exclude(o,ofOldStyleDialog); OpenDialog1.Options:=o; OpenDialog1.Filter:='Dat|*.dat|Все файлы|*?*'; OpenDialog1.OnIncludeItem:=OpenDialog1IncludeItem; if OpenDialog1.Execute then Caption:=OpenDialog1.FileName; end;
procedure TForm1.OpenDialog1IncludeItem(const OFN: TOFNotifyEx; var Include: Boolean); var FileName:string; sr:TStrRet; sHigh,sLow:cardinal; IDL:PItemIDList; begin Include:=true; //На всяк пожарный ofn.psf.GetDisplayNameOf(ofn.pidl, SHGDN_FORPARSING, sr); case sr.uType of STRRET_CSTR:FileName:=sr.cStr; STRRET_WSTR:FileName:=sr.pOleStr; STRRET_OFFSET:FileName:=PChar(Cardinal(ofn.pidl)+sr.uOffset); end; IDL:=ofn.pidl; if (FileExists(FileName,sHigh,sLow)=0)and((sHigh>0)or(sLow>12*1024)) then begin Include:=false; //На всяк пожарный try //IDL^.mkid.cb:=0; //приводит к утечкам IDL^.mkid.abID[0]:=0; except //На всяк пожарный - а то вдруг и вправду привелегий не будет end; end; end;
end.
|
Удачи. |