|
The NMHDR.Code has changed in Windows Vista.
If you use "If nmhdr.Code = CDN_FILEOK" block in the HookProc function, this solution will not work.
So, comment out the "If" block and set m_EncodingType on every WM_NOTIFY. (Or use another nmhdr.Code on various operating system, but MSDN says that these values may change again.)
|
|
|
|
|
Hi,
I need to avoid user to type more than 100 characters in file name control.
Also want to prohibit user to type some special characters i.e. user must use only alphanumeric characters.
Can I get access to this File Name combo?
|
|
|
|
|
Friend Const fdlgEdtFileName As UInteger = &H47C
Dim parent As Integer = GetParent(hwnd)
Dim fileNameEdit As Integer = GetDlgItem(parent, fdlgEdtFileName)
SetWindowText(CType(fileNameEdit, IntPtr), "modified name of the file")
|
|
|
|
|
|
Hi,
This is great work! Just a quick query to see if you can answer or point me in the right direction though. I would like to decrept a encrepted html file and dont want to save it any where in local disc for the maintaininig security purpose displying in web control from buffer directly,
NOW MY PROBLEM IS IT IS NOT FOLLOWING CSS APPLIED ON IT ,,,
HOW CAN I add this CSS WITH DECREPTED FILE
PLZ HELP ME,,,,,,
|
|
|
|
|
Thank you for this example. I'm learning quite a bit!
I'm trying to run this example under Vista/VS2008/.NET 2.0. I can change the title of the dialog but the label nor the dropdown appears.
Any one here have issues with this example running under Vista?
|
|
|
|
|
Hi,
This is great work! Just a quick query to see if you can answer or point me in the right direction though. I would like to extend the SaveFileDialog and OpenFileDialog for applications (Word, Excel, etc) so am trying to write something that runs in the background and does a similar job to what you've done here. Any suggestions?
Many thanks
|
|
|
|
|
I need to place the textbox infront of the filename combo and for that i need to get the pos which is in a binary format, how can i do that
|
|
|
|
|
This is the best thing ever. That savefiledialog has been pissing me off with multi-threaded applications.
This has solved that. Thank you.
Have you made any extentions to this?
|
|
|
|
|
I extended the save dialog with a button, that opens a new form by clicking on it. In this new form the user can generate a filename with a few clicks on some checkboxes (e.g. date, date of file, name of file and so on). When the user than exits the form the generated filename should appear in the filename control of the save dialog. The problem is to write a string via wm_settext in the filename control. I would be glad if you can give me a hint how to do this.
with kind regards - zardoz
|
|
|
|
|
Are there any special resource usage considerations? I've taken ideas from this code and put them into a component. Next, I want to create a new Dispose method that cleans up resources for the SaveFileDialog, so I can use it in a using clause like I do my other dialogs. What would you suggest I do in the Dispose method?
|
|
|
|
|
Basically, should I be calling DestroyWindow( ofn.hInstance ) at some point?
|
|
|
|
|
How to make the extended save file dialog resizable.? I noticed that the save file dialog created with GetSaveFileName win API is not resizable. Any thought? Thanks.
|
|
|
|
|
|
Hi all,
how can i find a dialog item id needed by GetDlgItem()?
Thanks,
Yuliyan Fasev
|
|
|
|
|
For some strange reason the C# code is converting | (124) to char 92, instead of 0 (unless the C# to VB.net converter I used did that - I had to fix various things by hand anyway)
Microsoft MVP J# 2004-2007
Borland "Spirit of Delphi"
QuickTime, ActiveX, VCL, .NET, Robotics
http://www.kagi.com/birbilis
http://birbilis.spaces.live.com
|
|
|
|
|
'20070325: George Birbilis (birbilis@kagi.com)
'Converted sample at http://www.codeproject.com/csharp/GetSaveFileName.asp from C# to VB.net
'Added "Encoding" property
'Added more "EncodingTypes" and respective dropdown strings
'Fixed filter to use "Chr" instead of "ChrW" and convert "|" [Chr(124)] to Chr(0) instead of ChrW(92)
' Example of use:
'
' Dim ofd As SaveFileDialogWithEncoding = New SaveFileDialogWithEncoding
' ofd.DefaultExt = "sql"
' ofd.EncodingType = EncodingTypes.UTF8
' ofd.Filter = "SQL files (*.sql)|*.sql|All files (*.*)|*.*"
' If (ofd.ShowDialog = DialogResult.OK) Then
' MessageBox.Show(String.Format("Name={0}, Encoding={1}", ofd.FileName, ofd.EncodingType))
' End If
Imports System.Text
Imports System.Text.Encoding
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports System.Runtime.InteropServices
Public Class SaveFileDialogWithEncoding
Inherits Component
#Region "Enums"
'note the order of these is important
Public Enum EncodingTypes
ANSI = 0
UTF8
UTF16
UTF7
UTF32
UNKNOWN
End Enum
#End Region
#Region "Fields"
Protected Encodings As System.Text.Encoding() = New System.Text.Encoding() {ASCII, UTF8, Unicode, UTF7, UTF32}
Private m_LabelHandle As Integer = 0
Private m_ComboHandle As Integer = 0
Private m_Filter As String = ""
Private m_DefaultExt As String = ""
Private m_FileName As String = ""
Private m_EncodingType As EncodingTypes
Private m_ActiveScreen As Screen
#End Region
#Region "Constants"
Private Const OFN_ENABLEHOOK As Integer = 32
Private Const OFN_EXPLORER As Integer = 524288
Private Const OFN_FILEMUSTEXIST As Integer = 4096
Private Const OFN_HIDEREADONLY As Integer = 4
Private Const OFN_CREATEPROMPT As Integer = 8192
Private Const OFN_NOTESTFILECREATE As Integer = 65536
Private Const OFN_OVERWRITEPROMPT As Integer = 2
Private Const OFN_PATHMUSTEXIST As Integer = 2048
Private Const SWP_NOSIZE As Integer = 1
Private Const SWP_NOMOVE As Integer = 2
Private Const SWP_NOZORDER As Integer = 4
Private Const WM_INITDIALOG As Integer = 272
Private Const WM_DESTROY As Integer = 2
Private Const WM_SETFONT As Integer = 48
Private Const WM_GETFONT As Integer = 49
Private Const CBS_DROPDOWNLIST As Integer = 3
Private Const CBS_HASSTRINGS As Integer = 512
Private Const CB_ADDSTRING As Integer = 323
Private Const CB_SETCURSEL As Integer = 334
Private Const CB_GETCURSEL As Integer = 327
Private Const WS_VISIBLE As UInteger = 268435456
Private Const WS_CHILD As UInteger = 1073741824
Private Const WS_TABSTOP As UInteger = 65536
Private Const CDN_FILEOK As Integer = -606
Private Const WM_NOTIFY As Integer = 78
#End Region
#Region "Properties"
Public Property DefaultExt() As String
Get
Return m_DefaultExt
End Get
Set(ByVal value As String)
m_DefaultExt = value
End Set
End Property
Public Property Filter() As String
Get
Return m_Filter
End Get
Set(ByVal value As String)
m_Filter = value
End Set
End Property
Public Property FileName() As String
Get
Return m_FileName
End Get
Set(ByVal value As String)
m_FileName = value
End Set
End Property
Public Property EncodingType() As EncodingTypes
Get
Return m_EncodingType
End Get
Set(ByVal value As EncodingTypes)
m_EncodingType = value
End Set
End Property
Public Property Encoding() As Encoding
Get
Return Encodings(m_EncodingType)
End Get
Set(ByVal value As Encoding)
Dim i As Integer = 0
For Each enc As Encoding In Encodings
If enc.Equals(value) Then
m_EncodingType = CType(i, EncodingTypes)
Exit Property
End If
Next enc
m_EncodingType = EncodingTypes.UNKNOWN
End Set
End Property
#End Region
#Region "Methods"
<DllImport("Comdlg32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function GetSaveFileName(ByRef lpofn As OPENFILENAME) As Boolean
End Function
<DllImport("Comdlg32.dll")> _
Private Shared Function CommDlgExtendedError() As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function SetWindowPos(ByVal hWnd As Integer, ByVal hWndInsertAfter As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function GetWindowRect(ByVal hWnd As Integer, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function GetParent(ByVal hWnd As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function SetWindowText(ByVal hWnd As Integer, ByVal lpString As String) As Boolean
End Function
<DllImport("user32.dll")> _
Private Overloads Shared Function SendMessage(ByVal hWnd As Integer, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Overloads Shared Function SendMessage(ByVal hWnd As Integer, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function DestroyWindow(ByVal hwnd As Integer) As Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function GetDlgItem(ByVal hDlg As Integer, ByVal nIDDlgItem As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function CreateWindowEx(ByVal dwExStyle As Integer, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As UInteger, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hWndParent As Integer, ByVal hMenu As Integer, ByVal hInstance As Integer, ByVal lpParam As Integer) As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function ScreenToClient(ByVal hWnd As Integer, ByRef lpPoint As POINT) As Boolean
End Function
Private Function HookProc(ByVal hdlg As Integer, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Select Case (msg)
Case WM_INITDIALOG
'we need to centre the dialog
Dim sr As Rectangle = m_ActiveScreen.Bounds
Dim cr As RECT = New RECT
Dim parent As Integer = GetParent(hdlg)
GetWindowRect(parent, cr)
Dim x As Integer = CInt((sr.Right + (sr.Left - (cr.Right - cr.Left))) / 2)
Dim y As Integer = CInt((sr.Bottom + (sr.Top - (cr.Bottom - cr.Top))) / 2)
SetWindowPos(parent, 0, x, y, (cr.Right - cr.Left), ((cr.Bottom - cr.Top) + 32), SWP_NOZORDER)
'we need to find the label to position our new label under
Dim fileTypeWindow As Integer = GetDlgItem(parent, 1089)
Dim aboveRect As RECT = New RECT
GetWindowRect(fileTypeWindow, aboveRect)
'now convert the label's screen co-ordinates to client co-ordinates
Dim point As POINT = New POINT
point.X = aboveRect.Left
point.Y = aboveRect.Bottom
ScreenToClient(parent, point)
'create the label
Dim labelHandle As Integer = CreateWindowEx(0, "STATIC", "mylabel", (WS_VISIBLE _
Or (WS_CHILD Or WS_TABSTOP)), point.X, (point.Y + 12), 200, 100, parent, 0, 0, 0)
SetWindowText(labelHandle, "&Encoding:") 'should show with same encoding as system dialog or not show label at all
Dim fontHandle As Integer = SendMessage(fileTypeWindow, WM_GETFONT, 0, 0)
SendMessage(labelHandle, WM_SETFONT, fontHandle, 0)
'we now need to find the combo-box to position the new combo-box under
Dim fileComboWindow As Integer = GetDlgItem(parent, 1136)
aboveRect = New RECT
GetWindowRect(fileComboWindow, aboveRect)
point = New POINT
point.X = aboveRect.Left
point.Y = aboveRect.Bottom
ScreenToClient(parent, point)
Dim rightPoint As POINT = New POINT
rightPoint.X = aboveRect.Right
rightPoint.Y = aboveRect.Top
ScreenToClient(parent, rightPoint)
'we create the new combobox
Dim comboHandle As Integer = CreateWindowEx(0, "ComboBox", "mycombobox", (WS_VISIBLE _
Or (WS_CHILD _
Or (CBS_HASSTRINGS _
Or (CBS_DROPDOWNLIST Or WS_TABSTOP)))), point.X, (point.Y + 8), (rightPoint.X - point.X), 100, parent, 0, 0, 0)
SendMessage(comboHandle, WM_SETFONT, fontHandle, 0)
'and add the encodings we want to offer
SendMessage(comboHandle, CB_ADDSTRING, 0, "ANSI")
SendMessage(comboHandle, CB_ADDSTRING, 0, "Unicode (UTF-8)")
SendMessage(comboHandle, CB_ADDSTRING, 0, "Unicode (UTF-16)")
SendMessage(comboHandle, CB_ADDSTRING, 0, "Unicode (UTF-7)")
SendMessage(comboHandle, CB_ADDSTRING, 0, "Unicode (UTF-32)")
SendMessage(comboHandle, CB_SETCURSEL, CType(m_EncodingType, Integer), 0)
'remember the handles of the controls we have created so we can destroy them after
m_LabelHandle = labelHandle
m_ComboHandle = comboHandle
Case WM_DESTROY
'destroy the handles we have created
If (m_ComboHandle <> 0) Then
DestroyWindow(m_ComboHandle)
End If
If (m_LabelHandle <> 0) Then
DestroyWindow(m_LabelHandle)
End If
Case WM_NOTIFY
'we need to intercept the CDN_FILEOK message
'which is sent when the user selects a filename
Dim nmhdr As NMHDR = CType(Marshal.PtrToStructure(New IntPtr(lParam), GetType(NMHDR)), NMHDR)
If (nmhdr.Code = CDN_FILEOK) Then
'a file has been selected
'we need to get the encoding
m_EncodingType = CType(SendMessage(m_ComboHandle, CB_GETCURSEL, 0, 0), EncodingTypes)
End If
End Select
Return 0
End Function
Public Function ShowDialog() As DialogResult
'set up the struct and populate it
Dim ofn As OPENFILENAME = New OPENFILENAME
ofn.lStructSize = Marshal.SizeOf(ofn)
ofn.lpstrFilter = (m_Filter.Replace("|", Microsoft.VisualBasic.Chr(0)) + Microsoft.VisualBasic.Chr(0))
ofn.lpstrFile = (m_FileName + New String(Microsoft.VisualBasic.Chr(32), 512))
ofn.nMaxFile = ofn.lpstrFile.Length
ofn.lpstrFileTitle = (System.IO.Path.GetFileName(m_FileName) + New String(Microsoft.VisualBasic.Chr(32), 512))
ofn.nMaxFileTitle = ofn.lpstrFileTitle.Length
ofn.lpstrTitle = "Save file as"
ofn.lpstrDefExt = m_DefaultExt
'position the dialog above the active window
ofn.hwndOwner = Form.ActiveForm.Handle
'we need to find out the active screen so the dialog box is
'centred on the correct display
m_ActiveScreen = Screen.FromControl(Form.ActiveForm)
'set up some sensible flags
ofn.Flags = (OFN_EXPLORER _
Or (OFN_PATHMUSTEXIST _
Or (OFN_NOTESTFILECREATE _
Or (OFN_ENABLEHOOK _
Or (OFN_HIDEREADONLY Or OFN_OVERWRITEPROMPT)))))
'this is where the hook is set. Note that we can use a C# delegate in place of a C function pointer
ofn.lpfnHook = New OFNHookProcDelegate(AddressOf HookProc)
'if we're running on Windows 98/ME then the struct is smaller
If (System.Environment.OSVersion.Platform <> PlatformID.Win32NT) Then
ofn.lStructSize = (ofn.lStructSize - 12)
End If
'show the dialog
If Not GetSaveFileName(ofn) Then
Dim ret As Integer = CommDlgExtendedError()
If (ret <> 0) Then
Throw New ApplicationException(("Couldn't show file open dialog - " + ret.ToString))
End If
Return DialogResult.Cancel
End If
'Birb-start
Dim oldFilename As String = m_FileName
m_FileName = ofn.lpstrFile
Dim cancelCheck As New CancelEventArgs()
RaiseEvent FileOK(Me, cancelCheck)
If cancelCheck.Cancel Then
m_FileName = oldFilename 'restore filename since dialog was canceled
Return DialogResult.Cancel
Else
Return DialogResult.OK
End If
'Birb-end
End Function
Public Delegate Function OFNHookProcDelegate(ByVal hdlg As Integer, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
#End Region
#Region "Structures"
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Private Structure OPENFILENAME
Public lStructSize As Integer
Public hwndOwner As IntPtr
Public hInstance As Integer
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrFilter As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrCustomFilter As String
Public nMaxCustFilter As Integer
Public nFilterIndex As Integer
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrFile As String
Public nMaxFile As Integer
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrFileTitle As String
Public nMaxFileTitle As Integer
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrInitialDir As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrTitle As String
Public Flags As Integer
Public nFileOffset As Short
Public nFileExtension As Short
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpstrDefExt As String
Public lCustData As Integer
Public lpfnHook As OFNHookProcDelegate
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpTemplateName As String
'only if on nt 5.0 or higher
Public pvReserved As Integer
Public dwReserved As Integer
Public FlagsEx As Integer
End Structure
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
Private Structure POINT
Public X As Integer
Public Y As Integer
End Structure
Private Structure NMHDR
Public HwndFrom As Integer
Public IdFrom As Integer
Public Code As Integer
End Structure
#End Region
#Region "Events"
Public Event FileOK(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) 'Birb
#End Region
End Class
http://www.kagi.com/birbilis
|
|
|
|
|
The SaveFileDialogWithEncoding example is great. However, the look and feel are "old style" -- in other words, the buttons and controls don't have the new "XP look" (i.e. rounded buttons, etc.). It's probably a flag setting in one of the fields in the OPENFILENAME structure and I'm looking into that. I was just wondering if you (or anyone else) had any insight to solving that problem.
Thanks for a great article and sample.
Regards,
Roy
_____________
Roy H. Berger
roybrew@att.net
|
|
|
|
|
Never mind -- figured it out. Before you instantiate the form object you need to call Application.EnableVisualStyles() like so:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
Regards,
Roy
_____________
Roy H. Berger
roybrew@att.net
|
|
|
|
|
Hi
This is chandu.Really this article is very cool.Can i know how to add some more controls like check box,text box etc..,to the dialog box
Thanks in advance
|
|
|
|
|
Where are the control IDs defined? I'm trying to find the control id to aid in extending the print dialog.
http://www.thesimpsonsquotes.com/
|
|
|
|
|
you could use WinSight maybe or similar tool
Microsoft MVP J# 2004-2007
Borland "Spirit of Delphi"
QuickTime, ActiveX, VCL, .NET, Robotics
http://www.kagi.com/birbilis
http://birbilis.spaces.live.com
|
|
|
|
|
Is it possible to place an own control (written in C#) into the file dialog?
|
|
|
|
|
Yes,
Declare:
[DllImport("user32.dll")]
static extern int SetParent(int HWNDChild, int HWNDParent);
In WM_INITDIALOG, comment out code to CreateWindowEx for COMBO, add following:
//we create the new combobox
_box = new ComboBox();
SetParent(_box.Handle.ToInt32(), parent);
_box.Location = new Point(point.X, point.Y+8);
_box.Size = new Size(aboveRect.Right - aboveRect.Left, 100);
_box.Items.AddRange(new object[] { "UTF-8", "UTF-8 with preamble", "Unicode", "ANSI"});
_box.DropDownStyle = ComboBoxStyle.DropDownList;
_box.SelectedIndex = 0;
In WM_DESTROY:
_box.Dispose();
In WM_NOTIFY:
m_EncodingType = (EncodingType)_box.SelectedIndex;
_________________
Stuart Carnie
|
|
|
|
|
I want to add a textbox rather than a combo, so I was excited when I saw Stuart's comment. For some reason, it won't draw my textbox until I mouse over the 87 pixels of the dialog where the TextBox should appear. After that, it does draw. I can tell it is the first 87 pixels because I made the TextBox longer and saw the dialog drew the control that extended beyond the first 87 pixels.
I tried adding _TextBox.Refresh to the WM_NOTIFY section. This immediately painted the client area of the TextBox, but not the border. The border was only drawn after I moused over the TextBox.
Here is the code I'm using to create the TextBox. Should there be any additional code that was not needed for the ComboBox?
private void _CreateTextBox( int parent, RECT aboveRect, POINT point )
{
_TextBox = new TextBox();
SetParent( _TextBox.Handle.ToInt32(), parent );
_TextBox.Location = new Point( point.X, point.Y + 8 );
_TextBox.Size = new Size( aboveRect.Right - ( aboveRect.Left - 50 ), 100 );
}
|
|
|
|
|