星火微课系统客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

XHMicroLessonSystemWindow.xaml.cs 22KB

4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. using Aspose.Words;
  2. using Aspose.Words.Saving;
  3. using Common.system;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Threading;
  9. using System.Windows;
  10. using System.Windows.Forms;
  11. using System.Windows.Ink;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Imaging;
  15. namespace XHWK.WKTool
  16. {
  17. /// <summary>
  18. /// 主页面
  19. /// </summary>
  20. public partial class XHMicroLessonSystemWindow : Window
  21. {
  22. #region 初始值
  23. /// <summary>
  24. /// 文件目录窗口
  25. /// </summary>
  26. //private CountdownWindow FileDirectoryWindows = null;
  27. private FolderBrowserDialog Ofd;
  28. private DialogResult Result;
  29. public readonly BlackboardNew myblackboard;
  30. private System.Windows.Forms.DialogResult result;
  31. private System.Windows.Forms.OpenFileDialog ofd;
  32. #endregion
  33. #region 初始化
  34. /// <summary>
  35. /// 主页面
  36. /// </summary>
  37. public XHMicroLessonSystemWindow()
  38. {
  39. InitializeComponent();
  40. myblackboard = new BlackboardNew(blackboard_canvas);
  41. APP.pageData.pagenum = 1;
  42. APP.pageData.currpage = 1;
  43. DataContext = APP.pageData;
  44. Initialize();
  45. }
  46. /// <summary>
  47. /// 初始化
  48. /// </summary>
  49. public void Initialize()
  50. {
  51. //创建 DrawingAttributes 类的一个实例
  52. drawingAttributes = new DrawingAttributes();
  53. //将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
  54. //InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
  55. blackboard_canvas.DefaultDrawingAttributes = drawingAttributes;
  56. drawingAttributes.FitToCurve = true;
  57. wfhCamera.Visibility = Visibility.Hidden;
  58. }
  59. #endregion
  60. #region 事件
  61. /// <summary>
  62. /// 窗体移动
  63. /// </summary>
  64. /// <param name="sender"></param>
  65. /// <param name="e"></param>
  66. private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  67. {
  68. DragMove();
  69. }
  70. /// <summary>
  71. /// 摄像头打开事件
  72. /// </summary>
  73. /// <param name="sender"></param>
  74. /// <param name="e"></param>
  75. private void RbnOpen_Click(object sender, RoutedEventArgs e)
  76. {
  77. //UCCamera win = new UCCamera();
  78. ////win.Topmost = true;
  79. //win.ShowDialog();
  80. wfhCamera.Visibility = Visibility.Visible;
  81. CameraHelper.IsDisplay = true;
  82. CameraHelper.SourcePlayer = player;
  83. CameraHelper.UpdateCameraDevices();
  84. if (CameraHelper.CameraDevices.Count > 0)
  85. {
  86. CameraHelper.SetCameraDevice(0);
  87. }
  88. }
  89. /// <summary>
  90. /// 摄像头关闭事件
  91. /// </summary>
  92. /// <param name="sender"></param>
  93. /// <param name="e"></param>
  94. private void RbnTurnOff_Click(object sender, RoutedEventArgs e)
  95. {
  96. wfhCamera.Visibility = Visibility.Hidden;
  97. CameraHelper.CloseDevice();
  98. }
  99. #endregion
  100. /// <summary>
  101. /// 录屏事件
  102. /// </summary>
  103. /// <param name="sender"></param>
  104. /// <param name="e"></param>
  105. private void BtnScreenRecording_Click(object sender, RoutedEventArgs e)
  106. {
  107. if(APP.IsLoginType==false)
  108. {
  109. Login();
  110. return;
  111. }
  112. if (APP.W_CountdownWindow == null)
  113. {
  114. APP.W_CountdownWindow = new CountdownWindow();
  115. //APP.W_CountdownWindow.Topmost = true;
  116. }
  117. else
  118. {
  119. APP.W_CountdownWindow.Initialize();
  120. APP.W_CountdownWindow.Topmost = true;
  121. }
  122. APP.W_CountdownWindow.Show();
  123. if (APP.W_ScreenRecordingToolbarWindow == null)
  124. {
  125. APP.W_ScreenRecordingToolbarWindow = new ScreenRecordingToolbarWindow
  126. {
  127. Topmost = true
  128. };
  129. APP.W_ScreenRecordingToolbarWindow.Initialize();
  130. }
  131. else
  132. {
  133. APP.W_ScreenRecordingToolbarWindow.Initialize();
  134. }
  135. //显示在右下角
  136. //APP.W_ScreenRecordingToolbarWindow.Left= PrimaryScreen.DESKTOP.Width - APP.W_ScreenRecordingToolbarWindow.Width - 10;
  137. //APP.W_ScreenRecordingToolbarWindow.Top= PrimaryScreen.DESKTOP.Height - APP.W_ScreenRecordingToolbarWindow.Height - 60;
  138. this.Hide();
  139. Hide();
  140. }
  141. /// <summary>
  142. /// 上传事件
  143. /// </summary>
  144. /// <param name="sender"></param>
  145. /// <param name="e"></param>
  146. private void BtnUpload_Click(object sender, RoutedEventArgs e)
  147. {
  148. if (APP.IsLoginType == false)
  149. {
  150. Login();
  151. return;
  152. }
  153. FileDirectoryWindow fileDirectoryWindow = new FileDirectoryWindow();
  154. fileDirectoryWindow.Show();
  155. }
  156. /// <summary>
  157. /// 关闭事件
  158. /// </summary>
  159. /// <param name="sender"></param>
  160. /// <param name="e"></param>
  161. private void BtnDown_Click(object sender, RoutedEventArgs e)
  162. {
  163. this.Close();
  164. }
  165. /// <summary>
  166. /// 设置 保存事件
  167. /// </summary>
  168. /// <param name="sender"></param>
  169. /// <param name="e"></param>
  170. private void BtnSave_Click(object sender, RoutedEventArgs e)
  171. {
  172. gridMain.Visibility = Visibility.Visible;
  173. gridSetUp.Visibility = Visibility.Collapsed;
  174. }
  175. /// <summary>
  176. /// 设置事件
  177. /// </summary>
  178. /// <param name="sender"></param>
  179. /// <param name="e"></param>
  180. private void BtnSetUp_Click(object sender, RoutedEventArgs e)
  181. {
  182. gridMain.Visibility = Visibility.Collapsed;
  183. gridSetUp.Visibility = Visibility.Visible;
  184. }
  185. /// <summary>
  186. /// 设置 浏览事件
  187. /// </summary>
  188. /// <param name="sender"></param>
  189. /// <param name="e"></param>
  190. private void BtnBrowse_Click(object sender, RoutedEventArgs e)
  191. {
  192. string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
  193. Ofd = new System.Windows.Forms.FolderBrowserDialog();
  194. Result = Ofd.ShowDialog();
  195. if (Result == System.Windows.Forms.DialogResult.OK)
  196. {
  197. if (Ofd.SelectedPath != "")
  198. {
  199. txbStoragePath.Text = Ofd.SelectedPath;
  200. //string ApplicationData = ZConfig.dataPath + "fileStorageAddress.txt";
  201. //string temp = ofd.SelectedPath;
  202. //System.IO.File.WriteAllText(ApplicationData, temp, Encoding.Default);
  203. }
  204. }
  205. }
  206. /// <summary>
  207. /// 画笔颜色事件 白色
  208. /// </summary>
  209. /// <param name="sender"></param>
  210. /// <param name="e"></param>
  211. private void BtnWhite_Click(object sender, RoutedEventArgs e)
  212. {
  213. //创建 DrawingAttributes 类的一个实例
  214. drawingAttributes = new DrawingAttributes();
  215. //将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
  216. //InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
  217. blackboard_canvas.DefaultDrawingAttributes = drawingAttributes;
  218. //设置 DrawingAttributes 的 Color 属性设置颜色
  219. drawingAttributes.Color = Colors.White;
  220. }
  221. //声明一个 DrawingAttributes 类型的变量
  222. DrawingAttributes drawingAttributes;
  223. /// <summary>
  224. /// 画笔颜色事件 红色
  225. /// </summary>
  226. /// <param name="sender"></param>
  227. /// <param name="e"></param>
  228. private void BtnRed_Click(object sender, RoutedEventArgs e)
  229. {
  230. //设置 DrawingAttributes 的 Color 属性设置颜色
  231. drawingAttributes.Color = Colors.Red;
  232. }
  233. /// <summary>
  234. /// 画笔颜色事件 灰色
  235. /// </summary>
  236. /// <param name="sender"></param>
  237. /// <param name="e"></param>
  238. private void BtnGray_Click(object sender, RoutedEventArgs e)
  239. {
  240. drawingAttributes.Color = Colors.Gray;
  241. }
  242. /// <summary>
  243. /// 画笔颜色事件 青色
  244. /// </summary>
  245. /// <param name="sender"></param>
  246. /// <param name="e"></param>
  247. private void BtnCyanBlue_Click(object sender, RoutedEventArgs e)
  248. {
  249. drawingAttributes.Color = Colors.LimeGreen;
  250. }
  251. /// <summary>
  252. /// 画笔颜色事件 黄色
  253. /// </summary>
  254. /// <param name="sender"></param>
  255. /// <param name="e"></param>
  256. private void BtnYellow_Click(object sender, RoutedEventArgs e)
  257. {
  258. drawingAttributes.Color = Colors.Gold;
  259. }
  260. /// <summary>
  261. /// 画笔颜色事件 蓝色
  262. /// </summary>
  263. /// <param name="sender"></param>
  264. /// <param name="e"></param>
  265. private void BtnBlue_Click(object sender, RoutedEventArgs e)
  266. {
  267. drawingAttributes.Color = Colors.DeepSkyBlue;
  268. }
  269. /// <summary>
  270. /// 画笔粗细 细
  271. /// </summary>
  272. /// <param name="sender"></param>
  273. /// <param name="e"></param>
  274. private void RbnFine_Click(object sender, RoutedEventArgs e)
  275. {
  276. drawingAttributes.Width = 1;
  277. drawingAttributes.Height = 1;
  278. }
  279. /// <summary>
  280. /// 画笔粗细 中
  281. /// </summary>
  282. /// <param name="sender"></param>
  283. /// <param name="e"></param>
  284. private void RbnIn_Click(object sender, RoutedEventArgs e)
  285. {
  286. drawingAttributes.Width = 3;
  287. drawingAttributes.Height = 3;
  288. }
  289. /// <summary>
  290. /// 画笔粗细 粗
  291. /// </summary>
  292. /// <param name="sender"></param>
  293. /// <param name="e"></param>
  294. private void RbnCrude_Click(object sender, RoutedEventArgs e)
  295. {
  296. drawingAttributes.Width = 5;
  297. drawingAttributes.Height = 5;
  298. }
  299. /// <summary>
  300. /// 登陆
  301. /// </summary>
  302. /// <param name="sender"></param>
  303. /// <param name="e"></param>
  304. private void BtnLoginType_Click(object sender, RoutedEventArgs e)
  305. {
  306. Login();
  307. }
  308. /// <summary>
  309. /// 登陆
  310. /// </summary>
  311. private void Login()
  312. {
  313. if (APP.W_LoginWindow == null)
  314. {
  315. APP.W_LoginWindow = new LoginWindow();
  316. }
  317. else
  318. {
  319. APP.W_LoginWindow.Initialize();
  320. }
  321. APP.W_LoginWindow.ShowDialog();
  322. if (APP.IsLoginType)
  323. {
  324. txbLoginType.Text = APP.UserInfo.Username;
  325. }
  326. else
  327. {
  328. txbLoginType.Text = "未登录";
  329. }
  330. }
  331. /// <summary>
  332. /// 截图事件
  333. /// </summary>
  334. /// <param name="sender"></param>
  335. /// <param name="e"></param>
  336. private void BtnScreenshot_Click(object sender, RoutedEventArgs e)
  337. {
  338. if (APP.IsLoginType == false)
  339. {
  340. Login();
  341. return;
  342. }
  343. }
  344. /// <summary>
  345. /// 导入
  346. /// </summary>
  347. /// <param name="sender"></param>
  348. /// <param name="e"></param>
  349. private void BtnImport_Click(object sender, RoutedEventArgs e)
  350. {
  351. if (APP.IsLoginType == false)
  352. {
  353. Login();
  354. return;
  355. }
  356. try
  357. {
  358. string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
  359. ofd = new System.Windows.Forms.OpenFileDialog
  360. {
  361. Filter = "文档|*.docx;*.doc",
  362. InitialDirectory = desktopPath,
  363. Multiselect = false,
  364. AddExtension = true,
  365. DereferenceLinks = true
  366. };
  367. new Thread(
  368. o =>
  369. {
  370. Thread.Sleep(400);
  371. Dispatcher.Invoke(new Action(() =>
  372. {
  373. openDialog();
  374. }
  375. ));
  376. })
  377. {
  378. IsBackground = true
  379. }.Start();
  380. }
  381. catch (Exception ex)
  382. {
  383. LogHelper.WriteErrLog("【导入(BtnImport_Click)" + ex.Message, ex);
  384. }
  385. }
  386. private void openDialog()
  387. {
  388. result = ofd.ShowDialog();
  389. if (result == System.Windows.Forms.DialogResult.OK)
  390. {
  391. if (ofd.FileName != "")
  392. {
  393. string filepath = ofd.FileName;
  394. string path = AppDomain.CurrentDomain.BaseDirectory+ "Temp\\";
  395. APP.Paths = ConvertWordToImage(filepath, path, "", 0, 0, null, 0).ToArray();
  396. if(!string.IsNullOrWhiteSpace(txbCurrpage.Text)&& Convert.ToInt32(txbCurrpage.Text)< APP.Paths.Length)
  397. {
  398. imgCanvas.Source = new BitmapImage(new Uri(APP.Paths[Convert.ToInt32(txbCurrpage.Text) - 1]));
  399. }
  400. else
  401. {
  402. imgCanvas.Source = null;
  403. }
  404. }
  405. }
  406. }
  407. /// <summary>
  408. /// 录制窗口内容
  409. /// </summary>
  410. /// <param name="sender"></param>
  411. /// <param name="e"></param>
  412. private void BtnRecord_Click(object sender, RoutedEventArgs e)
  413. {
  414. if (APP.IsLoginType == false)
  415. {
  416. Login();
  417. return;
  418. }
  419. }
  420. /// <summary>
  421. /// 停止录制窗口内容
  422. /// </summary>
  423. /// <param name="sender"></param>
  424. /// <param name="e"></param>
  425. private void BtnStop_Click(object sender, RoutedEventArgs e)
  426. {
  427. if (APP.IsLoginType == false)
  428. {
  429. Login();
  430. return;
  431. }
  432. }
  433. /// <summary>
  434. /// 增加
  435. /// </summary>
  436. /// <param name="sender"></param>
  437. /// <param name="e"></param>
  438. private void BtnAdd_Click(object sender, RoutedEventArgs e)
  439. {
  440. if (APP.IsLoginType == false)
  441. {
  442. Login();
  443. return;
  444. }
  445. }
  446. /// <summary>
  447. /// 打印
  448. /// </summary>
  449. /// <param name="sender"></param>
  450. /// <param name="e"></param>
  451. private void BtnPrint_Click(object sender, RoutedEventArgs e)
  452. {
  453. }
  454. /// <summary>
  455. /// 我的
  456. /// </summary>
  457. /// <param name="sender"></param>
  458. /// <param name="e"></param>
  459. private void BtnMyMine_Click(object sender, RoutedEventArgs e)
  460. {
  461. if (APP.IsLoginType == false)
  462. {
  463. Login();
  464. return;
  465. }
  466. }
  467. /// <summary>
  468. /// 上一页
  469. /// </summary>
  470. /// <param name="sender"></param>
  471. /// <param name="e"></param>
  472. private void last_button_Click(object sender, RoutedEventArgs e)
  473. {
  474. if (APP.pageData.currpage > 1)
  475. {
  476. APP.pageData.currpage -= 1;
  477. myblackboard.changepage(APP.pageData.currpage - 1);
  478. if(APP.Paths.Length>0)
  479. {
  480. if (!string.IsNullOrWhiteSpace(txbCurrpage.Text) && Convert.ToInt32(txbCurrpage.Text) < APP.Paths.Length&& Convert.ToInt32(txbCurrpage.Text)>1)
  481. {
  482. imgCanvas.Source = new BitmapImage(new Uri(APP.Paths[Convert.ToInt32(txbCurrpage.Text) - 2]));
  483. }
  484. else
  485. {
  486. imgCanvas.Source = null;
  487. }
  488. }
  489. }
  490. }
  491. /// <summary>
  492. /// 下一页
  493. /// </summary>
  494. /// <param name="sender"></param>
  495. /// <param name="e"></param>
  496. private void next_btn_Click(object sender, RoutedEventArgs e)
  497. {
  498. if (APP.pageData.currpage < APP.pageData.pagenum)
  499. {
  500. APP.pageData.currpage += 1;
  501. myblackboard.changepage(APP.pageData.currpage - 1);
  502. if (APP.Paths.Length > 0)
  503. {
  504. if (!string.IsNullOrWhiteSpace(txbCurrpage.Text) && Convert.ToInt32(txbCurrpage.Text)+1 < APP.Paths.Length)
  505. {
  506. imgCanvas.Source = new BitmapImage(new Uri(APP.Paths[Convert.ToInt32(txbCurrpage.Text) ]));
  507. }
  508. else
  509. {
  510. imgCanvas.Source = null;
  511. }
  512. }
  513. }
  514. }
  515. /// <summary>
  516. /// 添加
  517. /// </summary>
  518. /// <param name="sender"></param>
  519. /// <param name="e"></param>
  520. private void add_button_Click(object sender, RoutedEventArgs e)
  521. {
  522. APP.pageData.pagenum += 1;
  523. APP.pageData.currpage = APP.pageData.pagenum;
  524. myblackboard.changepage(APP.pageData.currpage - 1);
  525. }
  526. /// <summary>
  527. /// 将Word文档转换为图片的方法(该方法基于第三方DLL),你可以像这样调用该方法: ConvertPDF2Image("F:\\PdfFile.doc", "F:\\",
  528. /// "ImageFile", 1, 20, ImageFormat.Png, 256);
  529. /// </summary>
  530. /// <param name="pdfInputPath">Word文件路径</param>
  531. /// <param name="imageOutputPath">图片输出路径,如果为空,默认值为Word所在路径</param>
  532. /// <param name="imageName">图片的名字,不需要带扩展名,如果为空,默认值为Word的名称</param>
  533. /// <param name="startPageNum">从PDF文档的第几页开始转换,如果为0,默认值为1</param>
  534. /// <param name="endPageNum">从PDF文档的第几页开始停止转换,如果为0,默认值为Word总页数</param>
  535. /// <param name="imageFormat">设置所需图片格式,如果为null,默认格式为PNG</param>
  536. /// <param name="resolution">设置图片的像素,数字越大越清晰,如果为0,默认值为128,建议最大值不要超过1024</param>
  537. public List<string> ConvertWordToImage(string wordInputPath, string imageOutputPath,
  538. string imageName, int startPageNum, int endPageNum, ImageFormat imageFormat, float resolution)
  539. {
  540. // 返回的图片绝对路径集合
  541. List<string> images = new List<string>();
  542. try
  543. {
  544. // open word file
  545. Aspose.Words.Document doc = new Aspose.Words.Document(wordInputPath);
  546. // validate parameter
  547. if (doc == null) { throw new Exception("Word文件无效或者Word文件被加密!"); }
  548. if (imageOutputPath.Trim().Length == 0) { imageOutputPath = Path.GetDirectoryName(wordInputPath); }
  549. if (!Directory.Exists(imageOutputPath)) { Directory.CreateDirectory(imageOutputPath); }
  550. if (imageName.Trim().Length == 0) { imageName = Path.GetFileNameWithoutExtension(wordInputPath); }
  551. if (startPageNum <= 0) { startPageNum = 1; }
  552. if (endPageNum > doc.PageCount || endPageNum <= 0) { endPageNum = doc.PageCount; }
  553. if (startPageNum > endPageNum) { int tempPageNum = startPageNum; startPageNum = endPageNum; endPageNum = startPageNum; }
  554. if (imageFormat == null) { imageFormat = ImageFormat.Png; }
  555. if (resolution <= 0) { resolution = 128; }
  556. ImageSaveOptions imageSaveOptions = new ImageSaveOptions(GetSaveFormat(imageFormat))
  557. {
  558. Resolution = resolution
  559. };
  560. // start to convert each page
  561. for (int i = startPageNum; i <= endPageNum; i++)
  562. {
  563. imageSaveOptions.PageIndex = i - 1;
  564. doc.Save(Path.Combine(imageOutputPath, imageName) + "_" + APP.num.ToString() + "." + imageFormat.ToString(), imageSaveOptions);
  565. images.Add(Path.Combine(imageOutputPath, imageName) + "_" + APP.num.ToString() + "." + imageFormat.ToString());
  566. APP.num++;
  567. }
  568. imageSaveOptions = null;
  569. doc = null;
  570. }
  571. catch (Exception ex)
  572. {
  573. System.Windows.MessageBox.Show("文档已打开,请关闭后重试!");
  574. LogHelper.WriteErrLog("【课堂考试(ExamWindow)】错误日志:" + ex.Message, ex);
  575. }
  576. return images;
  577. }
  578. private static SaveFormat GetSaveFormat(ImageFormat imageFormat)
  579. {
  580. SaveFormat sf;// = SaveFormat.Unknown;
  581. if (imageFormat.Equals(ImageFormat.Png))
  582. {
  583. sf = SaveFormat.Png;
  584. }
  585. else if (imageFormat.Equals(ImageFormat.Jpeg))
  586. {
  587. sf = SaveFormat.Jpeg;
  588. }
  589. else if (imageFormat.Equals(ImageFormat.Tiff))
  590. {
  591. sf = SaveFormat.Tiff;
  592. }
  593. else if (imageFormat.Equals(ImageFormat.Bmp))
  594. {
  595. sf = SaveFormat.Bmp;
  596. }
  597. else
  598. {
  599. sf = SaveFormat.Unknown;
  600. }
  601. return sf;
  602. }
  603. }
  604. }