最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# WPF利用Clip屬性實(shí)現(xiàn)截屏框功能

 更新時(shí)間:2024年01月23日 09:49:58   作者:CodeOfCC  
這篇文章主要為大家詳細(xì)介紹了C# WPF如何利用Clip屬性實(shí)現(xiàn)截屏框功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

第一節(jié)已經(jīng)實(shí)現(xiàn)過截屏框,實(shí)現(xiàn)方法相對簡單,也僅支持矩形框。最近使用wpf的clip時(shí)發(fā)現(xiàn)了一種用法,可以實(shí)現(xiàn)穿透效果。那顯然我們基于clip也能實(shí)現(xiàn)截屏窗口,而且支持任意形狀。

一、實(shí)現(xiàn)步驟

1、Clip穿透

使用GeometryGroup 且FillRule為EvenOdd就可以做出穿透的效果。

<Grid>
    <Grid Width="200" Height="200" Background="SeaGreen" >
        <Grid.Clip>
            <GeometryGroup  FillRule="EvenOdd">
                <!--底下的rect必須保持和容器大小一致-->
                <RectangleGeometry  Rect="0 0 200 200" />
                <!--上層形狀即為穿透區(qū)域-->
                <RectangleGeometry x:Name="foreRect" Rect="0 0 200 200" RadiusX="100" RadiusY="100"/>
            </GeometryGroup>
        </Grid.Clip>
    </Grid>
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text= "Clip區(qū)域會(huì)穿透" Foreground="Black"></TextBlock>
</Grid>

2、子控件同步Clip區(qū)域

單純Clip無法實(shí)現(xiàn)拖動(dòng)和改變大小,尤其是改變大小直接通過鼠標(biāo)事件結(jié)合clip也不好實(shí)現(xiàn)。比較簡單的方法是定義一個(gè)子控件,子控件的位置和大小與Clip關(guān)聯(lián),這樣只要實(shí)現(xiàn)子控件的拖動(dòng)和調(diào)整大小功能就能控制Clip區(qū)域了。

通過LayoutUpdated事件就可以實(shí)時(shí)同步Clip區(qū)域。子控件就相當(dāng)于截屏框。

<Border x:Name="clipBorder" LayoutUpdated="Border_LayoutUpdated">

下列代碼的GetPosition是自定義拓展方法,自己實(shí)現(xiàn)獲取控件坐標(biāo)即可。

private void Border_LayoutUpdated(object sender, EventArgs e)
{
    //截屏框與上層clip rect保持一致
    foreRect.Rect = new Rect(clipBorder.GetPosition(), new Size(clipBorder.ActualWidth, clipBorder.ActualHeight));;
}

3、子控件實(shí)現(xiàn)拖動(dòng)

參考《wpf拖動(dòng)系列》,根據(jù)不同的容器選擇不同實(shí)現(xiàn)(直接拷貝網(wǎng)頁代碼),此處使用第六章的功能簡化實(shí)現(xiàn)。

<Border x:Name="clipBorder" ac:Move.IsDragMoveable="True" >

4、子控件實(shí)現(xiàn)拖動(dòng)調(diào)整大小

參考《wpf拖動(dòng)調(diào)整大小系列》,根據(jù)不同的容器選擇不同實(shí)現(xiàn)(直接拷貝網(wǎng)頁代碼),此處使用第五章的功能簡化實(shí)現(xiàn)。

<Border x:Name="clipBorder" ac:Resize.IsDragResizeable="True" >

5、鼠標(biāo)事件傳遞

由于使用了Clip穿透,穿透區(qū)域的子控件是無法響應(yīng)鼠標(biāo)的,有幸的是穿透區(qū)域不會(huì)影響裝飾層,所以我們需要在子控件里定義一個(gè)裝飾器用于捕獲鼠標(biāo)消息。我們通過《wpf 附加屬性實(shí)現(xiàn)界面上定義裝飾器》簡化裝飾器的定義。

