PDA

View Full Version : The windows open file dialog and extension filtering (bug?)


Blight
29th February 2004, 02:27
The following list is in reality 1 line, in delphi it's the "Filters" property of a TOpenDialog component and in C++/WinAPI it's the "lpstrFilter" value of the "OpenFilename" structure used with the "GetOpenFileName" WinAPI function (under WinAPI the "|" characters would be null characters, they are just listed as "|" for clarity and delphi compatibility {delphi convers the "|" to Ascii #0 before passing it along to the WinAPI function).


Media Files|VIDEO_TS.IFO;*.TRAILERS;*.URL;*.ASX;*.B4S;
*.M3U;*.PLS;*.WPL;*.ZPL;*.ASF;*.AVI;*.AVS;*.DAT;*.FLC;
*.FLI;*.MKV;*.MOV;*.MP4;*.MPG;*.MPEG;*.M2V;*.OGM;*.PART;
*.VOB;*.RM;*.RAM;*.RMM;*.RMVB;*.SWF;*.TS;*.TP;*.WMV;
*.AAC;*.AC3;*.APE;*.CDA;*.DTS;*.FLAC;*.MID;*.MKA;*.MP2;
*.MP3;*.MPA;*.MPC;*.OGG;*.RA;*.WAV;*.WMA;*.7Z;*.ARJ;*.BZ2;
*.CAB;*.RAR;*.ZIP|
Video Files|*.ASX;*.B4S;*.M3U;*.PLS;*.WPL;*.ZPL;*.ASF;
*.AVI;*.AVS;*.DAT;*.FLC;*.FLI;*.MKV;*.MOV;*.MP4;*.MPG;
*.MPEG;*.M2V;*.OGM;*.PART;*.VOB;*.RM;*.RAM;*.RMM;
*.RMVB;*.SWF;*.TS;*.TP;*.WMV;*.7Z;*.ARJ;*.BZ2;*.CAB;
*.RAR;*.ZIP|
Audio Files|*.ASX;*.B4S;*.M3U;*.PLS;*.WPL;*.ZPL;*.AAC;
*.AC3;*.APE;*.CDA;*.DTS;*.FLAC;*.MID;*.MKA;*.MP2;*.MP3;
*.MPA;*.MPC;*.OGG;*.RA;*.WAV;*.WMA;*.7Z;*.ARJ;*.BZ2;
*.CAB;*.RAR;*.ZIP|
Play Lists|*.ASX;*.B4S;*.M3U;*.PLS;*.WPL;*.ZPL;*.7Z;
*.ARJ;*.BZ2;*.CAB;*.RAR;*.ZIP|
CD Audio|*.CDA|
Images|*.BMP;*.GIF;*.JPEG;*.JPG;*.JPS;*.PNG|
All Files|*.*'


This massive list of extension is used for filtering in the windows open dialog. It is divided into several categories (Media Files, Video Files, Audio Files, Play Lists, CD Audio, Images and All Files).

Ok, and here is where the trouble arises... If the list of extensions in one of the categories is too big, that category basically becomes disfunctional (while all other categories seem to work).

The filter list is passed to the WinAPI function as one string, the string doesn't get truncated as categories further down the string work just fine, the only category that fails in the string specified above is the "Media Files" category which is ... HUGE.

This seem to be a bug in windows (using fully patched Windows XP here), I haven't found any mention of it (searched google quite a bit), anyone have an idea what can be done, I'd rather not write my own open-dialog component from scratch...

Moitah
29th February 2004, 06:28
I played around with GetOpenFileName in VB and figured out that it breaks when the filename part of the filter is longer than 260 characters, which is what the MAX_PATH constant is. I guess you'll have to find a different way :/

Windows 2000 SP4 here.

Blight
29th February 2004, 11:47
Moitah:
Huh? I'm not referencing the filename portion, I'm talking about the file extension filtering.

LIGHTNING UK!
29th February 2004, 14:02
Damn that's a weird bug!

It's not a problem with the length of the string because if you take what you're using there and add a single character to one of the extensions (pre char 255 - see below), it works fine. Same goes for removing one.

It would seem that if the '*.' are at positions 254 and 255 in the string, it becomes 'all files'.

To fix this, simply add another ';' after 'VIDEO_TS.IFO;' to make it 'VIDEO_TS.IFO;;'

Well, it worked for me anyway! But im using the API directly, not going via the crappy TOpenDialog built into Borland. Maybe if you're using Delphi 7 they've improved it... I dunno.

Moitah
29th February 2004, 16:42
Originally posted by Blight
Moitah:
Huh? I'm not referencing the filename portion, I'm talking about the file extension filtering. By 'filename part of the filter', I meant the extension list.

Originally posted by LIGHTNING UK!
It's not a problem with the length of the string because if you take what you're using there and add a single character to one of the extensions (pre char 255 - see below), it works fine. Same goes for removing one.I think all of the extensions past a certain point will be ignored, though.

gabest
29th February 2004, 18:01
With VC's MFC I got the same problem and ended up filtering the files myself by implementing some of the notification message handers of this dialog....

Blight
29th February 2004, 18:29
gabest:
I read some notes that the notification interface may not be supported on some early versions of windows... Any ideas about that?

gabest
29th February 2004, 18:47
MSDN writes about OFN_ENABLEINCLUDENOTIFY/CDN_INCLUDEITEM that it requires 2000/XP, but it works just fine on my 98SE too.

Blight
29th February 2004, 22:14
Gabest:
Anything special you need to do for the CDN_INCLUDEITEM callback to work, I'm setting the result, but it doesn't seem to be making any difference, all files appear on the dialog regardless.

gabest
29th February 2004, 22:30
Return Value

If the OFNHookProc hook procedure returns zero, the dialog box excludes the item from the list of items.

To include the item, return a nonzero value from the hook procedure.

Remarks

The dialog box always includes items that have both the SFGAO_FILESYSTEM and SFGAO_FILESYSANCESTOR attributes, regardless of the value returned by CDN_INCLUDEITEM.... and this looks to be working. Don't you have something in the underlying framework that sets the return value to true regardless what you do?

Blight
1st March 2004, 01:12
This is actually from the borland code showing how they implemented it:

CDN_INCLUDEITEM:
if Message.LParam <> 0 then
begin
Include := True;
DoIncludeItem(TOFNotifyEx(POFNotifyEx(Message.LParam)^), Include);
Message.Result := Byte(Include);
end;


The "DoIncludeItem" function is called properly, which calls my function which extract the file names properly, then my function sets include to false. But it still shows the open dialog file list.

I've actually did quite a bit of searching on this and it seems a lot of people have asked about this issue but never got a reply.

This seems to be effecting non-delphi users as well:
http://groups.google.com/groups?q=CDN_INCLUDEITEM&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=60bce9c7.0401230543.31586d5e%40posting.google.com&rnum=4

BlackSun
3rd March 2004, 19:46
Originally posted by Blight
Gabest:
Anything special you need to do for the CDN_INCLUDEITEM callback to work, I'm setting the result, but it doesn't seem to be making any difference, all files appear on the dialog regardless.

Sadly I'm experimenting the same problem. IncludeItem sounded like the solution but unfortunately it's not filtering at all even if you always return false.

Blight
3rd March 2004, 21:00
BlackSun:
I think the solution is to find the listing component and then remove the items manually. It's not too simple I'm afraid.

I don't see how Gabest's system works (I haven't in actuality checked that it really does) as even code I found on some microsoft Q&A section seem to imply that it won't work.

gabest
3rd March 2004, 21:18
http://cvs.sourceforge.net/viewcvs.py/guliverkli/guliverkli/src/apps/mplayerc/OpenDlg.cpp?rev=1.13&view=auto

See COpenFileDialog::OnNotify

Blight
3rd March 2004, 23:25
Gabest:
My code is identical... it's quite possible that your mask in the filters value is cropped at a point other than a "*", in which case your filters will partially filter the content.

You should try putting 1 file of each extension in a directory and see if it actually filters them all properly.