一个软件,不可能只有一个文档界面,会有多个甚至几十二,比如一些浏览器、文档查看等都是多个标签页的形式,在C#中开源的可停靠管理的常用的是Xceed.Wpf.AvalonDock;但是用C/C++开发的开源停靠管理库是没找到,没办法只能自己写一个了。
图1
可停靠管理项目名XPDock,其中所有控件的样式存放在“.bin\layout\Theme\Controls\XPDock.xml”;如图2:
图2
在XPDock控件中,DockingManager为控件主要控件,控件内定义添加视图方法AddView,添加的视图均基于LayoutElement(可被继承);
XPDock中控件的层级关系:
内嵌时:
DockingManager
---------LayoutPanelControl(Document)
-------LayoutDocumentTabControl
-------LayoutElement(可被继承)
---------LayoutAnchorSideControl(Anchor)
-------LayoutAnchorSideTabControl
-------LayoutElement
浮动时:
LayoutFloatingWindow(浮动窗口)
---------LayoutPanelControl(Document)
-------LayoutDocumentTabControl
-------LayoutElement(可被继承)
运行示例图:
图3
代码就不贴了,都是最简介功能的罗列,主要贴一下XPDock中主要控件样式的配置,以DockingManager,LayoutDocumentTabControl和LayoutElement为例如下:
1 <Style TargetType="DockingManager"> 2 <Setter Property="Background" Value="{DynamicResource WindowBackgroundLightBrush}" /> 3 <Setter Proterty="Foreground" value="{DynamicResource WindowForgroundLightBrush}"/> 4 <Setter Property="BorderThickness" Value="0" /> 5 <Setter Property="Margin" Value="2" /> 6 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}" /> 7 <Setter Property="Template"> 8 <Setter.Value> 9 <ControlTemplate TargetType="DockingManager"> 10 <Border Background="{TemplateBinding}" 11 BorderBrush="{TemplateBinding}" 12 BorderThickness="{TemplateBinding}" Padding="0" > 13 <Grid x:Name="PART_DOCKINGROOT"> 14 <Grid> 15 <Grid.ColumnDefinitions> 16 <ColumnDefinition Width="Auto"/> 17 <ColumnDefinition Width="1*"/> 18 <ColumnDefinition Width="Auto"/> 19 </Grid.ColumnDefinitions> 20 <Grid.RowDefinitions> 21 <RowDefinition Height="Auto"/> 22 <RowDefinition Height="Auto"/> 23 <RowDefinition Height="1*"/> 24 <RowDefinition Height="Auto"/> 25 <RowDefinition Height="Auto"/> 26 </Grid.RowDefinitions> 27 <LayoutAnchorSideControl Margin="0" x:Name="PART_TopSidePanel" Background="Blue" Height="100" AnchorSide="Top" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="0"/> 28 <LayoutAnchorSideControl Margin="0" x:Name="PART_TopSideInnerPanel" Background="Blue" Height="100" AnchorSide="InnerTop" Grid.Column="1" Grid.Row="1"/> 29 <LayoutAnchorSideControl Margin="0" x:Name="PART_LeftSidePanel" Background="Yellow" Width="200" AnchorSide="Left" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3"/> 30 <LayoutAnchorSideControl Margin="0" x:Name="PART_RightSidePanel" Background="Red" Width="200" AnchorSide="Right" Grid.Column="2" Grid.Row="1" Grid.RowSpan="3" /> 31 <LayoutAnchorSideControl Margin="0" x:Name="PART_BottomSideInnerPanel" Background="Green" Height="100" AnchorSide="InnerBottom" Grid.Column="1" Grid.Row="3" /> 32 <LayoutAnchorSideControl Margin="0" x:Name="PART_BottomSidePanel" Background="Green" Height="100" AnchorSide="Bottom" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="4" /> 33 <GridSplitter x:Name="PART_TopSidePanelSplitter" Height="3" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="0" Visibility="{Binding Path=Visibility,ElementName=PART_TopSidePanel}"/> 34 <GridSplitter x:Name="PART_TopSidePanelInnerSplitter" Height="3" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="1" Grid.Row="1" Visibility="{Binding Path=Visibility,ElementName=PART_TopSideInnerPanel}"/> 35 <GridSplitter x:Name="PART_LeftSidePaneSplitterl" Width="3" VerticalAlignment="Stretch" HorizontalAlignment="Right" Cursor="SizeWe" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3" Visibility="{Binding Path=Visibility,ElementName=PART_LeftSidePanel}"/> 36 <GridSplitter x:Name="PART_RightSidePanelSplitter" Width="3" VerticalAlignment="Stretch" HorizontalAlignment="Left" Cursor="SizeWe" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="2" Grid.Row="1" Grid.RowSpan="3" Visibility="{Binding Path=Visibility,ElementName=PART_RightSidePanel}"/> 37 <GridSplitter x:Name="PART_BottomSidePanelInnerSplitter" Height="3" VerticalAlignment="Top" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="1" Grid.Row="3" Visibility="{Binding Path=Visibility,ElementName=PART_BottomSideInnerPanel}"/> 38 <GridSplitter x:Name="PART_BottomSidePanelSplitter" Height="3" VerticalAlignment="Top" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="4" Visibility="{Binding Path=Visibility,ElementName=PART_BottomSidePanel}"/> 39 <LayoutPanelControl Margin="0" x:Name="PART_LayoutRootPanel" Grid.Column="1" Grid.Row="2" Background="White"/> 40 </Grid> 41 <LayoutFloatingControl Name="PART_FLOATASIDE" Visibility="Visible" VerticalAlignment="Left" HorizontalAlignment="Stretch" Background="{DynamicResource WindowBorderNormalBrush}"/> 42 <LayoutFloatingControl Name="PART_BOTTOMFLOATSIDE" Visibility="Visible" VerticalAlignment="Stretch" HorizontalAlignment="Bottom" Background="{DynamicResource WindowBorderNormalBrush}"/> 43 </Grid> 44 <!--<ContentPresenter />--> 45 </Border> 46 </ControlTemplate> 47 </Setter.Value> 48 </Setter> 49 </Style> 50 51 52 <Style TargetType="LayoutDocumentTabControl"> 53 <Setter Property="Background" Value="{DynamicResource WindowBackgroundLightBrush}" /> 54 <Setter Proterty="Foreground" value="{DynamicResource WindowForgroundLightBrush}"/> 55 <Setter Property="BorderThickness" Value="1" /> 56 <Setter Property="Margin" Value="0" /> 57 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderNormalBrush}" /> 58 <Setter Property="Template"> 59 <Setter.Value> 60 <ControlTemplate TargetType="LayoutDocumentTabControl"> 61 <Border Background="{TemplateBinding}" 62 BorderBrush="{TemplateBinding}" 63 BorderThickness="{TemplateBinding}" Padding="0" > 64 <Grid x:Name="PART_ROOT" > 65 <Grid.ColumnDefinitions> 66 <ColumnDefinition Width="Auto"/> 67 <ColumnDefinition Width="1*"/> 68 <ColumnDefinition Width="Auto"/> 69 <ColumnDefinition Width="Auto"/> 70 </Grid.ColumnDefinitions> 71 <Grid.RowDefinitions> 72 <RowDefinition Height="Auto"/> 73 <RowDefinition Height="Auto"/> 74 <RowDefinition Height="1*"/> 75 <RowDefinition Height="Auto"/> 76 <RowDefinition Height="Auto"/> 77 </Grid.RowDefinitions> 78 <DockPanel x:Name="PART_HOSTPANEL" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Background="{DynamicResource WindowBackgroundLightBrush}"/> 79 <ScrollViewer Grid.Row="1" Grid.Column="1" Focusable="False" Padding="{TemplateBinding Padding}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> 80 <StackPanel x:Name="PART_HEADERPANEL" MinHeight="25" Background="{DynamicResource WindowBackgroundBrush}" Orientation="Horizontal"/> 81 </ScrollViewer> 82 <StackPanel MinHeight="25" Orientation="Horizontal" Grid.Row="1" Grid.Column="2" Background="{DynamicResource WindowBackgroundBrush}"> 83 <Button x:Name="PART_DOCMENU" Tag="{DynamicResource xpdock_PinDocMenu}" Style="{DynamicResource MidToolbarStyle}" Margin="2,0,2,0"/> 84 </StackPanel> 85 <GridSplitter x:Name="PART_TOPSPLITTER" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" Height="1" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}"/> 86 <GridSplitter x:Name="PART_BOTTOMSPLITTER" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" Height="1" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Cursor="SizeNs" Background="{DynamicResource WindowBackgroundBrush}"/> 87 <GridSplitter x:Name="PART_LEFTSPLITTER" Grid.Row="0" Grid.Column="0" Grid.RowSpan="5" Width="1" VerticalAlignment="Stretch" HorizontalAlignment="Right" Cursor="SizeWe" Background="{DynamicResource WindowBackgroundBrush}"/> 88 <GridSplitter x:Name="PART_RIGHTSPLITTER" Grid.Row="0" Grid.Column="3" Grid.RowSpan="5" Width="1" VerticalAlignment="Stretch" HorizontalAlignment="Left" Cursor="SizeWe" Background="{DynamicResource WindowBackgroundBrush}"/> 89 </Grid> 90 </Border> 91 </ControlTemplate> 92 </Setter.Value> 93 </Setter> 94 <Style.Triggers> 95 <Trigger Property="IsMouseOver1" Value="True" > 96 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}" /> 97 </Trigger> 98 <Trigger Property="IsFocused1" Value="True" > 99 <Setter1 Property="BorderThickness" Value="1" /> 100 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderFocusBrush}" /> 101 </Trigger> 102 </Style.Triggers> 103 </Style> 104 105 <Style TargetType="LayoutElement"> 106 <Setter Property="Background" Value="{DynamicResource WindowBackgroundLightBrush}" /> 107 <Setter Proterty="Foreground" value="{DynamicResource WindowForgroundLightBrush}"/> 108 <Setter Property="BorderThickness" Value="1" /> 109 <Setter Property="Margin" Value="0" /> 110 <Setter Property="DockWidth" Value="200" /> 111 <Setter Property="DockHeight" Value="100" /> 112 <Setter Property="FloatingWidth" Value="200" /> 113 <Setter Property="FloatingHeight" Value="100" /> 114 <Setter Property="LayoutType" Value="Anchor" /> 115 <Setter Property="HorizontalAlignment" Value="Stretch" /> 116 <Setter Property="VerticalAlignment" Value="Stretch" /> 117 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderNormalBrush}" /> 118 <Setter Property="Template"> 119 <Setter.Value> 120 <ControlTemplate TargetType="LayoutElement"> 121 <Border Background="{TemplateBinding}" 122 BorderBrush="{TemplateBinding}" 123 BorderThickness="{TemplateBinding}" Padding="0" > 124 <ScrollViewer Focusable="False" Padding="{TemplateBinding Padding}" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"> 125 <Grid x:Name="PART_ROOT" > 126 <Grid.ColumnDefinitions> 127 <ColumnDefinition Width="1*"/> 128 </Grid.ColumnDefinitions> 129 <Grid.RowDefinitions> 130 <RowDefinition Height="Auto"/> 131 <RowDefinition Height="1*"/> 132 </Grid.RowDefinitions> 133 <DockPanel x:Name="PART_HOSTPANEL" Grid.Row="1" Background="{DynamicResource WindowBackgroundLightBrush}"> 134 <ContentPresenter /> 135 </DockPanel> 136 <DockPanel x:Name="PART_TITLEPANEL" Grid.Row="0" MinHeight="25" Background="{DynamicResource WindowBackgroundBrush}" Visibility="{TemplateBinding TitleVisibility}"> 137 <StackPanel DockPanel.Dock="Right" Height="20" Orientation="Horizontal"> 138 <Button x:Name="PART_AUTOHIDE" Tag="{DynamicResource xpdock_PinAutoHide}" Style="{DynamicResource MidToolbarStyle}" Margin="2,0,0,0"/> 139 <Button x:Name="PART_DOCK" Tag="{DynamicResource xpdock_PinDock}" Style="{DynamicResource MidToolbarStyle}" Padding="2"/> 140 <Button x:Name="PART_PINMENU" Tag="{DynamicResource xpdock_PinMenu}" Style="{DynamicResource MidToolbarStyle}" Padding="2"/> 141 </StackPanel> 142 <TextBlock Margin="5,0,0,0" Text="{TemplateBinding Title}"/> 143 </DockPanel> 144 </Grid> 145 </ScrollViewer > 146 </Border> 147 </ControlTemplate> 148 </Setter.Value> 149 </Setter> 150 <Style.Triggers> 151 <Trigger Property="IsMouseOver" Value="True" > 152 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}" /> 153 </Trigger> 154 <Trigger Property="IsFocused" Value="True" > 155 <Setter1 Property="BorderThickness" Value="1" /> 156 <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderFocusBrush}" /> 157 </Trigger> 158 <!-- <Trigger Property="LayoutType" Value="Document" > 159 <Setter Property="Visibility" TargetName="PART_TITLEPANEL" Value="Collapsed" /> 160 </Trigger> 161 <Trigger Property="LayoutType" Value="Floating" > 162 <Setter Property="Visibility" TargetName="PART_TITLEPANEL" Value="Collapsed" /> 163 </Trigger> --> 164 </Style.Triggers> 165 </Style> 166 <Style TargetType="LayoutFloatingWindow" > 167 <Setter Property="ResizeMode" Value="CanResize" /> 168 <Setter Property="Background" Value="Transparency" /> 169 <Setter Proterty="Foreground" value="{DynamicResource WindowForgroundLightBrush}"/> 170 <Setter Property="Height" Value="300" /> 171 <Setter Property="Width" Value="350" /> 172 <Setter Property="AllowsTransparency" Value="True" /> 173 <Setter Property="BorderThickness" Value="6" /> 174 <Setter Property="BorderBrush" Value="{DynamicResource BordersStrokeBrush_Normal}" /> 175 <Setter Property="Template"> 176 <Setter.Value> 177 <ControlTemplate TargetType="LayoutFloatingWindow"> 178 <Border Background="Transparent" 179 BorderBrush="{TemplateBinding}" 180 BorderThickness="{TemplateBinding}" Padding="0" 181 CornerRadius="5" > 182 <Border x:Name="bd" Background="{DynamicResource WindowBackgroundBrush}" CornerRadius="5"> 183 <Grid> 184 <DockPanel VerticalAlignment="Top"> 185 <StackPanel VerticalAlignment="Top" Height="40" Orientation="Horizontal" DockPanel.Dock="Right" > 186 <MinimizeButton ToolTip="最小化" DockPanel.Dock="Right" Focusable="False" Width="25" Height="25" VerticalAlignment="Top" /> 187 <MaximizeButton DockPanel.Dock="Right" Focusable="False" Width="25" Height="25" VerticalAlignment="Top" /> 188 <CloseButton DockPanel.Dock="Right" Width="25" Height="25" VerticalAlignment="Top" /> 189 </StackPanel> 190 <TextBlock Name="PART_TITLE" Text="{TemplateBinding Title}" FontSize="12" Margin="4" VerticalAlignment="Center" Foreground="{WindowForgroundLightBrush}" FontWeight="Bold"/><!--{Binding Title,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}, AncestorLevel=1}}--> 191 </DockPanel> 192 <Grid Margin="0,35,0,0"> 193 <DockPanel> 194 <ContentPresenter /> 195 </DockPanel> 196 </Grid> 197 </Grid> 198 </Border> 199 </Border> 200 <ControlTemplate.Triggers> 201 <Trigger Property="WindowState" Value="Maximized" > 202 <Setter TargetName="bd" Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}" /> 203 <Setter TargetName="bd" Property="BorderThickness" Value="1" /> 204 </Trigger> 205 <Trigger Property="IsMouseOver" Value="True" > 206 <Setter TargetName="bd" Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}" /> 207 <Setter TargetName="bd" Property="BorderThickness" Value="1" /> 208 </Trigger> 209 </ControlTemplate.Triggers> 210 </ControlTemplate> 211 </Setter.Value> 212 </Setter> 213 </Style>
从以上样式就可以看出和WPF是基本一致的,这也是SharpUI的一大特点;不管怎么说有了可停靠管理的实现,为我的插件式框架又进了一点;那要实现插件式管理还需要做什么呢?最主要的就是写的一个核心的项目库(XPCore),主要用来管理目录、日志、服务、资源加载、插件DLL的加载、角本编译、配置信息管理等等,这些将在下一篇中介绍。
本文版权所有,如转发和引用请注明。