<Border x:Name="clipBorder">
    <!--截屏框的裝飾層,用于捕獲鼠標(biāo)消息-->
    <local:AdornerHelper.AdornerContent>
        <Grid MouseDown="Grid_MouseDown" Background="Transparent"></Grid>
    </local:AdornerHelper.AdornerContent>
</Border>
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{  
     //事件轉(zhuǎn)移,觸發(fā)拖動(dòng)
    clipBorder.RaiseEvent(e);
}

二、完整代碼

1、自行整合

通過上述步驟,將《wpf拖動(dòng)系列》、《wpf拖動(dòng)調(diào)整大小系列》、《wpf 附加屬性實(shí)現(xiàn)界面上定義裝飾器》網(wǎng)頁上的代碼(對應(yīng)容器類型)整合到一起即可實(shí)現(xiàn)所有功能。

2、簡化的實(shí)現(xiàn)

下列是使用wpf拖動(dòng)系列第六章wpf拖動(dòng)調(diào)整大小系列第五章的實(shí)現(xiàn),需要下載。

xaml

<Window x:Class="WpfClip.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfClip"
        xmlns:ac="clr-namespace:AC"
        mc:Ignorable="d"
        WindowStyle="None"
        Background="Transparent"
        ResizeMode="NoResize"
        Topmost="True"
        WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"   CaptionHeight="0"   />
    </WindowChrome.WindowChrome >
    <Grid x:Name="grid" Background="#80000000" LayoutUpdated="Grid_LayoutUpdated">
        <Grid.Clip>
            <!--利用clip實(shí)現(xiàn)穿透-->
            <GeometryGroup  FillRule="EvenOdd">
                <RectangleGeometry x:Name="backRect"/>
                <!--實(shí)際的截屏形狀-->
                <RectangleGeometry x:Name="foreRect"  />
            </GeometryGroup>
        </Grid.Clip>
        <!--截屏框-->
        <Border x:Name="clipBorder" Width="200" Height="200" ac:Move.IsDragMoveable="True" ac:Resize.IsResizeable="True" LayoutUpdated="Border_LayoutUpdated">
            <ac:Resize.ThumbsTemplate>
                <ControlTemplate>
                    <Border Width="16" Height="16" Background=" Green"  BorderBrush="White" BorderThickness="2" CornerRadius="8"></Border>
                </ControlTemplate>
            </ac:Resize.ThumbsTemplate>
            <ac:Resize.ThumbsPanel>
                <ItemsPanelTemplate>
                    <Grid Margin="-8"></Grid>
                </ItemsPanelTemplate>
            </ac:Resize.ThumbsPanel>
            <!--截屏框的裝飾層,用于捕獲鼠標(biāo)消息-->
            <local:AdornerHelper.AdornerContent>
                <Grid MouseDown="Grid_MouseDown" Background="Transparent"></Grid>
            </local:AdornerHelper.AdornerContent>
        </Border>
    </Grid>
</Window>

cs

