亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 WPF 中使用捏合功能同時啟用滾動和縮放?

如何在 WPF 中使用捏合功能同時啟用滾動和縮放?

C#
侃侃爾雅 2023-09-24 15:44:06
我正在努力使觸摸事件和操作在 WPF 項目中正常工作。我有一個包含圖片的ScrollViewer,我想使用滑動手勢水平和垂直滾動。此外,我想在捏合手勢的中心放大/縮小。下面的代碼實現了我的愿望,但是存在以下問題:有時滾動會很滯后;滾動在第一次嘗試時不起作用,只有在第二次嘗試相同的手勢時才會起作用;第一次嘗試時放大/縮小不起作用,僅當第二次嘗試相同手勢時才起作用。我啟用了IsManipulationEnabled并實現了放大/縮小功能的代碼。但是,我無法將其與滾動功能結合起來(僅通過在ScrollViewer中設置PanningMode)。因此,我創建了一個繼承自Image控件的自定義控件,并覆蓋了OnTouchDown和OnTouchUp事件處理程序?;旧希以谶@些覆蓋的處理程序中所做的就是計算屏幕上的觸摸次數并啟用/禁用操作。我還嘗試設置ScrollViewer的PanningMode,但它沒有成功。下面是 XAML:<Grid>        <ScrollViewer            x:Name="ScrollViewerParent"            HorizontalScrollBarVisibility="Auto"            VerticalScrollBarVisibility="Auto"            PanningMode="Both">            <local:CustomImage                 x:Name="MainImage"                Source="{Binding Source={x:Static local:Constants.ImagePath}}"                IsManipulationEnabled="True"                ManipulationStarting="MainImage_ManipulationStarting"                ManipulationDelta="MainImage_ManipulationDelta">            </local:CustomImage>        </ScrollViewer>    </Grid>這是背后的代碼:public partial class MainWindow : Window{        private void MainImage_ManipulationStarting(object sender, ManipulationStartingEventArgs e)        {            e.ManipulationContainer = ScrollViewerParent;            e.Handled = true;        }        private void MainImage_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)        {            var matrix = MainImage.LayoutTransform.Value;            Point? centerOfPinch = (e.ManipulationContainer as FrameworkElement)?.TranslatePoint(e.ManipulationOrigin, ScrollViewerParent);            if (centerOfPinch == null)            {                return;        }}
查看完整描述

1 回答

?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

幸運的是,我設法找到了完美的解決方案。因此,如果有人正在解決類似的問題并需要一些幫助,我將發布答案。

我做了什么:

  1. 擺脫了自定義控件,因為它沒有必要;

  2. 創建一個統計觸摸點數量的字段;

  3. 實現了TouchDown事件處理程序,它將觸摸點的數量增加 1(每次設備上有觸摸向下手勢時都會調用此方法);

  4. 實現了TouchUp事件處理程序,它將觸摸點的數量減 1(每次設備上有觸摸向上手勢時都會調用此方法);

  5. Image_ManipulationDelta事件處理程序中,我檢查觸摸點的數量:

    • 如果觸摸點數<2,則將平移值加上滾動條當前的偏移量,從而實現滾動;

    • 否則,計算捏合中心并應用縮放手勢。

這是完整的 XAML:

 <Grid

        x:Name="GridParent">

        <ScrollViewer

            x:Name="ScrollViewerParent"

            HorizontalScrollBarVisibility="Auto"

            VerticalScrollBarVisibility="Auto"

            PanningMode="Both">

            <Image

                x:Name="MainImage"

                Source="{Binding Source={x:Static local:Constants.ImagePath}}"

                IsManipulationEnabled="True"

                TouchDown="MainImage_TouchDown"

                TouchUp="MainImage_TouchUp"

                ManipulationDelta="Image_ManipulationDelta"

                ManipulationStarting="Image_ManipulationStarting"/>

        </ScrollViewer>

    </Grid>

這是上面討論的完整代碼:


    public partial class MainWindow : Window

    {


        private volatile int nrOfTouchPoints;

        private object mutex = new object();


        public MainWindow()

        {

            InitializeComponent();

            DataContext = this;

        }


        private void Image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)

        {

            e.ManipulationContainer = ScrollViewerParent;

            e.Handled = true;

        }


        private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)

        {

            int nrOfPoints = 0;


            lock (mutex)

            {

                nrOfPoints = nrOfTouchPoints;

            }


            if (nrOfPoints >= 2)

            {

                DataLogger.LogActionDescription($"Executed {nameof(Image_ManipulationDelta)}");


                var matrix = MainImage.LayoutTransform.Value;


                Point? centerOfPinch = (e.ManipulationContainer as FrameworkElement)?.TranslatePoint(e.ManipulationOrigin, ScrollViewerParent);


                if (centerOfPinch == null)

                {

                    return;

                }


                var deltaManipulation = e.DeltaManipulation;

                matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, centerOfPinch.Value.X, centerOfPinch.Value.Y);

                MainImage.LayoutTransform = new MatrixTransform(matrix);


                Point? originOfManipulation = (e.ManipulationContainer as FrameworkElement)?.TranslatePoint(e.ManipulationOrigin, MainImage);


                double scrollViewerOffsetX = ScrollViewerParent.HorizontalOffset;

                double scrollViewerOffsetY = ScrollViewerParent.VerticalOffset;


                double pointMovedOnXOffset = originOfManipulation.Value.X - originOfManipulation.Value.X * deltaManipulation.Scale.X;

                double pointMovedOnYOffset = originOfManipulation.Value.Y - originOfManipulation.Value.Y * deltaManipulation.Scale.Y;


                double multiplicatorX = ScrollViewerParent.ExtentWidth / MainImage.ActualWidth;

                double multiplicatorY = ScrollViewerParent.ExtentHeight / MainImage.ActualHeight;


                ScrollViewerParent.ScrollToHorizontalOffset(scrollViewerOffsetX - pointMovedOnXOffset * multiplicatorX);

                ScrollViewerParent.ScrollToVerticalOffset(scrollViewerOffsetY - pointMovedOnYOffset * multiplicatorY);


                e.Handled = true;

            }

            else

            {

                ScrollViewerParent.ScrollToHorizontalOffset(ScrollViewerParent.HorizontalOffset - e.DeltaManipulation.Translation.X);

                ScrollViewerParent.ScrollToVerticalOffset(ScrollViewerParent.VerticalOffset - e.DeltaManipulation.Translation.Y);

            }

        }


        private void MainImage_TouchDown(object sender, TouchEventArgs e)

        {

            lock (mutex)

            {

                nrOfTouchPoints++;

            }

        }


        private void MainImage_TouchUp(object sender, TouchEventArgs e)

        {

            lock (mutex)

            {

                nrOfTouchPoints--;

            }

        }

    }

}



查看完整回答
反對 回復 2023-09-24
  • 1 回答
  • 0 關注
  • 119 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號