using Microsoft.WindowsAPICodePack.Shell; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace HistoryDLL { /// /// PlaneRotateMap.xaml 的互動邏輯 /// public partial class PlaneRotateMap : UserControl { //創造 PlaneRotateMap 物件 private delegate void CreatePlaneRotateMapDelegate(); private delegate void DynamicChangeLan(); private DispatcherTimer RotateWaitTime = new DispatcherTimer(); //該PlaneRotate中有幾個可以顯示的物件 private int ImageWidth, ImageHeight; private List ElementForRotateList = new List(); private Rectangle RectForTouch = new Rectangle(); //當前顯示的物件是屬於ElementForRotateList中的第幾個索引 private int CurrentShowIndex = 0; //該輪播塊是屬於該年事件中的第幾個索引 public int indexOfEvent = -1; //亂數產生 private Random rnd = new Random(Guid.NewGuid().GetHashCode()); //切換資訊的亂數時間範圍 changeInfoTimeMin <= s < changeInfoTimeMax private int changeInfoTimeMin = 8; private int changeInfoTimeMax = 32; //Other Number private double RotateAngle = 10.0; //區塊旋轉時候的角度 private double TextFontSize = 23; //顯示的資訊如果是文字~則設定文字大小 private int RotateAnimationTime = 400; private Storyboard sbStepOne = new Storyboard(); private DoubleAnimation dbOffsetOne = new DoubleAnimation(); private Storyboard sbStepTwo = new Storyboard(); private DoubleAnimation dbOffsetTwo = new DoubleAnimation(); private SolidColorBrush RotateContainColor = new SolidColorBrush(ConfigSettingClass.EventCollect.BackgroundColor); private SolidColorBrush RotateContainTextColor = new SolidColorBrush(ConfigSettingClass.EventCollect.TextColor); //判斷是否資料已經到底的紀錄的 Index private int RecordInfoCount = 1; //資料暫存 public MonthClass RotateMonthClass = new MonthClass(); private string[] imgfilter = { ".jpeg", ".jpg", ".bmp", ".png" }; private string[] mediafilter = { ".mp4", ".wmv", ".mpeg", "mpg", "avi" }; //該PlaneRotateMap在LiveContainer 中的哪個區塊 public int BlockIndex = -1; public bool ChangeInfo = false; public PlaneRotateMap() { InitializeComponent(); } public PlaneRotateMap(MonthClass sourcemonthClass, int ImageWidth, int ImageHeight) { InitializeComponent(); if (GlobalFunction.isSolutionUsing4K) TextFontSize *= 1.5; //將暫時設定一下顏色 uxRotateContain.Background = RotateContainColor; //設定翻轉頻率 SetRotateFreq(); //設定旋轉動作的相關Timer SettingRotateMap(); RotateWaitTime.Tick += new EventHandler(RotateWaitTime_Tick); //資料存到緩衝 RotateMonthClass = sourcemonthClass; //設定寬高 uxRotateContain.Width = uxRotateMainGrid.Width = this.ImageWidth = ImageWidth; uxRotateContain.Height = uxRotateMainGrid.Height = this.ImageHeight = ImageHeight; //設定可觸控層 SetTouchLay(ImageWidth, ImageHeight); //翻轉角度設定 uxMyPlanerator.FieldOfView = RotateAngle; } private void DynamicChangeLanEvent() { //第 0 個一定是文字 Grid gd = ElementForRotateList[0] as Grid; TextBlock tb = gd.Children[0] as TextBlock; //假如現在是第一種語系 if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1") { tb.Text = RotateMonthClass.titleLan1; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2") { tb.Text = RotateMonthClass.titleLan2; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3") { tb.Text = RotateMonthClass.titleLan3; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4") { tb.Text = RotateMonthClass.titleLan4; } } //動態改變 PlaneRotate 內容物件的語系 internal void ChangeLanByDynamic() { this.Dispatcher.BeginInvoke(new DynamicChangeLan(DynamicChangeLanEvent), DispatcherPriority.Background); } private void SetRotateFreq() { changeInfoTimeMin = 8; if (ConfigSettingClass.MainBackCollect.ScreenSetting == 1) { changeInfoTimeMax = 32; } else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 2) { changeInfoTimeMax = 48; } else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 3) { changeInfoTimeMax = 64; } } internal void CreatePlaneRotateMap() { //透過RotateMonthClass取得該PlaneRotateMap 顯示資訊 GetInformationToShow(); } private void GetInformationToShow() { System.Windows.Application.Current.Dispatcher.Invoke(new CreatePlaneRotateMapDelegate(AddRotateInfoToList), DispatcherPriority.Background); //點擊區 uxRotateMainGrid.Children.Add(RectForTouch); } private void SettingRotateMap() { dbOffsetOne = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(RotateAnimationTime), EasingFunction = new PowerEase() { EasingMode = EasingMode.EaseIn, Power = 2 }, }; dbOffsetOne.From = 0; dbOffsetOne.To = 90; dbOffsetTwo = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(RotateAnimationTime), EasingFunction = new PowerEase() { EasingMode = EasingMode.EaseOut, Power = 2 }, }; dbOffsetTwo.From = -90; dbOffsetTwo.To = 0; Storyboard.SetTarget(dbOffsetOne, (DependencyObject)this.FindName("uxMyPlanerator")); Storyboard.SetTargetProperty(dbOffsetOne, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty)); sbStepOne.Children.Add(dbOffsetOne); sbStepOne.FillBehavior = FillBehavior.HoldEnd; sbStepOne.Completed += new EventHandler(sbStepOne_Completed); Storyboard.SetTarget(dbOffsetTwo, (DependencyObject)this.FindName("uxMyPlanerator")); Storyboard.SetTargetProperty(dbOffsetTwo, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty)); sbStepTwo.Children.Add(dbOffsetTwo); sbStepTwo.FillBehavior = FillBehavior.HoldEnd; } /// /// 旋轉 /// public void RotateTheObject() { sbStepOne.Begin(); } public void sbStepOne_Completed(object sender, EventArgs e) { //改變資料 if (ChangeInfo) { SendChangeBlockIndex("Prepare", BlockIndex); } CurrentShowIndex++; ChangeElementForShow(ref CurrentShowIndex); sbStepTwo.Begin(); } /// /// 判斷該資料是否已經到底了~如果是~則通知 LiveContainer /// /// 紀錄已經播放幾筆資料 private void CheckTheFileEndToSend(ref int RecordInfoCount) { if (RecordInfoCount >= ElementForRotateList.Count) { //到底~將該區塊的索引值傳回 LiveContainer SendChangeBlockIndex("DataEnd", BlockIndex); } } /// /// 設定可觸控層以方便之後能夠點擊觸發 /// private void SetTouchLay(int ImageWidth, int ImageHeight) { RectForTouch.Width = ImageWidth; RectForTouch.Height = ImageHeight; RectForTouch.Fill = Brushes.Transparent; RectForTouch.PreviewTouchDown += new EventHandler(RectForTouch_PreviewTouchDown); } void RectForTouch_PreviewTouchDown(object sender, TouchEventArgs e) { //通知被點擊 SendInfoToLiveContainer(indexOfEvent, CurrentShowIndex - 1); } /// /// 該PlaneRotate 顯示資訊 /// public void startShow() { //將紀錄設定為第一筆資料 <一開始會先顯示的資料> RecordInfoCount = 1; //一開始先顯示圖片或者文字(亂數取) CurrentShowIndex = rnd.Next(0, ElementForRotateList.Count); //透過索引值~改變要顯示的是該月份的第幾個資料~文字或者圖~? ChangeElementForShow(ref CurrentShowIndex); } /// /// 停止該PlaneRotate自轉模式 /// public void stopShow() { //清除所有顯示資訊 uxRotateContain.Children.Clear(); ElementForRotateList.Clear(); RotateWaitTime.Stop(); } /// /// 取得下次要翻轉的等待時間 (翻轉開始呼叫函數~) /// public void StartCountDownForRatate() { //亂數取得 int time = rnd.Next(changeInfoTimeMin, changeInfoTimeMax); RotateWaitTime.Interval = TimeSpan.FromSeconds(time); RotateWaitTime.Start(); } //如果等待時間到~則開始旋轉並在設定其下次要旋轉的等待時間 void RotateWaitTime_Tick(object sender, EventArgs e) { RotateWaitTime.Stop(); StartCountDownForRatate(); RotateTheObject(); #region 判斷是否資料已經到底 //該遍資料紀錄值加一 RecordInfoCount++; //判斷該資料是否已經到底了~如果是~則通知 LiveContainer CheckTheFileEndToSend(ref RecordInfoCount); #endregion } /// /// 停止翻轉功能 /// public void StopCountDownForRatate() { RotateWaitTime.Stop(); } /// /// 先將可以顯示的資訊放到 ElementForRotateList 中 /// private void AddRotateInfoToList() { ElementForRotateList.Clear(); #region 先加文字 Grid gridfortext = new Grid(); TextBlock textblock = new TextBlock(); if (ConfigSettingClass.MainBackCollect.DefaultLangIndex < ConfigSettingClass.MainBackCollect.LangFlowDir.Length) { textblock.FlowDirection = ConfigSettingClass.MainBackCollect.LangFlowDir[ConfigSettingClass.MainBackCollect.DefaultLangIndex]; } try { //假如現在是第一種語系 if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1") { textblock.Text = RotateMonthClass.titleLan1; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2") { textblock.Text = RotateMonthClass.titleLan2; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3") { textblock.Text = RotateMonthClass.titleLan3; } else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4") { textblock.Text = RotateMonthClass.titleLan4; } } catch { } gridfortext.VerticalAlignment = System.Windows.VerticalAlignment.Center; gridfortext.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; gridfortext.Width = ImageWidth; gridfortext.Height = ImageHeight; textblock.TextWrapping = TextWrapping.Wrap; textblock.FontSize = TextFontSize; textblock.Foreground = RotateContainTextColor; textblock.Margin = new Thickness(10); gridfortext.Children.Add(textblock); ElementForRotateList.Add(gridfortext); #endregion #region 加圖片 //做法 : 先將 imagepath 路徑下的圖片縮圖, 之後放到 image controller 下再放到 ElementForRotateList 中 if (RotateMonthClass.imagepath != "") { string[] tempFile; if (Directory.Exists(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath)) { tempFile = Directory.GetFiles(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath); // tempFile 為全部的圖片張數,避免記憶體吃太多~ 每個事件框以亂數載入五張為最多 int startupIndex = 0; int targetIndex = 0; bool startGet = true; int maxLoadValue = 5; if (tempFile.Count() > maxLoadValue) { startGet = false; startupIndex = rnd.Next(0, tempFile.Count() - maxLoadValue); } foreach (string item in tempFile) { if (targetIndex != startupIndex && !startGet) { targetIndex++; } else { // 開始取圖 startGet = true; if (maxLoadValue < 0) break; maxLoadValue--; if (imgfilter.Contains(System.IO.Path.GetExtension(item).ToLower())) { Grid gd = new Grid(); Image img = new Image(); FileInfo fileinfo = new FileInfo(item); string FilePath = fileinfo.FullName.ToString().Trim(); RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality); img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(FilePath, ImageWidth); img.Stretch = Stretch.UniformToFill; img.VerticalAlignment = System.Windows.VerticalAlignment.Center; img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; gd.Width = ImageWidth; gd.Height = ImageHeight; gd.Children.Add(img); ElementForRotateList.Add(gd); } else if (mediafilter.Contains(System.IO.Path.GetExtension(item).ToLower())) { Grid gd = new Grid(); Image img = new Image(); FileInfo fileinfo = new FileInfo(item); string FilePath = fileinfo.FullName.ToString().Trim(); // 影片取縮圖 RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality); ShellFile shellFile = ShellFile.FromFilePath(FilePath); BitmapSource shellThumb = shellFile.Thumbnail.ExtraLargeBitmapSource; img.Source = shellThumb; img.Stretch = Stretch.UniformToFill; img.VerticalAlignment = System.Windows.VerticalAlignment.Center; img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; gd.Width = ImageWidth; gd.Height = ImageHeight; gd.Children.Add(img); ElementForRotateList.Add(gd); } } } } } #endregion #region 加預設logo圖 //如果以上圖文只有一個有資料~則加上預設的圖 if (ElementForRotateList.Count <= 1 && ConfigSettingClass.MainBackCollect.ImgLogo != "") { string DefaultLogoPath = ConfigSettingClass.MainBackCollect.ImgLogo; if (File.Exists(GlobalFunction.thumbPath + DefaultLogoPath)) { Grid gd = new Grid(); Image img = new Image(); img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(GlobalFunction.thumbPath + DefaultLogoPath, ImageWidth); img.Stretch = Stretch.Uniform; img.VerticalAlignment = System.Windows.VerticalAlignment.Center; img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; gd.Width = ImageWidth; gd.Height = ImageHeight; gd.Children.Add(img); ElementForRotateList.Add(gd); } } #endregion SendChangeBlockIndex("Load Complete", 0); } /// /// 增加事件~增加從 LiveContainer Callback Event /// /// public void ListenFromLiveContainerCode(LiveContainer liveContainer) { liveContainer.LiveContainerBubbleToPlaneRotateEvent += new LiveContainer.LiveContainerBubbleToPlaneRotateMap(ReceiveFromLiveContainerForFileChange); } /// /// 將該索引加到uxRotateContain /// /// 指向 ElementForRotateList 中的索引值 private void ChangeElementForShow(ref int index) { uxRotateContain.Children.Clear(); if (index >= ElementForRotateList.Count) { //超過資料上限~重頭播放 index = 0; } if (ElementForRotateList.Count == 0) { return; } uxRotateContain.Children.Add(ElementForRotateList[index]); } /// /// 取得圖片Source /// /// 指定圖片路徑 /// private ImageSource GetBitmapImage(string imgpath) { BitmapImage bitmapImg = new BitmapImage(); bitmapImg.BeginInit(); bitmapImg.UriSource = new Uri(imgpath, UriKind.RelativeOrAbsolute); //忽略原始圖檔的色盤設定,使用預設值,可縮短載入圖檔的時間 //如有遇到色彩不正確的問題,或者原圖有特殊的自定義色盤,請不要使用此設定 bitmapImg.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; //使用以下的預先載入設定,在BitmapImage創建完成之後,可立刻釋放其所占用或鎖住的資源,以免咬住檔案 bitmapImg.CacheOption = BitmapCacheOption.OnLoad; //根據欲顯示的區域長或寬,來設定 DecodePixelHeight 或 DecodePixelWidth 的值 //bitmapImg.DecodePixelHeight = THUMB_HEIGHT; //bitmapImg.DecodePixelWidth = THUMB_WIDTH; bitmapImg.EndInit(); bitmapImg.Freeze(); return bitmapImg; } } }