using AC;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace WpfClip
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Grid_LayoutUpdated(object sender, EventArgs e)
        {
            //確保底層clip rect與容器大小相同
            backRect.Rect=new Rect(0,0, grid.ActualWidth, grid.ActualHeight);
        }
        private void Border_LayoutUpdated(object sender, EventArgs e)
        {
            //截屏框與上層clip rect保持一致
            foreRect.Rect = new Rect(clipBorder.GetPosition(), new Size(clipBorder.ActualWidth, clipBorder.ActualHeight));
            //圓形效果,去掉則是矩形
            foreRect.RadiusX = clipBorder.Width/2;
            foreRect.RadiusY= clipBorder.Height/2;
        }

        private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
        {  
             //事件轉(zhuǎn)移,觸發(fā)拖動(dòng)
            clipBorder.RaiseEvent(e);
        }
    }

    internal class AdornerHelper
    {
        public static UIElement GetAdornerContent(DependencyObject obj)
        {
            return (UIElement)obj.GetValue(AdornerContent);
        }
        public static void SetAdornerContent(DependencyObject obj, UIElement value)
        {
            obj.SetValue(AdornerContent, value);
        }
        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AdornerContent =
            DependencyProperty.RegisterAttached("AdornerContent", typeof(UIElement), typeof(AdornerHelper), new PropertyMetadata(null, (d, e) =>
            {
                var c = d as FrameworkElement;
                if (c == null)
                    return;
                var adronerContent = e.NewValue as UIElement;
                if (!c.IsLoaded)
                {
                    if (adronerContent != null)
                    {
                        RoutedEventHandler l = null;
                        l = (s, E) =>
                        {
                            var content = GetAdornerContent(c);
                            if (content != null)
                            {
                                var layer = AdornerLayer.GetAdornerLayer(c);
                                if (layer == null)
                                    throw new Exception("獲取控件裝飾層失敗,控件可能沒有裝飾層!");
                                layer.Add(new NormalAdorner((UIElement)c, (UIElement)e.NewValue));
                            }
                            c.Loaded -= l;
                        };
                        c.Loaded += l;
                    }
                }
                else
                {
                    var layer = AdornerLayer.GetAdornerLayer(d as Visual);
                    if (layer == null)
                        throw new Exception("獲取控件裝飾層失敗,控件可能沒有裝飾層!");
                    if (e.OldValue != null)
                    {
                        var adorners = layer.GetAdorners(c);
                        foreach (var i in adorners)
                        {
                            if (i is NormalAdorner)
                            {
                                var na = i as NormalAdorner;
                                if (na.Child == e.OldValue)
                                {
                                    layer.Remove(i);
                                    break;
                                }
                            }
                        }
                    }
                    if (adronerContent != null)
                    {
                        layer.Add(new NormalAdorner((UIElement)c, (UIElement)e.NewValue));
                    }
                }
            }));

        class NormalAdorner : Adorner
        {
            UIElement _child;
            /// <summary>
            /// 構(gòu)造方法
            /// </summary>
            /// <param name="adornedElement">被添加裝飾器的元素</param>
            /// <param name="child">放到裝飾器中的元素</param>
            public NormalAdorner(UIElement adornedElement, UIElement child) : base(adornedElement)
            {
                _child = child;
                AddVisualChild(child);
            }
            public UIElement Child { get { return _child; } }
            protected override Visual GetVisualChild(int index)
            {
                return _child;
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return 1;
                }
            }
            protected override Size ArrangeOverride(Size finalSize)
            {
                _child.Arrange(new Rect(new Point(0, 0), finalSize));
                return finalSize;
            }

        }
    }
}

三、效果預(yù)覽

我們可以通過設(shè)置foreRect的類型改變形狀,當(dāng)然Border_LayoutUpdated的邏輯也要相應(yīng)的修改。

1、矩形框

2、圓形框

總結(jié)

有了之前的基礎(chǔ)本文實(shí)現(xiàn)起來相對容易,當(dāng)前目前的也是比較初步的功能,但靈活性是比DockPanel要好的,尤其是支持任意形狀,這樣就有利于后期劃線截屏的實(shí)現(xiàn)了。

