I am posting this for two reasons. It may be useful for others that might
need to implement related functionality, and to see if any Windows API gurus can help me understand some interesting nuances and maybe improve the approach. I have two different file formats (ie: file.exa and file.exb) and want users to choose which format they want to save via the file dialog type drop down box. The default behavior of the FileSaveDialog is to not change the extension of the file when the type is changed. I wanted the functionality of the Word or Excel file save dialog where when the type is changed the file extension is updated. After some digging it seemed that this functionality was only available via hooking some code in via a callback. So that is what I did, and after quite a few image crashes I got it working. The first thing I had to do was to edit the OPENFILENAME class <<defineFields method to remove the beFiller message from the lpfnHook field. My first curiosity is why was this marked as filler? Was this a philosophical decision because OA had not tested that element, or was there a technical reason for this? It seems odd to properly define a known field and then make it unusable. After removing beFiller it seems to work fine. This is the method that handles the callback (see further comments bellow): ===================== callBackhWnd: hWnd uMsg: uMsg lp: lp pData: pData "Private - cdemers - 11/14/2005" | dialogView formatCb filenameTb fileName fileTypeIndex extension idFormat idFilename nmHdr | idFormat := 1136. "ID_FORMAT" idFilename := 1152. Transcript nextPutAll: (Array with: uMsg with: hWnd with: lp with: pData) displayString; cr. (uMsg = 78 "WM_NOTIFY") ifTrue: [ nmHdr := NMHDR fromAddress: pData. Transcript nextPutAll: nmHdr displayString; cr. nmHdr code = -607 "CDN_TYPECHANGE" ifTrue: [ "For some reason this message is sent twice, it does not seem to cause a problem though." dialogView := (View fromHandle: hWnd) creationParentView. formatCb := dialogView getItem: idFormat. fileTypeIndex := formatCb sendMessage: 327. "CB_GETCURSEL" extension := (fileTypes at: fileTypeIndex + 1) last. "If there is more than one extension specified for the type get the first." "Since the extensions always start with '.' we skip it." extension := (extension subStrings: $;) first copyFrom: 2. filenameTb := dialogView getItem: idFilename. fileName := filenameTb text. fileName := File change: fileName extension: extension. filenameTb text: fileName]]. ^0 ===================== This is the logged text when run on Windows XP SP2: =========== 78, 16r1A09B4, 0, 12639608 a NMHDR(hwndFrom=4983232 idFrom=0 code=-607) 49263, 16r1A09B4, 1136, 1 78, 16r1A09B4, 0, 12639608 a NMHDR(hwndFrom=4983232 idFrom=0 code=-607) 49263, 16r1A09B4, 1136, 1 78, 16r1A09B4, 0, 12640988 a NMHDR(hwndFrom=4983232 idFrom=0 code=-602) 2, 16r1A09B4, 0, 0 130, 16r1A09B4, 0, 0 ============== My first attempt was to look for a uMsg of 49263 and an lp of 1136 because I knew 1136 was the ID of the file type drop down box. Unfortunately I did not know what 49263 meant, and even more unfortunately on Windows 98 I got a different uMsg of 50467. Does anyone know what this message means? I ultimately decided to look for a uMsg of 78, which I know is WM_NOTIFY and then look for an NMHDR code of -607, which is CDN_TYPECHANGE. However I notice that message gets sent twice, so my code runs twice. While not ideal, it does not seem to be cause any real problems, so I left it that way. Another interesting nuance is that in MitSciEnhancedFileSaveDialog class <<initialize I have to bitOr OFN_ENABLESIZING with the style to get a resizable dialog. For some reason this is not needed with the default implementation. Why? I don't work with low-level Windows API's very often so I have cobbled together a rather limited understanding. If someone with a more comprehensive understanding can suggest a more elegant implementation I am receptive. The package can be downloaded here (Only load this into a test image, it will replace the OPENFILENAME class <<defineFields method, use and experiment at your own risk.): http://www.cjd77.com/smalltalk/temp/MitSciEnhancedFileSaveDialog.pac Comments and suggestions are welcome. Chris |
Christopher J. Demers wrote:
> I am posting this for two reasons. It may be useful for others that might > need to implement related functionality, and to see if any Windows API gurus > can help me understand some interesting nuances and maybe improve the > approach. > I'm long past being a Windows API guru, but I'll try to help anyway. > I have two different file formats (ie: file.exa and file.exb) and want users > to choose which format they want to save via the file dialog type drop down > box. The default behavior of the FileSaveDialog is to not change the > extension of the file when the type is changed. I wanted the functionality > of the Word or Excel file save dialog where when the type is changed the > file extension is updated. After some digging it seemed that this > functionality was only available via hooking some code in via a callback. > So that is what I did, and after quite a few image crashes I got it working. > This behavior doesn't sound like what I remember, so I went digging in MSDN. I found the following information, but haven't tested any of it, so maybe the docs are incorrect in this case, or maybe your situation doesn't fit what it says. (Sorry for any link wrapping) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/aboutcommondialogboxes/openandsaveasdialogboxes.asp says this: "For Explorer-style dialog boxes, the default extension may change if the user selects a different filter. If the user selects a filter whose first pattern is of the form *. xxx (that is, the extension does not include a wildcard character), the dialog box uses xxx as the default extension. This occurs only if you specified a default extension in the lpstrDefExt member of the OPENFILENAME structure. For example, if the user selects the "Source\0*.C;*.CXX\0" filter, the default extension changes to "C". However, if you had defined the filter as "Source\0*.C*\0", the default extension would not change because the extension includes a wildcard." See also the docs for the lpstrDefExt member of the OPENFILENAME structure. I think that if you added separate filter patterns for *.exa and *.exb, set the lpstrDefExt member to 'exa', and set the nFilterIndex member to 1, you'd get the behavior you want. Randy -- Randy Coulman NOTE: Reply-to: address is spam-guarded. Reassemble the following to reply directly: rcoulman at charter dot net |
"Randy Coulman" <[hidden email]> wrote in message
news:j6yff.29956$[hidden email]... > Christopher J. Demers wrote: ... >> I have two different file formats (ie: file.exa and file.exb) and want >> users >> to choose which format they want to save via the file dialog type drop >> down >> box. The default behavior of the FileSaveDialog is to not change the >> extension of the file when the type is changed. I wanted the >> functionality >> of the Word or Excel file save dialog where when the type is changed the >> file extension is updated. After some digging it seemed that this >> functionality was only available via hooking some code in via a callback. >> So that is what I did, and after quite a few image crashes I got it >> working. >> > > This behavior doesn't sound like what I remember, so I went digging in > MSDN. I found the following information, but haven't tested any of it, so > maybe the docs are incorrect in this case, or maybe your situation doesn't > fit what it says. > > (Sorry for any link wrapping) > > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/aboutcommondialogboxes/openandsaveasdialogboxes.asp > > See also the docs for the lpstrDefExt member of the OPENFILENAME > structure. > > I think that if you added separate filter patterns for *.exa and *.exb, > set the lpstrDefExt member to 'exa', and set the nFilterIndex member to 1, > you'd get the behavior you want. Thanks for the info. While I think the information you have found is correct, I believe that it falls short of what I want. It appears to only change the default extension, not the extension of the actual file name selected. It seems that the default extension is only used when the entered file name does not have an extension. This is the code I tried, let me know if I have missed something. ========== fsd := FileSaveDialog new. fsd fileTypes: #(#('File exa (*.exa)' '*.exa') #('File exb (*.exb)' '*.exb')). fsd model: 'test.exa'. fsd winStruct lpstrDefExt: 'exa'. fsd winStruct nFilterIndex: 1. fsd showModal. ========== Notice that the file name defaults to 'test.exa'. If the user selects the *.exb filter I want the extension of the selected file to change to 'exb'. Basically I want it to work the way it does in Word, if you change the filter from *.doc to *.rtf the extension of the file name actually changes. This is something I would have expected to be built into the control, but it does not seem to be. I am happy to be proved wrong though. ;) Chris |
> "Randy Coulman" <[hidden email]> wrote in message
This is completely off-topic. Randy, I didn't see your message that Christopher's replying to. After a bit of digging I found that it's because I have "[hidden email]" in my killfile (probably to block one of the bozos who dump garbarge in the Java newsgroups). I'm not suggesting you should change your email to please me, but you should be aware that you are using an email that is also used by thousands of other people on Usenet. (Google thinks there are over a million posts by "you"...) -- chris |
Free forum by Nabble | Edit this page |