Proponowane rozwiązanie działa zgodnie z opisem:
oknie dialogowym Zapisz jako plik (stosowanego w tym przykładzie) jest związany z kontroli użytkownika, zwanego CustomSaveFileDialog. Ma tę zaletę, że jest obecny w Toolbox i automatycznie implementuje interfejs IDisposable. Jednak mogłaby to być również prosta klasa C#.
Ta kontrolka ma konstruktor akceptujący dowolną aplikację Kontrolę użytkownika zawierającą wszystkie elementy, które mają się pojawić w oknie dialogowym Plik. Kiedy mam pytanie w prawo, to właśnie jest wymagane.
CustomSaveFileDialog ma następujące właściwości:
- Przyjmowanie arbitralnych Kontrola użytkownika zadokowany w dolnej części pliku Dialog, czyli idą zmiany rozmiaru File Dialog
- Brak szczególnych zachowanie dodatkowych elementów (przyciski, obrazy, pola wyboru pola wyboru itp.) jest konieczne. Działają one normalnie, tak jak w innych oknach .
Jest to kod opisanego klasy:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace customSaveFileDialog
{
public partial class CustomSaveFileDialog : UserControl
{
//https://stackoverflow.com/questions/9665579/setting-up-hook-on-windows-messages
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
const uint WINEVENT_OUTOFCONTEXT = 0;
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
[DllImport("user32.dll")]
private static extern bool GetClientRect(IntPtr hWnd, out RECT rc);
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hwndChild, IntPtr hwndNewParent);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetParent(IntPtr hWnd);
private IntPtr hDlg; // Save As dialog handle
private IntPtr hHook; // Event hook
private IntPtr hCtrl; // App. specific user control handle
UserControl ctrl; // App. specific user control
//Static variable containing the instance object
private static CustomSaveFileDialog customSaveFileDialog;
//public property for the user
//theSaveFileDialog has been added to the control in the designer from the Toolbox
public SaveFileDialog Dlg { get { return theSaveFileDialog; } }
//Event hook delegate
private static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);
/// <summary>
/// Constructor
/// </summary>
/// <param name="ctrl">The User Control to be displayed in the file dialog</param>
public CustomSaveFileDialog(UserControl ctrl)
{
InitializeComponent();
customSaveFileDialog = this;
this.ctrl = ctrl;
hCtrl = ctrl.Handle;
//Setup Hook; for simplicity, hook all possible events from the current process
hHook = SetWinEventHook(1, 0x7fffffff, IntPtr.Zero,
procDelegate, (uint)Process.GetCurrentProcess().Id, 0, WINEVENT_OUTOFCONTEXT);
}
// Hook function
static void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
CustomSaveFileDialog csfdg = customSaveFileDialog;
if (csfdg.hDlg == IntPtr.Zero)
csfdg.hDlg = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "#32770", "Save As");
if (hwnd == csfdg.hDlg)
{
IntPtr hParent = GetParent(csfdg.hCtrl);
//this is done only once
if (!(hParent == csfdg.hDlg))
SetParent(csfdg.hCtrl, csfdg.hDlg); //Bind the user control to the Common Dialog
RECT cliRect;
GetClientRect(csfdg.hDlg, out cliRect);
//Position the button in the file dialog
MoveWindow(csfdg.hCtrl, cliRect.Left + 130, cliRect.Bottom - 55, 500, 60, true);
}
}
}
}
Zasadniczą częścią jest zahaczenie o wydarzeniach okien. Zostało to zaczerpnięte z that post.
Można zauważyć, że funkcja "FindWindowEx" (w WinEventProc) znajduje wszystkie wspólne okna dialogowe (i prawdopodobnie więcej) z tytułem "Zapisz jako". Jeśli to powinno być problemem, konieczne będzie więcej filtrowania, np. Poprzez wyszukiwanie w bieżącym wątku. Taką funkcję wyszukiwania można znaleźć here.
Dodatkowo (nie pokazano w powyższym kodzie) metoda "Usuń" w pliku CustormSaveFileDialog.desinger.cs zawiera funkcję Odłączone z uchwytem hHook jako parametrem.
Oprogramowanie zostało przetestowane w systemie Windows7 w trybie debugowania. Jako test, okno prostych form z przyciskiem został wdrożony:
//Test for the customized "Save As" dialog
private void button1_Click(object sender, EventArgs e)
{
//Arbitrary User Control
myUserControl ctrl = new myUserControl();
using (CustomSaveFileDialog csfdg = new CustomSaveFileDialog(ctrl))
{
csfdg.Dlg.FileName = "test";
//Show the Save As dialog associated to the CustomFileDialog control
DialogResult res = csfdg.Dlg.ShowDialog();
if (res == System.Windows.Forms.DialogResult.OK)
MessageBox.Show("Save Dialog Finished");
}
}
I - jak test - kontrola applicatioin określony użytkownik obsługuje następujące zdarzenia:
using System;
using System.Windows.Forms;
namespace CustomFile
{
public partial class myUserControl : UserControl
{
public myUserControl()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button Clicked");
}
private void pictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("Image Clicked");
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (!checkBox1.Checked)
pictureBox1.Visible = false;
else
pictureBox1.Visible = true;
}
}
}
następujący wynik jest produkowany:

kolejne zdjęcie przedstawia inny zrzut ekranu, File Dialog zmieniany, a pole do wyświetlania obrazu jest odznaczone.

To jest wspólny styl okna dialogowego systemu Windows XP. Jeśli chcesz użyć nowego Visma/7/etc. następnie należy użyć nowego wspólnego okna dialogowego elementu https://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx#customizing. Zobacz także ten artykuł: http://www.codeproject.com/Articles/16678/Vista-Goodies-in-C-Using-the-New-Vista-File-Dialog. –
Tak to wygląda. Został zmieniony po vista. Ale podany link ma kod C++/VC++ i szukam C# .net czy jest jakiś inny link? Dzięki! – user1821499
Czy ktoś może pomóc? Próbowałem dostać się do IFileDialogCustomize przykład C#, ale nie jestem w stanie użyć żadnego z nich. Przykład lub przykład byłby naprawdę pomocny! – user1821499