Click here to Skip to main content
6,291,124 members and growing! (15,046 online)
Email Password   helpLost your password?
Languages » C# » Windows Forms     Intermediate

Extending the save file dialog class in .NET

By Neil Davidson

Using the GetSaveFileName function to extend the Save File dialog class
C#, Windows, .NET 1.0, Visual Studio, Dev
Posted:24 Aug 2004
Views:110,525
Bookmarked:31 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
24 votes for this article.
Popularity: 5.63 Rating: 4.08 out of 5
1 vote, 4.2%
1

2
3 votes, 12.5%
3
4 votes, 16.7%
4
16 votes, 66.7%
5

Introduction

Sometimes programming is like doing a jigsaw puzzle with a missing corner.

I work at Red Gate Software, the company that produces SQL Compare, which is written in C#. Although C# and the .NET framework enable us to write good code quickly, the combination has its drawbacks. More often than not I find that even though .NET covers 95 percent of the native Windows API, the five percent that�s missing is the five percent I need. This article describes one of these situations.

C# is very good at handling international character support. This means that SQL Compare can handle databases that use diverse character sets. The problem comes when we need to get the T-SQL scripts out of SQL Compare and into other third-party tools.

Tangled web of encoding

There are a number of different ways of saving Unicode data to disk. ASCII encoding doesn�t handle international characters at all � it will only cope with seven-bit values from 0 to 127. UTF-8 encoding is the same as ANSI encoding for seven-bit characters such as A, B, C and D. Other, more exotic, characters are stored as two-, three- or four-byte combinations. Unicode, or UTF-16, encoding normally stores each character as two bytes, although it can occasionally use four bytes. In addition, each encoding type allows a preamble. This consists of two (for UTF-16) or three (UTF-8) bytes written at the start of a file to indicate the encoding of the file.

Not all tools support all encodings. SQL Query Analyzer, for example, supports UTF-16, but not UTF-8 encoded files; if you ask it to open a UTF-8 file it will treat it as ASCII and treat a two-byte international character as two separate characters. If, however, you save files as UTF-16, then editors that are not Unicode-aware will display each two-byte character as two single characters, l i k e t h i s.

Simple solution?

The lack of universal support means that we need to let our users choose the type of encoding they want when saving files to disk. This is where the tricky part starts. .NET provides a SaveFileDialog class that you can normally use to get a filename. Unfortunately, this dialog does not provide a way of asking the user for an encoding. I thought adding this functionality would be a simple matter of inheriting from the SaveFileDialog class and then adding a couple of controls to the dialog. This class is not, however, a simple Windows form. Instead, it uses the Windows GetSaveFileName function to display the save file dialog.

This made things a bit harder. I looked at the MSDN help for the SaveFileDialog class and noticed that there is a protected HookProc method. This lets you hook into the dialog creation process. You should be able to inherit from the class, intercept the appropriate windows messages, and then add the controls onto the form. Unfortunately, the SaveFileDialog class is sealed. This means that you cannot inherit from the class and override the HookProc method.

At this point I did a search through MSDN and the newsgroups. I found a couple of interesting articles by Dino Esposito and some newsgroup postings by Nicholas Paladino that suggested a good approach.

I decided to use the GetSaveFileName from the Windows API. This takes an OPENFILENAME struct. One of the fields of this struct is a hook that expects a function pointer. One of the neat things about .NET interop is the way you can use a managed C# delegate in place of an unmanaged C++ function pointer:

.
.
private delegate int OFNHookProcDelegate(int hdlg, int msg, 
                                         int wParam, int lParam);
.
.
ofn.lpfnHook = new OFNHookProcDelegate(HookProc);
.
.
GetSaveFileName(ref ofn)
.
.
private int HookProc(int hdlg, int msg, int wParam, int lParam)
{
      //function body

}
.
.

When GetSaveFileName is called, the HookProc receives notification messages from the save file dialog box.

I needed to hook into the WM_INITDIALOG message. In the hook I found the location of the standard Save as type: label and combobox and added a new label and combo box for the encoding choices using CreateWindowEx:

