PlaneRotateMap.xaml.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. using Microsoft.WindowsAPICodePack.Shell;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Data;
  11. using System.Windows.Documents;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Animation;
  15. using System.Windows.Media.Imaging;
  16. using System.Windows.Navigation;
  17. using System.Windows.Shapes;
  18. using System.Windows.Threading;
  19. namespace HistoryDLL
  20. {
  21. /// <summary>
  22. /// PlaneRotateMap.xaml 的互動邏輯
  23. /// </summary>
  24. public partial class PlaneRotateMap : UserControl
  25. {
  26. //創造 PlaneRotateMap 物件
  27. private delegate void CreatePlaneRotateMapDelegate();
  28. private delegate void DynamicChangeLan();
  29. private DispatcherTimer RotateWaitTime = new DispatcherTimer();
  30. //該PlaneRotate中有幾個可以顯示的物件
  31. private int ImageWidth, ImageHeight;
  32. private List<FrameworkElement> ElementForRotateList = new List<FrameworkElement>();
  33. private Rectangle RectForTouch = new Rectangle();
  34. //當前顯示的物件是屬於ElementForRotateList中的第幾個索引
  35. private int CurrentShowIndex = 0;
  36. //該輪播塊是屬於該年事件中的第幾個索引
  37. public int indexOfEvent = -1;
  38. //亂數產生
  39. private Random rnd = new Random(Guid.NewGuid().GetHashCode());
  40. //切換資訊的亂數時間範圍 changeInfoTimeMin <= s < changeInfoTimeMax
  41. private int changeInfoTimeMin = 8;
  42. private int changeInfoTimeMax = 32;
  43. //Other Number
  44. private double RotateAngle = 10.0; //區塊旋轉時候的角度
  45. private double TextFontSize = 23; //顯示的資訊如果是文字~則設定文字大小
  46. private int RotateAnimationTime = 400;
  47. private Storyboard sbStepOne = new Storyboard();
  48. private DoubleAnimation dbOffsetOne = new DoubleAnimation();
  49. private Storyboard sbStepTwo = new Storyboard();
  50. private DoubleAnimation dbOffsetTwo = new DoubleAnimation();
  51. private SolidColorBrush RotateContainColor = new SolidColorBrush(ConfigSettingClass.EventCollect.BackgroundColor);
  52. private SolidColorBrush RotateContainTextColor = new SolidColorBrush(ConfigSettingClass.EventCollect.TextColor);
  53. //判斷是否資料已經到底的紀錄的 Index
  54. private int RecordInfoCount = 1;
  55. //資料暫存
  56. public MonthClass RotateMonthClass = new MonthClass();
  57. private string[] imgfilter = { ".jpeg", ".jpg", ".bmp", ".png" };
  58. private string[] mediafilter = { ".mp4", ".wmv", ".mpeg", "mpg", "avi" };
  59. //該PlaneRotateMap在LiveContainer 中的哪個區塊
  60. public int BlockIndex = -1;
  61. public bool ChangeInfo = false;
  62. public PlaneRotateMap()
  63. { InitializeComponent(); }
  64. public PlaneRotateMap(MonthClass sourcemonthClass, int ImageWidth, int ImageHeight)
  65. {
  66. InitializeComponent();
  67. if (GlobalFunction.isSolutionUsing4K)
  68. TextFontSize *= 1.5;
  69. //將暫時設定一下顏色
  70. uxRotateContain.Background = RotateContainColor;
  71. //設定翻轉頻率
  72. SetRotateFreq();
  73. //設定旋轉動作的相關Timer
  74. SettingRotateMap();
  75. RotateWaitTime.Tick += new EventHandler(RotateWaitTime_Tick);
  76. //資料存到緩衝
  77. RotateMonthClass = sourcemonthClass;
  78. //設定寬高
  79. uxRotateContain.Width = uxRotateMainGrid.Width = this.ImageWidth = ImageWidth;
  80. uxRotateContain.Height = uxRotateMainGrid.Height = this.ImageHeight = ImageHeight;
  81. //設定可觸控層
  82. SetTouchLay(ImageWidth, ImageHeight);
  83. //翻轉角度設定
  84. uxMyPlanerator.FieldOfView = RotateAngle;
  85. }
  86. private void DynamicChangeLanEvent()
  87. {
  88. //第 0 個一定是文字
  89. Grid gd = ElementForRotateList[0] as Grid;
  90. TextBlock tb = gd.Children[0] as TextBlock;
  91. //假如現在是第一種語系
  92. if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1")
  93. {
  94. tb.Text = RotateMonthClass.titleLan1;
  95. }
  96. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2")
  97. {
  98. tb.Text = RotateMonthClass.titleLan2;
  99. }
  100. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3")
  101. {
  102. tb.Text = RotateMonthClass.titleLan3;
  103. }
  104. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4")
  105. {
  106. tb.Text = RotateMonthClass.titleLan4;
  107. }
  108. }
  109. //動態改變 PlaneRotate 內容物件的語系
  110. internal void ChangeLanByDynamic()
  111. {
  112. this.Dispatcher.BeginInvoke(new DynamicChangeLan(DynamicChangeLanEvent),
  113. DispatcherPriority.Background);
  114. }
  115. private void SetRotateFreq()
  116. {
  117. changeInfoTimeMin = 8;
  118. if (ConfigSettingClass.MainBackCollect.ScreenSetting == 1)
  119. {
  120. changeInfoTimeMax = 32;
  121. }
  122. else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 2)
  123. {
  124. changeInfoTimeMax = 48;
  125. }
  126. else if (ConfigSettingClass.MainBackCollect.ScreenSetting == 3)
  127. {
  128. changeInfoTimeMax = 64;
  129. }
  130. }
  131. internal void CreatePlaneRotateMap()
  132. {
  133. //透過RotateMonthClass取得該PlaneRotateMap 顯示資訊
  134. GetInformationToShow();
  135. }
  136. private void GetInformationToShow()
  137. {
  138. System.Windows.Application.Current.Dispatcher.Invoke(new CreatePlaneRotateMapDelegate(AddRotateInfoToList), DispatcherPriority.Background);
  139. //點擊區
  140. uxRotateMainGrid.Children.Add(RectForTouch);
  141. }
  142. private void SettingRotateMap()
  143. {
  144. dbOffsetOne = new DoubleAnimation()
  145. {
  146. Duration = TimeSpan.FromMilliseconds(RotateAnimationTime),
  147. EasingFunction = new PowerEase()
  148. {
  149. EasingMode = EasingMode.EaseIn,
  150. Power = 2
  151. },
  152. };
  153. dbOffsetOne.From = 0;
  154. dbOffsetOne.To = 90;
  155. dbOffsetTwo = new DoubleAnimation()
  156. {
  157. Duration = TimeSpan.FromMilliseconds(RotateAnimationTime),
  158. EasingFunction = new PowerEase()
  159. {
  160. EasingMode = EasingMode.EaseOut,
  161. Power = 2
  162. },
  163. };
  164. dbOffsetTwo.From = -90;
  165. dbOffsetTwo.To = 0;
  166. Storyboard.SetTarget(dbOffsetOne, (DependencyObject)this.FindName("uxMyPlanerator"));
  167. Storyboard.SetTargetProperty(dbOffsetOne, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty));
  168. sbStepOne.Children.Add(dbOffsetOne);
  169. sbStepOne.FillBehavior = FillBehavior.HoldEnd;
  170. sbStepOne.Completed += new EventHandler(sbStepOne_Completed);
  171. Storyboard.SetTarget(dbOffsetTwo, (DependencyObject)this.FindName("uxMyPlanerator"));
  172. Storyboard.SetTargetProperty(dbOffsetTwo, new PropertyPath(NLPlaneRotator.PlaneRotator.RotationXProperty));
  173. sbStepTwo.Children.Add(dbOffsetTwo);
  174. sbStepTwo.FillBehavior = FillBehavior.HoldEnd;
  175. }
  176. /// <summary>
  177. /// 旋轉
  178. /// </summary>
  179. public void RotateTheObject()
  180. {
  181. sbStepOne.Begin();
  182. }
  183. public void sbStepOne_Completed(object sender, EventArgs e)
  184. {
  185. //改變資料
  186. if (ChangeInfo)
  187. {
  188. SendChangeBlockIndex("Prepare", BlockIndex);
  189. }
  190. CurrentShowIndex++;
  191. ChangeElementForShow(ref CurrentShowIndex);
  192. sbStepTwo.Begin();
  193. }
  194. /// <summary>
  195. /// 判斷該資料是否已經到底了~如果是~則通知 LiveContainer
  196. /// </summary>
  197. /// <param name="RecordInfoCount">紀錄已經播放幾筆資料</param>
  198. private void CheckTheFileEndToSend(ref int RecordInfoCount)
  199. {
  200. if (RecordInfoCount >= ElementForRotateList.Count)
  201. {
  202. //到底~將該區塊的索引值傳回 LiveContainer
  203. SendChangeBlockIndex("DataEnd", BlockIndex);
  204. }
  205. }
  206. /// <summary>
  207. /// 設定可觸控層以方便之後能夠點擊觸發
  208. /// </summary>
  209. private void SetTouchLay(int ImageWidth, int ImageHeight)
  210. {
  211. RectForTouch.Width = ImageWidth;
  212. RectForTouch.Height = ImageHeight;
  213. RectForTouch.Fill = Brushes.Transparent;
  214. RectForTouch.PreviewTouchDown += new EventHandler<TouchEventArgs>(RectForTouch_PreviewTouchDown);
  215. }
  216. void RectForTouch_PreviewTouchDown(object sender, TouchEventArgs e)
  217. {
  218. //通知被點擊
  219. SendInfoToLiveContainer(indexOfEvent, CurrentShowIndex - 1);
  220. }
  221. /// <summary>
  222. /// 該PlaneRotate 顯示資訊
  223. /// </summary>
  224. public void startShow()
  225. {
  226. //將紀錄設定為第一筆資料 <一開始會先顯示的資料>
  227. RecordInfoCount = 1;
  228. //一開始先顯示圖片或者文字(亂數取)
  229. CurrentShowIndex = rnd.Next(0, ElementForRotateList.Count);
  230. //透過索引值~改變要顯示的是該月份的第幾個資料~文字或者圖~?
  231. ChangeElementForShow(ref CurrentShowIndex);
  232. }
  233. /// <summary>
  234. /// 停止該PlaneRotate自轉模式
  235. /// </summary>
  236. public void stopShow()
  237. {
  238. //清除所有顯示資訊
  239. uxRotateContain.Children.Clear();
  240. ElementForRotateList.Clear();
  241. RotateWaitTime.Stop();
  242. }
  243. /// <summary>
  244. /// 取得下次要翻轉的等待時間 (翻轉開始呼叫函數~)
  245. /// </summary>
  246. public void StartCountDownForRatate()
  247. {
  248. //亂數取得
  249. int time = rnd.Next(changeInfoTimeMin, changeInfoTimeMax);
  250. RotateWaitTime.Interval = TimeSpan.FromSeconds(time);
  251. RotateWaitTime.Start();
  252. }
  253. //如果等待時間到~則開始旋轉並在設定其下次要旋轉的等待時間
  254. void RotateWaitTime_Tick(object sender, EventArgs e)
  255. {
  256. RotateWaitTime.Stop();
  257. StartCountDownForRatate();
  258. RotateTheObject();
  259. #region 判斷是否資料已經到底
  260. //該遍資料紀錄值加一
  261. RecordInfoCount++;
  262. //判斷該資料是否已經到底了~如果是~則通知 LiveContainer
  263. CheckTheFileEndToSend(ref RecordInfoCount);
  264. #endregion
  265. }
  266. /// <summary>
  267. /// 停止翻轉功能
  268. /// </summary>
  269. public void StopCountDownForRatate()
  270. {
  271. RotateWaitTime.Stop();
  272. }
  273. /// <summary>
  274. /// 先將可以顯示的資訊放到 ElementForRotateList 中
  275. /// </summary>
  276. private void AddRotateInfoToList()
  277. {
  278. ElementForRotateList.Clear();
  279. #region 先加文字
  280. Grid gridfortext = new Grid();
  281. TextBlock textblock = new TextBlock();
  282. if (ConfigSettingClass.MainBackCollect.DefaultLangIndex < ConfigSettingClass.MainBackCollect.LangFlowDir.Length)
  283. {
  284. textblock.FlowDirection = ConfigSettingClass.MainBackCollect.LangFlowDir[ConfigSettingClass.MainBackCollect.DefaultLangIndex];
  285. }
  286. try
  287. {
  288. //假如現在是第一種語系
  289. if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language1")
  290. {
  291. textblock.Text = RotateMonthClass.titleLan1;
  292. }
  293. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language2")
  294. {
  295. textblock.Text = RotateMonthClass.titleLan2;
  296. }
  297. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language3")
  298. {
  299. textblock.Text = RotateMonthClass.titleLan3;
  300. }
  301. else if (System.Windows.Application.Current.Properties["Language"].ToString() == "Language4")
  302. {
  303. textblock.Text = RotateMonthClass.titleLan4;
  304. }
  305. }
  306. catch
  307. {
  308. }
  309. gridfortext.VerticalAlignment = System.Windows.VerticalAlignment.Center;
  310. gridfortext.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
  311. gridfortext.Width = ImageWidth;
  312. gridfortext.Height = ImageHeight;
  313. textblock.TextWrapping = TextWrapping.Wrap;
  314. textblock.FontSize = TextFontSize;
  315. textblock.Foreground = RotateContainTextColor;
  316. textblock.Margin = new Thickness(10);
  317. gridfortext.Children.Add(textblock);
  318. ElementForRotateList.Add(gridfortext);
  319. #endregion
  320. #region 加圖片
  321. //做法 : 先將 imagepath 路徑下的圖片縮圖, 之後放到 image controller 下再放到 ElementForRotateList 中
  322. if (RotateMonthClass.imagepath != "")
  323. {
  324. string[] tempFile;
  325. if (Directory.Exists(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath))
  326. {
  327. tempFile = Directory.GetFiles(GlobalFunction.EventFileImgPath + RotateMonthClass.imagepath);
  328. // tempFile 為全部的圖片張數,避免記憶體吃太多~ 每個事件框以亂數載入五張為最多
  329. int startupIndex = 0;
  330. int targetIndex = 0;
  331. bool startGet = true;
  332. int maxLoadValue = 5;
  333. if (tempFile.Count() > maxLoadValue)
  334. {
  335. startGet = false;
  336. startupIndex = rnd.Next(0, tempFile.Count() - maxLoadValue);
  337. }
  338. foreach (string item in tempFile)
  339. {
  340. if (targetIndex != startupIndex && !startGet)
  341. {
  342. targetIndex++;
  343. }
  344. else
  345. {
  346. // 開始取圖
  347. startGet = true;
  348. if (maxLoadValue < 0)
  349. break;
  350. maxLoadValue--;
  351. if (imgfilter.Contains(System.IO.Path.GetExtension(item).ToLower()))
  352. {
  353. Grid gd = new Grid();
  354. Image img = new Image();
  355. FileInfo fileinfo = new FileInfo(item);
  356. string FilePath = fileinfo.FullName.ToString().Trim();
  357. RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
  358. img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(FilePath, ImageWidth);
  359. img.Stretch = Stretch.UniformToFill;
  360. img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
  361. img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
  362. gd.Width = ImageWidth;
  363. gd.Height = ImageHeight;
  364. gd.Children.Add(img);
  365. ElementForRotateList.Add(gd);
  366. }
  367. else if (mediafilter.Contains(System.IO.Path.GetExtension(item).ToLower()))
  368. {
  369. Grid gd = new Grid();
  370. Image img = new Image();
  371. FileInfo fileinfo = new FileInfo(item);
  372. string FilePath = fileinfo.FullName.ToString().Trim();
  373. // 影片取縮圖
  374. RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
  375. ShellFile shellFile = ShellFile.FromFilePath(FilePath);
  376. BitmapSource shellThumb = shellFile.Thumbnail.ExtraLargeBitmapSource;
  377. img.Source = shellThumb;
  378. img.Stretch = Stretch.UniformToFill;
  379. img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
  380. img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
  381. gd.Width = ImageWidth;
  382. gd.Height = ImageHeight;
  383. gd.Children.Add(img);
  384. ElementForRotateList.Add(gd);
  385. }
  386. }
  387. }
  388. }
  389. }
  390. #endregion
  391. #region 加預設logo圖
  392. //如果以上圖文只有一個有資料~則加上預設的圖
  393. if (ElementForRotateList.Count <= 1 && ConfigSettingClass.MainBackCollect.ImgLogo != "")
  394. {
  395. string DefaultLogoPath = ConfigSettingClass.MainBackCollect.ImgLogo;
  396. if (File.Exists(GlobalFunction.thumbPath + DefaultLogoPath))
  397. {
  398. Grid gd = new Grid();
  399. Image img = new Image();
  400. img.Source = MediaViewerLib.Utilities.MediaUtilties.LoadBitmapImage(GlobalFunction.thumbPath + DefaultLogoPath, ImageWidth);
  401. img.Stretch = Stretch.Uniform;
  402. img.VerticalAlignment = System.Windows.VerticalAlignment.Center;
  403. img.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
  404. gd.Width = ImageWidth;
  405. gd.Height = ImageHeight;
  406. gd.Children.Add(img);
  407. ElementForRotateList.Add(gd);
  408. }
  409. }
  410. #endregion
  411. SendChangeBlockIndex("Load Complete", 0);
  412. }
  413. /// <summary>
  414. /// 增加事件~增加從 LiveContainer Callback Event
  415. /// </summary>
  416. /// <param name="liveContainer"></param>
  417. public void ListenFromLiveContainerCode(LiveContainer liveContainer)
  418. {
  419. liveContainer.LiveContainerBubbleToPlaneRotateEvent += new LiveContainer.LiveContainerBubbleToPlaneRotateMap(ReceiveFromLiveContainerForFileChange);
  420. }
  421. /// <summary>
  422. /// 將該索引加到uxRotateContain
  423. /// </summary>
  424. /// <param name="CurrentShowIndex">指向 ElementForRotateList 中的索引值</param>
  425. private void ChangeElementForShow(ref int index)
  426. {
  427. uxRotateContain.Children.Clear();
  428. if (index >= ElementForRotateList.Count)
  429. {
  430. //超過資料上限~重頭播放
  431. index = 0;
  432. }
  433. if (ElementForRotateList.Count == 0)
  434. {
  435. return;
  436. }
  437. uxRotateContain.Children.Add(ElementForRotateList[index]);
  438. }
  439. /// <summary>
  440. /// 取得圖片Source
  441. /// </summary>
  442. /// <param name="imgpath">指定圖片路徑</param>
  443. /// <returns></returns>
  444. private ImageSource GetBitmapImage(string imgpath)
  445. {
  446. BitmapImage bitmapImg = new BitmapImage();
  447. bitmapImg.BeginInit();
  448. bitmapImg.UriSource = new Uri(imgpath, UriKind.RelativeOrAbsolute);
  449. //忽略原始圖檔的色盤設定,使用預設值,可縮短載入圖檔的時間
  450. //如有遇到色彩不正確的問題,或者原圖有特殊的自定義色盤,請不要使用此設定
  451. bitmapImg.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
  452. //使用以下的預先載入設定,在BitmapImage創建完成之後,可立刻釋放其所占用或鎖住的資源,以免咬住檔案
  453. bitmapImg.CacheOption = BitmapCacheOption.OnLoad;
  454. //根據欲顯示的區域長或寬,來設定 DecodePixelHeight 或 DecodePixelWidth 的值
  455. //bitmapImg.DecodePixelHeight = THUMB_HEIGHT;
  456. //bitmapImg.DecodePixelWidth = THUMB_WIDTH;
  457. bitmapImg.EndInit();
  458. bitmapImg.Freeze();
  459. return bitmapImg;
  460. }
  461. }
  462. }