DSGraphEdit:.NET 中 Microsoft GraphEdit 的合理翻版






4.93/5 (77投票s)
一个为 .NET 应用程序添加类似 Microsoft GraphEdit 功能的库
引言
DSGraphEdit
是一个库,可以轻松地将类似于 Microsoft 经典的 GraphEdit
的功能添加到您的 .NET 应用程序中。大部分功能已被重新实现,并加入了一些新的特性,以辅助 DirectShow
软件的调试。
背景
GraphEdit
是 DirectShow
SDK(后来移至 Windows SDK)附带的一个实用程序,它是一个用于创建和测试媒体播放过滤器图的可视化工具。GraphEdit
最强大的功能之一是通过 ROT(正在运行对象表)连接到外部应用程序中运行的过滤器图的能力。然而,这样做往往令人沮丧,因为它经常崩溃,并且在连接到远程图时只提供有限的功能。GraphEdit
的另一个缺点是它是闭源的,不能与您自己的软件自由分发。DSGraphEdit
使用 DirectShowLib、Media Foundation .NET(用于增强视频渲染器)和 DaggerLib
。DaggerLib
是一个有助于可视化构建和执行 DAG(有向无环图)以实现基于流的编程的库。这将在后续文章中更详细地介绍。
Using the Code
要在您自己的应用程序中使用 DSGraphEdit
,请将对 lib 目录中的 DaggerLib.DSGraphEdit.dll 文件进行引用,并将命名空间添加到窗体中
//add namespace
using DaggerLib.DSGraphEdit;
DaggerLib.DSGraphedit
提供了三个控件
DSGraphEditPanel
:用于查看和操作过滤器图的画布。DSFiltersPanel
:一个面板,维护系统上注册的DirectShow
过滤器的树状结构。DSGraphEditForm
:一个集成了DSGraphEditPanel
和DSFiltersPanel
的多合一对话框,方便测试。
DSGraphEditPanel
构造 DSGraphEditPanel
DSGraphEditPanel
可以通过四种不同的方式创建
-
// construct a DSGraphEditPanel with an empty IFilterGraph DSGraphEditPanel dsGraphEditPanel = new DSGraphEditPanel();
-
// construct a DSGraphEditPanel from an existing IFilterGraph IFilterGraph myFilterGraph = (IFilterGraph)new FilterGraph(); ... // do something with myFilterGraph ... DSGraphEditPanel dsGraphEditPanel = new DSGraphEditPanel(myFilterGraph);
-
// construct a DSGraphEditPanel from a *.grf file // Grf files are files that are created by GraphEdit or from a call // to DSGraphEditPanel.SaveFilterGraph(string filename). // Also, constructing a DSGraphEditPanel from a grf file should // always be enclosed in a try/catch block because // it may want some filters that are not registered on your system. DSGraphEditPanel dsGraphEditPanel = null; try { dsGraphEditPanel = new DSGraphEditPanel("c:\\somegraphfile.grf"); } catch (Exception ex) { // we failed, show the error MessageBox.Show(ex.Message, "Error loading graph file"); }
-
// attempt connection to a remote graph on the ROT via // the DSGraphEditPanel.ConnectToRemoteGraph static method DSGraphEditPanel dsGraphEditPanel = null; try { dsGraphEditPanel = DSGraphEditPanel.ConnectToRemoteGraph(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error connecting to remote graph"); } ... // do something with your connected graph ... // disconnect from the Remote Graph dsGraphEditPanel.Dispose(); dsGraphEditPanel = null;
DSGraphEditPanel.ConnectToRemoteGraph()
静态
方法会弹出一个对话框,其中包含一个当前在 ROT 中注册的 IFilterGraph
列表,供用户选择。
要断开与远程图的连接,只需调用 Dispose()
方法来释放 DSGraphEditPanel
。此外,与从 *.grf 文件构造类似,ConnectToRemoteGraph
静态方法应始终包含在 try
/catch
块中。
使用 DSGraphEditPanel
DSGraphEditPanel
由三个区域组成
工具栏按钮
运行过滤器图。对应的方法是
DSGraphEditPanel.Play()
。暂停过滤器图。对应的方法是
DSGraphEditPanel.Pause()
。停止过滤器图。对应的方法是
DSGraphEditPanel.Run()
。向前跳过一帧。对应的方法是
DSGraphEditPanel.StepOneFrame()
。同步显示图与过滤器图的内容。如果认为画布的内容不能准确反映过滤器图的当前状态,请使用此按钮。对应的方法是
DSGraphEditPanel.SyncGraphs()
。自动排列显示图中的过滤器。对应的方法是
DSGraphEditPanel.ArrangeNodes()
。断开过滤器图中的所有引脚连接。
将过滤器图保存到 *.grf 文件。这些文件与 Microsoft 的
GraphEdit
兼容。对应的方法是DSGraphEditPanel.SaveFilterGraph(string filename)
。将媒体文件渲染到过滤器图中。对应的方法是
DSGraphEditPanel.RenderMediaFile(string filename)
。将 URL(统一资源定位符)渲染到过滤器图中。对应的方法是
DSGraphEditPanel.RenderURL(string URL)
。提供了多种样式来显示过滤器之间的连接。对应的属性是
DSGraphEditPanel.NoodleStyle
(是的,它们被称为“面条”)Bezier
:简单的贝塞尔曲线Lines
:五段线CircuitBoardCoarse
:所有直角(使用 A* 寻路算法)CircuitBoardFine
:与CircuitBoardCoarse
相同,但允许非直角Ramen
:与CircuitBoardFine
相同,但使用样条曲线而不是直线段
提供了过滤器图的多种操作和视觉样式
- 阴影:过滤器和面条会在画布上投射阴影。对应的属性是
DSGraphEditPanel.DropShadow
。 - 引脚放置:设置过滤器上的引脚是位于内部、外部还是缩进。对应的属性是
DSGraphEditPanel.PinPlacement
。 - 显示引脚名称:将引脚名称绘制在画布上。对应的属性是
DSGraphEditPanel.ShowPinNames
。 - 显示/隐藏时间滑块:设置时间滑块的可见性。对应的属性是
DSGraphEditPanel.ShowTimeSlider
。 - 模态属性:设置过滤器是在模态对话框中显示其属性,还是直接在画布上显示。对应的属性是
DSGraphEditPanel.ModalProperties
。 - 智能连接:设置过滤器图在连接两个引脚时是否添加中间过滤器。对应的属性是
DSGraphEditPanel.ConnectIntelligent
。 - 使用时钟:启用或禁用过滤器图的参考时钟。对应的属性是
DSGraphEditPanel.UseReferenceClock
。
- 阴影:过滤器和面条会在画布上投射阴影。对应的属性是
时间滑块
如果 filterGraph
具有 IMediaSeeking
功能,您可以通过时间滑块设置图的当前播放位置。与 Microsoft 的 GraphEdit
不同,时间滑块显示当前时间(以小时:分钟:秒:帧格式),并允许您设置媒体的开始和结束位置。
画布
Canvas
是过滤器显示为节点并通过面条相互连接的地方。连接引脚就像拖放或点击一样简单。此外,根据过滤器类型的不同,节点可以具有几种不同的属性。
如果 DSGraphEditPanel
被设置为 ModalProprties = false
,点击 按钮将显示/隐藏节点内部过滤器的属性。这样,您可以在画布上同时打开多个过滤器属性。否则,过滤器属性将在模态对话框中显示。查看过滤器属性时,点击 **扫描接口** 按钮将扫描过滤器支持的所有已知
DirectShow
和 Media Foundation 接口,以及注册表中的任何接口,并将它们显示在一个对话框中供您查看。
如果 DSGraphEditPanel
是使用 DSGraphEditPanel()
或 DSGraphEditPanel(string graphFileName)
构造函数创建的,并且过滤器是视频渲染器,则视频将在节点内部显示。要将视频分离到自己的窗口中,请单击“分离视频窗口”按钮 。关闭分离的视频窗口将返回到节点内的视频。此外,如果视频渲染器连接到任何 DVD 导航器过滤器,视频窗口将向导航器发送鼠标事件,从而实现与 DVD 菜单的交互。
与 Microsoft 的 GraphEdit
不同,DSGraphEditPanels
允许您查看和修改 DMO(DirectX 媒体对象)的属性。
DSFiltersPanel
DSFiltersPanel
提供了一个可搜索的 TreeView
,其中包含系统中注册的所有 DirectShow
过滤器。构造 DSFiltersPanel
后,将其 AssociatedGraphPanel
属性设置为当前的 DSGraphEditPanel
。一旦创建了 DSFilterPanel
并将其与 DSGraphEditPanel
关联,您就可以将过滤器拖放到 DSGraphEditPanel
上,双击它们将其添加到关联的 DSGraphEditPanel
中,或者点击“插入过滤器”按钮 。
DSFilterPanel
还提供了一个属性面板,其中包含注册表中找到的所有 FilterData
信息。
图导航器
图导航器提供了当前 DSGraphEditPanel
的小视图,其中有一个指示器显示视口中可见的画布部分。您可以拖动指示器以快速滚动图到新位置。
DSGraphEditForm
DSGraphEditForm
允许您快速查看过滤器图,而无需麻烦地设置 DSGraphEditPanel
/DSFiltersPanel
对或连接到远程图。
// create an arbitrary IFilterGraph
IFilterGraph myFilterGraph = (IFilterGraph)new FilterGraph();
...
// do something with myFilterGraph
...
// create and show the DSGraphEditForm as a modal dialog
DSGraphEditForm dsGraphEditForm = new DSGraphEditForm(myFilterGraph);
dsGraphEditForm.ShowDialog();
// dispose of it
dsGraphEditForm.Dispose();
dsGraphEditForm = null;
简单快捷。
已知问题
为了让 DSGraphEditPanel.ConnectToRemoteGraph()
在 Windows Vista 上正常工作,您需要安装 Windows SDK for Windows Vista 中的 GraphEdit
版本,并注册它附带的 proppage.dll。如果您使用的是旧版 Windows SDK 中的旧版 GraphEdit
,它仍然无法工作。它必须是 Windows SDK for Vista 中的版本。原因是 Microsoft(以其无限的智慧)在 Vista 的 Quartz.dll 中删除了几乎所有的代理/存根对,并将它们全部移到了 proppage.dll 文件中。如果没有注册代理/存根对,Windows 就无法在不同的线程单元之间编组代理。(微软,真可耻。)
历史
- 2007/10/30:
DSGraphEdit
初始发布 - 2007/12/14:版本 1.1
DSGraphEdit
演示现在使用 Weifenluo DockPanel Suite 进行 MDI 风格的多图编辑。- 对
DaggerLib.UI.Windows
的渲染速度进行了重大优化。 - 现在已将
DaggerLib.Core
和DaggerLib.UI.Windows
的完整源代码包含在解决方案中。 - 添加了
GraphNavigator
控件,以便于编辑/浏览大型图。 - 在不显示非模态属性时,引脚名称会绘制在节点内。
- 排列节点 现在会考虑绘制在画布上的引脚名称。
- 当加载包含未连接视频渲染器的图时,
VideoInternalWindow
中的InitVideoWindow
会失败。 VideoInternalWindow
现在支持加载包含 EVR 过滤器的图。SyncGraph
现在会移除/重新路由连接。VideoInternalWindow
会将鼠标位置和鼠标单击事件发送到连接的 DVD 导航器,以便与 DVD 菜单进行交互。- 托管连接到 DVD 导航器的
VideoInternalWindow
的过滤器节点现在具有 DVD 章节按钮。 VideoInternalWindow
现在支持窗口化全屏。- 向
DSGraphEditPanel
添加了CanvasImage
属性,用于检索画布的快照。 - 现在会扫描所有接口,而不仅仅是
DirectShow
接口(引脚和过滤器都支持)。 - 修复了一些在非模态模式下不显示的属性页。
- 2018/1/20:版本 1.2
- 修复了 64 位系统上
DaggerUIGraph.KeyboardProc
的问题 - 在主窗体上添加了 64/32 位运行时指示
- 添加了“作为 32 位运行”的项目
- 许可证更改为 MIT
- 更新了
MediaFoundationNet
和DirectShowLib
的版本
- 修复了 64 位系统上