int fileTypeWindow=GetDlgItem(parent, 0x441);
RECT aboveRect = new RECT();
GetWindowRect(fileTypeWindow, ref aboveRect);

POINT point=new POINT();
point.X=aboveRect.Left;
point.Y=aboveRect.Bottom;
ScreenToClient(parent, ref point);

int labelHandle=CreateWindowEx(0, "STATIC", "mylabel", 
                               WS_VISIBLE | WS_CHILD | WS_TABSTOP, 
                               point.X, point.Y + 12, 200, 100, parent, 
                               0, 0, 0);
SetWindowText(labelHandle, "&Encoding:");

In addition to intercepting the WM_INITDIALOG message, I needed to intercept the WM_DESTROY and WM_NOTIFY messages to destroy the label and combo box, and to intercept the selection of a file to work out the chosen encoding.

The final dialog box looks like this:

Download the source code

You can download the complete source code for this sample by following the link at the top of this article. Although the sample doesn�t provide all the functionality of the SaveFileDialog class, it should provide a good starting point for you to implement the functionality you need.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Neil Davidson


Member
Neil Davidson is technical director of Red Gate Software (www.red-gate.com), a company that provides simple tools for Microsoft developers, testers and DBAs. He can be reached at neil.davidson@red-gate.com.
Location: United Kingdom United Kingdom

Other popular C# articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 29 (Total in Forum: 29) (Refresh)FirstPrevNext
GeneralHow css can be applied in files stored in Memory Pinmembersushilabhanvar23:16 1 Apr '09  
GeneralThank you - I have a question Pinmemberloumarco6:14 8 Dec '08  
GeneralApplying this to all applications Pinmemberscoulton8913:24 12 Oct '08  
Generalhow can i find a dialog item id needed by GetDlgItem()? PinmemberAjithevn22:58 4 Mar '08  
GeneralAwesome Pinmemberviperjason14:08 29 Feb '08  
QuestionGood stuff, I have a question PinmemberZardoz3:48 17 Nov '07  
QuestionAny resource usage considerations? Pinmemberflipdoubt5:35 9 Nov '07  
QuestionRe: Any resource usage considerations? Pinmemberflipdoubt6:13 9 Nov '07  
Generalresizable file dialog Pinmembertsaik9923:07 17 Jun '07  
GeneralRe: resizable file dialog PinmemberGiorgi Dalakishvili23:39 17 Jun '07  
GeneralDialog items Pinmemberjuliusf6:49 15 May '07  
GeneralReplase "|" with #0, not #92 PinmemberGeorge Birbilis11:02 25 Mar '07  
GeneralVB.net version with FileOK event [modified] PinmemberGeorge Birbilis12:31 20 Mar '07  
GeneralGood stuff, but I have a question. Pinmemberroybrew6:02 27 Oct '06  
GeneralRe: Good stuff, but I have a question. Pinmemberroybrew8:40 27 Oct '06  
Questionvery nice Pinmemberchandu.sanka2:30 8 Sep '06  
GeneralControl Id PinmemberKynanHaas18:16 31 May '06  
GeneralRe: Control Id PinmemberGeorge Birbilis7:34 20 Mar '07  
QuestionC# Control in dialog PinmemberOlaf Gramkow6:42 26 May '06  
AnswerRe: C# Control in dialog PinmemberStuart Carnie20:57 7 Feb '07  
QuestionRe: C# Control in dialog Pinmemberflipdoubt5:24 27 Oct '07  
AnswerRe: C# Control in dialog Pinmemberflipdoubt5:39 27 Oct '07  
GeneralThank you! PinmemberJohnWillemse23:43 17 Jan '06  
GeneralHow save a file Pinmemberitsbijusamuel19:54 12 Apr '05  
GeneralRe: How save a file PinmemberPrincetech17:57 18 Dec '05  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Aug 2004
Editor: Chris Maunder
Copyright 2004 by Neil Davidson
Everything else Copyright © CodeProject, 1999-2009
Web13 | Advertise on the Code Project