到此這篇關(guān)于C# WPF利用Clip屬性實(shí)現(xiàn)截屏框功能的文章就介紹到這了,更多相關(guān)C# WPF截屏框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# 反射(Reflection)的用處分析

    C# 反射(Reflection)的用處分析

    反射(Reflection)是C#里很重要的一個(gè)特性,其它語言也有這個(gè)特性,比如JAVA。反射這個(gè)特性是很實(shí)用的,如果使用過struts, hibernate, spring等等這些框架的話,便會(huì)知道反射這個(gè)特性是多么的強(qiáng)大了。在我接觸過的那些框架中,沒有一個(gè)框架是不使用反射的。
    2015-03-03
  • C#子線程執(zhí)行完后通知主線程的方法

    C#子線程執(zhí)行完后通知主線程的方法

    下面小編就為大家?guī)硪黄狢#子線程執(zhí)行完后通知主線程的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • 深入了解c# 匿名類型

    深入了解c# 匿名類型

    這篇文章主要介紹了c# 匿名類型的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 使用C#調(diào)用百度地圖并實(shí)現(xiàn)坐標(biāo)點(diǎn)的設(shè)置以及讀取示例

    使用C#調(diào)用百度地圖并實(shí)現(xiàn)坐標(biāo)點(diǎn)的設(shè)置以及讀取示例

    這篇文章主要介紹了使用C#調(diào)用百度地圖并實(shí)現(xiàn)坐標(biāo)點(diǎn)的設(shè)置以及讀取示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • C#開啟線程的四種方式示例詳解

    C#開啟線程的四種方式示例詳解

    今天小編就為大家分享一篇關(guān)于C#開啟線程的四種方式示例詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • C#中Prism框架的SetRegionManager用法詳解

    C#中Prism框架的SetRegionManager用法詳解

    這篇文章主要介紹了C#中SetRegionManager的正確使用方法,避免常見誤區(qū),如未正確注入IRegionManager、重復(fù)設(shè)置RegionManager等錯(cuò)誤,深入了解Prism框架中的區(qū)域管理技巧,需要的朋友可以參考下
    2026-06-06
  • C#操作INI文件的方法詳解

    C#操作INI文件的方法詳解

    INI文件全稱是Initialization File的縮寫,即初始化文件,是windows系統(tǒng)的系統(tǒng)配置文件所采用的存儲(chǔ)格式,統(tǒng)管windows的各項(xiàng)配置。本文介紹了C#操作INI文件的方法,需要的可以參考一下
    2022-10-10
  • C#中Winform 實(shí)現(xiàn)Ajax效果自定義按鈕

    C#中Winform 實(shí)現(xiàn)Ajax效果自定義按鈕

    這篇文章主要介紹了C#中Winform 實(shí)現(xiàn)Ajax效果自定義按鈕的相關(guān)資料,需要的朋友可以參考下
    2017-12-12
  • 淺析C#中的Main(String[] args)參數(shù)輸入問題

    淺析C#中的Main(String[] args)參數(shù)輸入問題

    本篇文章主要是對C#中的Main(String[] args)參數(shù)輸入問題進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 通過C#和RTSPClient實(shí)現(xiàn)簡易音視頻解碼功能

    通過C#和RTSPClient實(shí)現(xiàn)簡易音視頻解碼功能

    在多媒體應(yīng)用中,實(shí)時(shí)傳輸協(xié)議(RTSP)用于流媒體服務(wù),特別是音視頻?監(jiān)控系統(tǒng),通過?C#?和?RTSPClient?庫,可以輕松實(shí)現(xiàn)簡易的音視頻解碼和播放功能,本文將詳細(xì)介紹如何使用?C#?和?RTSPClient?構(gòu)建一個(gè)簡易但高效的音視頻解碼器,需要的朋友可以參考下
    2024-12-12

最新評論

星座| 长岛县| 嘉鱼县| 凤阳县| 黄平县| 黑龙江省| 叙永县| 永胜县| 成都市| 彭山县| 德格县| 聊城市| 安徽省| 清水河县| 澄江县| 固始县| 高邮市| 闸北区| 石楼县| 千阳县| 淅川县| 修武县| 娄烦县| 比如县| 睢宁县| 边坝县| 上虞市| 越西县| 霍林郭勒市| 闵行区| 祁连县| 阜阳市| 瓮安县| 饶阳县| 醴陵市| 尖扎县| 辽中县| 封开县| 武威市| 绥芬河市| 昆明市|