Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > TOpenDialog


Автор: Illusion Dolphin 3.10.2004, 17:48
Можно ли в стандартном TOpenDialog установить максимальный размер отображаемых файлов? Т.е. чтобы, например, отображались только файлы, размером менее 12 килобайт?

Автор: Alex 3.10.2004, 18:02
я думаю нет

Автор: Illusion Dolphin 3.10.2004, 18:11
А что значит это событие?
Код

procedure TForm1.OpenDialog1IncludeItem(const OFN: TOFNotifyEx;
 var Include: Boolean);
begin

end;


Я перевожу этот как ПриДовавленииИтема - может, как-то можно? А?

Автор: Pakshin A. S. 3.10.2004, 20:39
А когда это вообще срабатывает?

Один из вариантов решения: самостоятельное создание диалога стандартными и нестандартными средствами... hmmm.gif

Автор: Illusion Dolphin 3.10.2004, 22:30
Мдя... Ещё варианты есть? Если нет, то неблагодарное это дело...

Автор: Alex 3.10.2004, 22:40
Ну вообщето ты нашел правильное событие, но оно сработает только на виндах от 2000 и выше. Но как им пользоваться пока не знаю.

Автор: Illusion Dolphin 3.10.2004, 23:58
Цитата
правильное событие

Гы 8). У меня виньХР, и как это всё запустить biggrin.gif? Кто-нибудь знает?

Автор: p0s0l 4.10.2004, 11:01
Запустить - включить опцию ofEnableIncludeNotify
Пользоваться - я написал такой обработчик:
Код
procedure TForm1.OpenDialog1IncludeItem(const OFN: TOFNotifyEx;
 var Include: Boolean);
var
 fi : WIN32_FILE_ATTRIBUTE_DATA;
 sr : STRRET;
 FileName : string;

begin
 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;
 GetFileAttributesEx (PChar(FileName), GetFileExInfoStandard, @fi);
 Include := (fi.nFileSizeHigh = 0) and (fi.nFileSizeLow < 12*1024);
end;
Но это не работает... Код-то типа правильный, но само событие немного левое: изменение Include ни на что не влияет (хотя должно влиять). К примеру, если просто написать:
Код
procedure TForm1.OpenDialog1IncludeItem(const OFN: TOFNotifyEx;
 var Include: Boolean);
begin
 Include := False;
end;
то всё равно все файлы будут добавляться в OpenDialog... sad.gif

Автор: Alex 4.10.2004, 16:27
Цитата(p0s0l @ 4.10.2004, 12:01)
Но это не работает... Код-то типа правильный, но само событие немного левое: изменение Include ни на что не влияет (хотя должно влиять). К примеру, если просто написать:
Код
procedure TForm1.OpenDialog1IncludeItem(const OFN: TOFNotifyEx;
var Include: Boolean);
begin
Include := False;
end;



то всё равно все файлы будут добавляться в OpenDialog...

Я вчера тутже заткнулся к чему этот Include вообще не понятно sad.gif

Автор: Girder 4.10.2004, 18:48
И так не работает
Код
function fHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
var FileName:string;
   fi:WIN32_FILE_ATTRIBUTE_DATA;
   sr:_STRRET;
   sHigh,sLow:cardinal;
begin
Result:=0;
if (Msg = WM_NOTIFY) then
 if (POFNotify(LParam)^.hdr.code)=CDN_INCLUDEITEM then
  begin
   Result:=1;
   if LParam<>0 then
    begin
     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: FileName:=PChar(Cardinal(POFNotifyEx(LParam)^.pidl)+sr.uOffset);
     end;
     if (FileExists(FileName,sHigh,sLow)=0)and((sHigh>0)or(sLow>12*1024)) then
      Result:=0;
    end;
  end;
end;

procedure TForm1.Button2Click(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:='DD'+#0+'*.dd'+#0+'Все файлы'+#0+'*.*'+#0+#0;
ofn.nFilterIndex:=1;
ofn.lpstrFileTitle:='Title';
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
 Edit1.Text:=ofn.lpstrFile;
end;
Может быть ноги от сюда растут:
Цитата
The dialog box always includes items that have both the SFGAO_FILESYSTEM and SFGAO_FILESYSANCESTOR attributes, regardless of the value returned by CDN_INCLUDEITEM

Автор: Pakshin A. S. 4.10.2004, 20:24
А может все-таки своими силами диалог составлять?

Автор: Illusion Dolphin 4.10.2004, 21:03
Цитата
А может все-таки своими силами диалог составлять?

Т.е. полностью переписывать с использованием TListView? Или способ попроще?

Автор: Pakshin A. S. 4.10.2004, 21:14
Можно и ListBox переделать (иконки поставить под папки и файлы...). Надо немного подумать...

Автор: Pakshin A. S. 4.10.2004, 21:45
А можно и с компонетами во вкладке Win3.1: DriveComboBox1 FilterComboBox1 DirectoryListBox1 FileListBox1

по обытиям от Change компонентов смотрим в FileListBox1
Код

for i:=0 to FileListBox1.items.Count-1 do
 if  ...FileListBox1.Items[i]... // проверяем размер
  then
   begin
    // размер не тот
    FileListBox1.Items.Delete(i);
    dec(i);
   end;


Может сработает... sad.gif

Автор: Alex 4.10.2004, 21:48
а я бы попробовал вариант Girder

Автор: p0s0l 4.10.2004, 23:10
Цитата(Alex @ 4.10.2004, 21:48)
а я бы попробовал вариант Girder
На самом деле, это почти тот же TOpenDialog, поэтому тоже и не работает... Если добиться того, чтобы заработал вариант Girder'а, то можно заставить работать и TOpenDialog...

Автор: Alex 5.10.2004, 08:28
Цитата(p0s0l @ 5.10.2004, 00:10)
На самом деле, это почти тот же TOpenDialog, поэтому тоже и не работает... Если добиться того, чтобы заработал вариант Girder'а, то можно заставить работать и TOpenDialog...

Я бы все же с его вариантом экспериментировал. Особенно мне хук функция покоя не дает.

Автор: Girder 5.10.2004, 09:25
Когда я увидел это
Цитата
а я бы попробовал вариант Girder
я решил обождать с ответом, но почему-то ни кто так и недогадался.

Стандартным(цивилизованным) способом, заставить принимать Result(а также Malloc.Free(POFNotifyEx(LParam)^.pidl)) на врядли удастся. Но эту ОС писали(и пишут) обычные люди и как всегда(если очень хочется smile.gif ) можно все это обойти.

Предположения для решения:
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:[email protected][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.


Удачи.

Автор: Girder 5.10.2004, 14:53
Забыл добавить: Все это работает только для Explorer стиля (т.е. если убрать OFN_EXPLORER или Exclude(o,ofOldStyleDialog) - работать не будет!).

ИМХО: Считаю... что старый стиль уже в прошлом smile.gif

Автор: Illusion Dolphin 5.10.2004, 15:59
Girder: большое СПАСИБО! Оно действительно работает... Теперь буду разбираться, что к чему 8)...

Автор: Alex 5.10.2004, 18:40
Цитата(Girder @ 5.10.2004, 10:25)
я решил обождать с ответом, но почему-то ни кто так и недогадался.

Я бы сказал времени небыло smile.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)