自定义“保存文件”对话框,使其类似于底层操作系统的“保存”对话框C#
我一直在使用此示例自定义“保存”对话框 这很好,我也可以自定义对话框。但是,我看到自定义对话框没有遵循底层的windows样式。例如,如果我在Windows 7中,对话框将如下所示 这是word中的一个保存对话框,它几乎没有标签之类的选项。但其外观与OS保存对话框相同。 但是,具有上述链接的自定义保存对话框如下所示 为什么它不遵循操作系统提供的功能?有什么办法处理这个问题吗自定义“保存文件”对话框,使其类似于底层操作系统的“保存”对话框C#,c#,windows,winforms,C#,Windows,Winforms,我一直在使用此示例自定义“保存”对话框 这很好,我也可以自定义对话框。但是,我看到自定义对话框没有遵循底层的windows样式。例如,如果我在Windows 7中,对话框将如下所示 这是word中的一个保存对话框,它几乎没有标签之类的选项。但其外观与OS保存对话框相同。 但是,具有上述链接的自定义保存对话框如下所示 为什么它不遵循操作系统提供的功能?有什么办法处理这个问题吗 好的,我做了一些研究,终于可以使用Microsoft.WindowsAPICodePack.Dialogs中的Co
好的,我做了一些研究,终于可以使用Microsoft.WindowsAPICodePack.Dialogs中的CommonSaveFileDialog创建底层的保存对话框(与Windows 7样式匹配)。我安装了WindowsAPI外壳包,并使用CommonSaveFileDialog控件创建了如下内容:
红色标记的控件实际上是这些API中提供的CommonFileDialogLabel/CommonFileDialogTextBox/CommonFileDialogComboBox等。但现在我的问题是,如何将用户控件/自定义控件添加到此控件?我需要完全控制我添加的内容,以便它可以是一个用户控件。任何想法。。请帮助,谢谢。建议的解决方案如下所述: “另存为文件”对话框(在本例中使用)与名为CustomSaveFileDialog的用户控件相关联。它的优点是它存在于工具箱中,并自动实现IDisposable接口。然而,它也可能是一个简单的C#类 此控件具有一个构造函数,该构造函数接受任意特定于应用程序的用户控件,该控件承载将在文件对话框中显示的所有元素。当我答对了问题时,这就是所需要的 CustomSaveFileDialog具有以下属性:
- 接受停靠在文件底部的任意用户控件 对话框,即它们跟随文件对话框的大小调整
- 其他元素(按钮、图像、, 复选框等)是必要的。他们的行为很正常,就像其他人一样 窗户
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);
}
}
}
}
和-以及测试-特定于应用程序的用户控件处理以下事件:
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;
}
}
}
产生以下输出:
下一张图片显示另一个屏幕截图,调整了文件对话框的大小,显示图像的复选框未选中
这是Windows XP常用对话框样式。如果要使用新的Visma/7/etc.样式,则必须使用“新建公用项”对话框。也看这篇文章。是的,这看起来像。它是在vista之后更改的。但是你提供的链接有C++/VC++代码,我在寻找C。.NET有其他的链接吗?谢谢有人能帮忙吗?我试图访问IFileDialogCustomize示例C,但我无法使用其中任何一个。一个示例或例子将非常有用!这是可行的,但是用户控件不能比图片中显示的更大。“另存为类型”和“浏览/隐藏文件夹”链接之间的空间非常小。我的用户控制可能更大,我需要额外的空间。这可能吗?是的,你是对的。所提供的解决方案仅适用于对现有空间内的公共对话框进行少量添加。你可以咨询,这是你在发帖中引用的解决方案的基础,比这里介绍的要复杂得多。简言之,在我看来,微软让我们修补各种各样的pinvoke来定制这样一个对话框是荒谬的。说得好。。谢谢你,乔希。我将看看什么是满足我需求的最佳解决方案。有没有办法处理此窗口的调整大小事件?当我们调整“保存”对话框的大小时,它将越过我的用户控件。。我希望用户控件停留在一个位置(可能带有滚动条)。我尝试了正常的dock/anchor属性,但不起作用。有没有办法更改对话框的背景色?还有最受欢迎的..桌面。。还有名单吗?
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;
}
}
}