Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net windows窗体自定义布局引擎_C#_Winforms_Layout_Overlap - Fatal编程技术网

C# .Net windows窗体自定义布局引擎

C# .Net windows窗体自定义布局引擎,c#,winforms,layout,overlap,C#,Winforms,Layout,Overlap,我正在尝试写一个纸牌游戏,玩家可以堆叠纸牌。例如A,二,三 我想想象一堆卡片,其中王牌部分由两张卡片覆盖,两张卡片部分由三张卡片覆盖。三张卡片完全可见 简单,我想。我在添加卡的地方创建一个用户控件:Controls.add(ace);控件。添加(两个);等等 然后我需要一些能够布置控件的东西,所以我编写了自定义LayoutEngine(源自LayoutEngine)。我的第一个测试只不过是将控件移动50像素 运行解决方案后,我注意到Z顺序是错误的。不是三张牌在上面,而是王牌在上面,看起来像这样:

我正在尝试写一个纸牌游戏,玩家可以堆叠纸牌。例如A,二,三

我想想象一堆卡片,其中王牌部分由两张卡片覆盖,两张卡片部分由三张卡片覆盖。三张卡片完全可见

简单,我想。我在添加卡的地方创建一个用户控件:Controls.add(ace);控件。添加(两个);等等

然后我需要一些能够布置控件的东西,所以我编写了自定义LayoutEngine(源自LayoutEngine)。我的第一个测试只不过是将控件移动50像素

运行解决方案后,我注意到Z顺序是错误的。不是三张牌在上面,而是王牌在上面,看起来像这样:

王牌>两张牌>三张牌,其中: 王牌在上面 王牌下有两张牌 三张牌在两张牌下面

所以我开始寻找一种方法来改变WinForms中的Z顺序,发现它只是“不可用”。喜欢啊

另一种选择(由MS提供)是,可以通过设置控件的ChildIndex来更改Z顺序。Jikes,这意味着在列表中四处搜索,可以改变我的应用程序的行为。加油,女士

不管怎样,我尝试了各种方法,但似乎不可能编写一个布局引擎来实现这一点

我用google-d搜索了一整天,没有发现任何有用的东西。我不是GUI专家,所以我在这个蹩脚的问题上陷入了困境。谁能帮我

非常感谢


Bas

你最好的办法是完全避免使用控件。它们将导致A)性能差(er)和B)命中测试/绘图复杂化

只需创建对象来表示表的状态(我使用CardContainer对象),并使用Graphics.DrawImage在绘制事件期间将所有卡绘制到它们所在的位置。如果还需要添加其他UI元素,则可以对整个表使用单个控件

如果您决定添加动画,这也将使卡片移动动画更简单

已更新

我本想扩大这个答案,但被叫走了,只是把我的答案贴了出来。以下是一些您可能会发现有用的细节。我创建了一个“纸牌游戏引擎”。该引擎一次只能运行一个纸牌游戏(克朗代克、蜘蛛、战略等)。它跟踪每个游戏的统计信息,并允许玩和编辑单个游戏。这些游戏是IronPython脚本,这使得添加新游戏相对容易

My CardContainer是一个包含零张或多张卡的对象

它有一个方向(无、上、下、左、右),这决定了它的牌是如何排列的

它有一个最大深度,可以钳制在该方向上绘制的卡数。对于Klondike这样的游戏来说,这很方便,因为你只想展示最上面的3张牌

它具有用于分隔卡片的属性。对于正面朝上和正面朝下的卡片,有单独的间距值。它可以将卡自动打包到由MaximumLength定义的区域中。它有一个“额外的pad”值,每一张卡对应一个值——不管该索引中是否有卡。后者在模拟鼠标悬停期间用于“揭开”指向的卡,以便用户可以清楚地看到可能被上面的卡遮挡的卡。这是通过在悬停卡顶部设置卡的“额外垫”来实现的。这可以通过使用“悬停牌”和“悬停间距”属性来简化,但每张牌都有额外的填充,这就允许进行奇怪的单人纸牌游戏,用间距突出画面堆中的特定“行”

它有一个HitTest方法从给定的X,Y位置返回一张卡

所有这些都意味着Card对象不知道它在表上的绘制位置。我有一个复杂的动画系统,所以卡的位置最终来自动画引擎。如果卡当前未设置动画,动画系统将从其容器获取其位置

请注意,上面提到的卡片位置仅用于绘图。所有的卡片都是固定在一个卡片容器上的,只需从一个卡片容器移动到另一个卡片容器即可。有一个“特殊”容器称为卡片组,最初包含每张卡片。最初,它位于桌子之外。容器具有可见属性。仅当将卡从一个可见容器移动到另一个可见容器时,才会播放动画。这允许您在必要时移动卡片,而无需动画,并且卡片可以“飞出”到桌子以外的容器

该引擎还有一个基本的布局系统,用于相对定位卡片容器。我做的一件非常方便的事情是使用卡片大小的相对坐标系。表的“宽度”正好是11个卡片宽度。无论用户的表大小有多大,宽度始终为11卡宽。这意味着卡的大小(由用户查看)会变大或缩小。高度是可变的,但由固定的卡大小比率决定(由卡位图决定)。如果给CardContainer的X值为1.0,则表示它将位于表左侧一个卡宽的位置。这些值是浮点数,因此您可以使用0.5指定1/2卡宽。这使得在脚本中定位元素非常容易,而不必担心屏幕坐标。无论用户如何改变屏幕大小,您的游戏都将以完全相同的方式进行布局

引擎还具有无限的撤消和重做功能。这意味着不仅要记录卡的移动(从一个容器到另一个容器),还要记录所有属性的更改(卡和容器属性)。如果从一开始就没有计划,撤消和重做可能很难实现。脚本可以访问Game.LogVariableChange方法,以便通过记录机制更改全局变量的值。这是