剑指 Offer 14- II. 剪绳子 II
Posted taoyuxin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 14- II. 剪绳子 II相关的知识,希望对你有一定的参考价值。
介绍 几天前,我想开始创建一个图标编辑器应用程序来利用我IconLib图书馆。 我创建了我的主要形式,我想“我要从哪里开始”。然后,我决定创建a 与开放的功能菜单。我认为开放特性之前,应该有一个预览屏幕看到图标打开它。 如果你正在读这一页,可能是因为你知道。net OpenFileDialog类,但它不能定制。这种控制的目的是允许您添加一些功能OpenFileDialog。net类。你不能定制的主要原因。net是因为班上OpenFileDialog声明密封这意味着你不能继承它。如果你去基类FileDialog,它将允许您继承它,但是有一个内部抽象方法“RunFileDialog”。因为它是内部和抽象,它只允许继承里面相同的装配。 有多少次你想把一些额外的控制OpenFileDialog控制和你不能… 寻找。net代码时,我发现他们使用MFC的地方,但没有为。net。OpenFileDialog不是本机在。net实现,相反,它使用了一个Win32 API“GetOpenFileName”。 MSDN 在这一点上,我有三个选择: 从头开始创建自己的OpenFileDialog。 创建我自己的OpenFileDialog重用资源,(使用API“GetOpenFileName”和提供自己的模板)。 黑客。net OpenFileDialog并添加我需要的功能。 选项(一)对我来说不是一个选择,因为它可能需要大量的开发时间,当我有更多的事情要做。后,产品完成后,我可以检查它。下一个选项需要我提供我自己的模板使用Win32 API调用和资源。选项(c)是更可行的选择在这个时间;不认为这是一个糟糕的黑客,黑客基本上是当你想要控制做一些额外的功能,你必须从一个不同的线程或进程。 因为我喜欢挑战,我决定“黑客”OpenFileDialog类来创建自己的定制的控制。 它可以帮你做什么 我可以砍控制去做我需要会这样,但我遇到了这个问题很多次从。net 1.0,没有人到目前为止已经有一个解决方案,所以我决定创建一个接口控制,它可用于不同的应用程序。 同时,我想创造一些东西,不需要更改或添加代码当前项目,并能够添加多个控件不知道它们是如何工作的详细信息;它需要一个独立的控制一样,可以添加其他的IDE。 我创建了这个控件,我称之为“OpenFileDialogEx”。 我怎么做吗? OpenFileDialogEx想象成一个抽象类:我不让这类抽象的唯一原因是因为VS IDE不能创建一个抽象类的一个实例,避免了呈现在屏幕上。 你可以使用OpenFileDialogEx类但毫无意义,因为它不包含任何额外的功能,只是一个空的用户控件。 所以你必须继承OpenFileDialogEx来创建您自己的自定义版本的打开文件对话框。 继承OpenFileDialogEx之后,您已经创建了一个自定义控件,您可以添加任何控制,你可以添加额外的按钮、面板、或一组框。基本上,它是一个容器控件;后来这个容器将“追加”。net OpenFileDialog动态对象。 有三个额外的属性,三种方法,和两个事件控制,不同于任何用户控件。 DefaultViewMode: 这个属性允许您选择哪种观点OpenFileDialog应该开始;默认情况下,它使用“细节视图”打开。在这里你可以指定一个不同的默认视图像图标,列表,缩略图,细节等。 StartLocation: 这个属性告诉如果创建的控制应堆放在右边,底部,或在经典OpenFileDialog后面。通常情况下,此属性将用于扩大OpenFileDialog水平。如果相反,你需要添加额外的控制当前OpenFileDialog,那么您可以指定“没有”和控制内部OpenFileDialogEx将共享相同的客户区与原OpenFileDialog。 OpenDialog: 此属性内部的嵌入式OpenFileDialog控制。在这里你可以设置标准属性InitialDir, AddExtension,过滤器等。 OpenFileDialog违约是可调整大小的,OpenFileDialogEx将帮助您自动;用户控制“OpenFileDialogEx”将自动调整大小。当用户扩展或收缩的窗口,它取决于StartLocation属性上的表现也不同。 StartLocation 右:用户控件将垂直缩放。 底部:用户控件将调整水平。 没有:用户控件将水平和垂直大小。 基本上,当你一个你必须设置每个控件的锚定属性,然后当用户调整OpenFileDialog窗口的大小时,你可以控制控件的位置。 例如,要进行图像预览,你可以在右侧设置开始位置,在继承的OpenFileDialogEx中添加一个PictureBox,并将PictureBox的锚定属性设置为左、上、右、下;这将在用户调整OpenFileDialog大小时动态调整图片框的大小。 这些方法是虚拟方法,您将覆盖它们以与原始OpenFileDialog交互。 OnFileNameChanged () 每当用户单击视图中的任何文件时,都会调用此方法。 OnFolderNameChanged () 每当用户更改OpenFileDialog中任何控件中的文件夹时,都会调用此方法。 OnClosing () 这个方法在OpenFileDialog关闭时被调用,这对于释放分配的资源很有用。 这两个事件是FileNameChanged和FolderNameChanged,这些事件是由它们各自的虚拟方法“OnFileNameChanged”和“OnFolderNameChanged”触发的。我建议重写方法,而不是使用事件,因为它是干净的代码,而且它没有另一层间接。 it 是怎么做的? 第一个问题是OpenFileDialog是一个模态对话框。这意味着您基本上无法获得窗口的句柄,因为当您调用ShowDialog()时,只要OpenFileDialog是打开的,您就无法控制程序流。 获得OpenFileDialog句柄的一种方法是覆盖窗体上的WndProc方法,并注意消息。当OpenFileDialog被创建时,所有者表单将收到一些消息,如WM_IDLE, WM_ACTIVATE, WM_NC_ACTIVATE,等等。这些消息将使用OpenFileDialog窗口的句柄来设置参数lParam。 如您所见,这需要重写WndProc方法。有些开发人员甚至不知道WndProc的存在,所以我想避免它。也。我注意到一些MDI窗口打开OpenFileDialog的问题。 然后我所做的是,当ShowDialog()被调用时,它在屏幕外创建了一个虚拟表单并隐藏了它,这个表单将负责打开OpenFileDialog并获取OpenFileDialog窗口句柄。 起初,它监听了WM_IDLE消息,但问题是,当消息发送时,已经太晚了,窗口被创建并显示在屏幕上。尽管如此,您仍然可以更改内容,但用户将看到原始OpenFileDialog和定制版本之间的屏幕上有一个小的闪烁。 相反,我们可以采取消息WM_ACTIVATE发生在OpenDialog显示在屏幕上。 到目前为止,它得到了句柄并准备好显示了,现在呢? 它将如何改变OpenFileDialog窗口的属性? 这时就出现了方便的。net NativeWindow, NativeWindow是一个窗口包装器,它处理关联到它的句柄发送的消息。它创建一个NativeWindow并将OpenFileWindow句柄关联到它。从这里开始,每个发送到OpenFileWindow的消息都将被重定向到我们自己的WndProc方法,我们可以取消、修改或者让它们通过。 在我们的WndProc中,我们处理消息WM_WINDOWPOSCHANGING。如果打开对话框正在打开,那么我们将根据用户设置的StartLocation改变原始的水平或垂直大小。它将增加要创建的窗口的大小。这只在控件打开时发生一次。 此外,我们将处理消息WM_SHOWWINDOW。在这里,原始OpenFileDialog中的所有控件都被创建,我们将把我们的控件“追加”到open file对话框中。这是通过调用Win32 API的“SetParent”来实现的。这个API允许您更改父窗口。然后,基本上它所做的是将我们的控件“附加”到它设置的位置中的原始OpenFileDialog,这取决于StartLocation属性的值。 它的优点是我们仍然可以完全控制附加到OpenFileDialog窗口的控件。这意味着我们可以接收事件,调用方法,并对这些控件做任何我们想做的事情。 同样,在初始化过程中,我们将获得原始OpenFileDialog中每个控件的窗口句柄。这再次允许创建。net NativeWindows来处理每个控件中的消息。 现在一切都准备好了,当用户点击ListView时,我们如何观察消息呢? 起初,我试图处理来自ListView本身的消息,为它创建一个本地窗口,但问题是,每次用户更改文件夹或单击不同的视图,处理程序被销毁,我们必须重新创建处理程序。 用MS Spy分析FileOpenDialog内的所有窗口,我们可以注意到FileOpenDialog内还有另一个文件对话框窗口,很可能是FileOpenDialog的基本窗口。检查MSDN文档中,我们看到在FileOpenDialog上所做的每一个动作都会触发一个WM_NOTIFY消息来填充一个OFNOTIFY结构;这个结构体包含所做操作的代码,其中两个操作是CDN_SELCHANGE和CDN_FOLDERCHANGE。 MSDN 当用户与文件夹组合框或列表视图交互时,将调用它们。然后,首先我获得了基文件窗口的句柄,并从这个句柄创建了一个NativeWindow。这允许处理消息WM_NOTIFY来分析OFNOTIFY结构和进程CDN_SELCHANGE和CDN_FOLDERCHANGE。当这个窗口处理这些消息时,它们被转发到OpenFileDialogEx控件的方法OnFileNameChanged和OnFolderNameChanged。 另一种方法是在关闭FileOpenDialog窗口时进行拦截。起初,我使用了消息WM_CLOSE,它工作,但后来我发现,这条消息没有被调用时,用户双击一个文件在列表视图。通过观察FileOpenDialog产生的消息,我发现我可以使用WM_IME_NOTIFY消息。当FileOpenDialog被关闭时,该消息以IMN_CLOSESTATUSWINDOW的wParam值发送;下面是我们对OnClosingDialog()方法的调用。 现在,当用户调整FileOpenDialog大小时,如何调整UserControl的大小;这是通过处理消息WM_WINDOWPOSCHANGING;在这里,我们指定相对于FileOpenDialog大小更改控件的大小。 作为一个重要的细节,当OpenFileWindow关闭时,它必须恢复到我们打开它时的原始大小,这是可能的,因为OpenFileWindow记住了最后的位置/大小。如果我们不这样做,每次打开OpenFileDialog时,它将增加大小,使其越来越大。 结论 我在Windows XP上进行了测试,它运行得很好,我没有机会在Windows 2000/2003或Vista等不同的操作系统上进行测试,但它应该可以正常工作,没有问题。我不认为它将工作在Windows 95/98,因为我设置的结构大小只匹配WinNT操作系统。如果您有任何评论或发现bug,请告诉我,我将更新控件。 历史 版本1.0.1 (11/14/2006) 将DialogResult状态转发给调用者。 代码优化。 使用带有特殊标志的SetWindowsPos API来调整控件的大小,而不是直接分配大小来减少闪烁。 控件大小调整现在在WM_SIZING中完成;这修正了在鼠标按钮被释放之前,控件没有为最后一次更新调整大小的错误。 初始版本1.0.0(2006年7月14日) 本文转载于:http://www.diyabc.com/frontweb/news5115.html
以上是关于剑指 Offer 14- II. 剪绳子 II的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode]剑指 Offer 14- II. 剪绳子 II
剑指 Offer 14- II. 剪绳子 II(数学推导,贪心)
LeetCode(剑指 Offer)- II. 剪绳子 II