FormMain.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. using Emgu.CV.Face;
  2. using Emgu.CV.Structure;
  3. using Emgu.CV.Util;
  4. using Emgu.CV;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Data;
  9. using System.Drawing;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14. using System.IO;
  15. using System.Windows.Media.Imaging;
  16. using Emgu.CV.CvEnum;
  17. using System.Runtime.CompilerServices;
  18. using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
  19. using System.Data.SqlClient;
  20. namespace T_FaceRecognizer
  21. {
  22. public partial class FormMain : Form
  23. {
  24. public FormMain()
  25. {
  26. InitializeComponent();
  27. }
  28. private void CaptureTimer_Tick(object sender, EventArgs e)
  29. {
  30. ProcessFrame();
  31. }
  32. #region <Переменные>
  33. SqlConnection SCon = new SqlConnection(@"Data Source=213.155.192.79,3002;Initial Catalog=FaceTrackApp;Persist Security Info=True;User ID=u20teresh;Password=bfg2");
  34. public int SelectedCameraID { get; set; } = 0;
  35. Rectangle CurrentFace;
  36. public string UserName { get; set; } = "Лицо не обнаружено";
  37. /// <summary>
  38. /// ID пользователя, который обнаружен
  39. /// </summary>
  40. private string CurrentUserID = string.Empty;
  41. /// <summary>
  42. /// тип операции 1 - вход, 0- выход
  43. /// </summary>
  44. private int TypeOperation = 0;
  45. private bool IsMenuOpened = true;
  46. #endregion
  47. #region <Свойства>
  48. public event PropertyChangedEventHandler PropertyChanged;
  49. private VideoCapture Capture;
  50. private CascadeClassifier HaarCascade;
  51. private Image<Bgr, Byte> BgrFrame = null;
  52. private Image<Gray, Byte> DetectedFace = null;
  53. private List<FaceData> FaceList = new List<FaceData>();
  54. private VectorOfMat ImageList = new VectorOfMat();
  55. private List<string> NameList = new List<string>();
  56. private VectorOfInt LabelList = new VectorOfInt();
  57. private EigenFaceRecognizer recognizer;
  58. private Timer CaptureTimer;
  59. private Timer CaptureTimerIdent;
  60. private bool IsRecognized = false;
  61. #region FaceName
  62. private string faceName;
  63. public string FaceName
  64. {
  65. get { return faceName; }
  66. set
  67. {
  68. faceName = value;
  69. if (faceName == "Лицо не обнаружено")
  70. {
  71. IsRecognized = false;
  72. }
  73. else
  74. {
  75. IsRecognized = true;
  76. }
  77. UserName = faceName;
  78. NotifyPropertyChanged();
  79. }
  80. }
  81. #endregion
  82. #region CameraCaptureImage
  83. private Bitmap cameraCapture;
  84. public Bitmap CameraCapture
  85. {
  86. get { return cameraCapture; }
  87. set
  88. {
  89. cameraCapture = value;
  90. if (TabPages.SelectedIndex == 1)
  91. {
  92. DrawName(cameraCapture, CurrentFace);
  93. PbxIdentification.Image = cameraCapture;
  94. }
  95. else
  96. {
  97. PbxFaces.Image = cameraCapture;
  98. }
  99. NotifyPropertyChanged();
  100. }
  101. }
  102. #endregion
  103. #region CameraCaptureFaceImage
  104. private Bitmap cameraCaptureFace;
  105. public Bitmap CameraCaptureFace
  106. {
  107. get { return cameraCaptureFace; }
  108. set
  109. {
  110. cameraCaptureFace = value;
  111. PbxFaces.Image = cameraCapture;
  112. NotifyPropertyChanged();
  113. }
  114. }
  115. #endregion
  116. #endregion
  117. /// <summary>
  118. /// отрисовка имени над прямоугольком
  119. /// </summary>
  120. private void DrawName(Bitmap cameraCapture, Rectangle face)
  121. {
  122. Pen PenForFace = new Pen(Brushes.Red, 5);
  123. Brush BrushForFace = Brushes.White;
  124. Font MyFont = new Font("Segoe UI Variable Small Semibol; 12pt; style=Bold", 12, FontStyle.Regular);
  125. Brush BrushInfo = Brushes.White;
  126. Pen PenInfo = new Pen(Brushes.White, 4);
  127. Graphics Graph = Graphics.FromImage(cameraCapture);
  128. //Graph.DrawRectangle(PenForFace, face.X, face.Y, face.Width, face.Height);
  129. //позиция отрисовки имени человека
  130. Point PointName = new Point(face.X, face.Y - 25);
  131. Graph.DrawString($"{UserName}", MyFont, BrushForFace, PointName);
  132. }
  133. /// <summary>
  134. /// получение данных с камеры и обработка изображени
  135. /// </summary>
  136. private void ProcessFrame()
  137. {
  138. try
  139. {
  140. BgrFrame = Capture.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal);
  141. }
  142. catch
  143. {
  144. return;
  145. }
  146. if (BgrFrame != null)
  147. {
  148. try
  149. {//for emgu cv bug
  150. Image<Gray, byte> grayframe = BgrFrame.Convert<Gray, byte>();
  151. Rectangle[] faces = HaarCascade.DetectMultiScale(grayframe, 1.2, 10, new System.Drawing.Size(50, 50), new System.Drawing.Size(200, 200));
  152. //detect face
  153. FaceName = "Лицо не обнаружено";
  154. foreach (var face in faces)
  155. {
  156. BgrFrame.Draw(face, new Bgr(0, 0, 255), 2);
  157. DetectedFace = BgrFrame.Copy(face).Convert<Gray, byte>();
  158. FaceRecognition();
  159. break;
  160. }
  161. CameraCapture = BgrFrame.ToBitmap();
  162. }
  163. catch (Exception ex)
  164. {
  165. //todo log
  166. }
  167. }
  168. }
  169. /// <summary>
  170. /// распознавание лица
  171. /// </summary>
  172. private void FaceRecognition()
  173. {
  174. if (ImageList.Size != 0)
  175. {
  176. //Eigen Face Algorithm
  177. FaceRecognizer.PredictionResult result = recognizer.Predict(DetectedFace.Resize(100, 100, Inter.Cubic));
  178. FaceName = NameList[result.Label];
  179. CurrentUserID = FaceList[result.Label].UserID;
  180. CameraCaptureFace = DetectedFace.ToBitmap();
  181. }
  182. else
  183. {
  184. FaceName = "Пожалуйста добавьте лицо";
  185. }
  186. }
  187. /// <summary>
  188. /// добавление лица в систему
  189. /// </summary>
  190. private void BtnAdd_Click(object sender, EventArgs e)
  191. {
  192. if (DetectedFace == null)
  193. {
  194. MessageBox.Show("Лица не обнаружены!\r\nУбедитесь что лицо находится в кадре и обведено красным прямоугольником.", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Error);
  195. return;
  196. }
  197. string PhotoPath = string.Empty;
  198. //ProgressOperation.Value = 10;
  199. //TslStatus.Text = "Добавление нового пользователя...";
  200. bool Flag = TbxLastname.Text.Trim() == "" || TbxName.Text.Trim() == "" || TbxMaskPhone.Text.Trim() == "" || TbxMaskSnils.Text.Trim() == "";
  201. if (Flag)
  202. {
  203. MessageBox.Show("Заполните все поля и повторите попытку!", "Ошибка добавления!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  204. return;
  205. }
  206. SCon.Open();
  207. string QueryCheckPassport = $@"select UserID
  208. from Users
  209. where Snils = '{TbxMaskSnils.Text.Trim()}'";
  210. SqlCommand CmdCheck = new SqlCommand(QueryCheckPassport, SCon);
  211. SqlDataReader Res = CmdCheck.ExecuteReader();
  212. if (Res.HasRows)
  213. {
  214. MessageBox.Show("Такой пользователь уже зарегистрирован в системе!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  215. SCon.Close();
  216. return;
  217. }
  218. SCon.Close();
  219. //изменить размеры изображения
  220. DetectedFace = DetectedFace.Resize(100, 100, Inter.Cubic);
  221. //сохранить изображение в папку
  222. DetectedFace.Save(Config.FacePhotosPath + $"{TbxName.Text.Trim()}{TbxMaskSnils.Text.Trim()}" + Config.ImageFileExtension);
  223. PhotoPath = Config.FacePhotosPath + $"{TbxName.Text.Trim()}{TbxMaskSnils.Text.Trim()}" + Config.ImageFileExtension;
  224. //добавление пользователя в БД
  225. SCon.Open();
  226. string QueryAdd = $@"insert into Users (Lastname,Firstname,Patronymic,Phone,Snils,Photo)
  227. values (@last,@first,@patr,@phone,@snils,@photo)
  228. ";
  229. SqlCommand Cmd = new SqlCommand(QueryAdd, SCon);
  230. Cmd.Parameters.AddWithValue("@last", TbxLastname.Text.Trim());
  231. Cmd.Parameters.AddWithValue("@first", TbxName.Text.Trim());
  232. Cmd.Parameters.AddWithValue("@patr", TbxPatronymic.Text.Trim());
  233. Cmd.Parameters.AddWithValue("@phone", TbxMaskPhone.Text.Trim());
  234. Cmd.Parameters.AddWithValue("@snils", TbxMaskSnils.Text.Trim());
  235. Cmd.Parameters.AddWithValue("@photo", PhotoPath);
  236. Cmd.ExecuteNonQuery();//выполнить запрос
  237. SCon.Close();
  238. MessageBox.Show("Успешно сохранено!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  239. }
  240. /// <summary>
  241. /// получение данных об изображениях
  242. /// </summary>
  243. public void GetFacesList()
  244. {
  245. if (!File.Exists(Config.HaarCascadePath))
  246. {
  247. string text = "Файл каскада Хаара не обнаружен:\n\n";
  248. text += Config.HaarCascadePath;
  249. DialogResult result = MessageBox.Show(text, "Ошибка",
  250. MessageBoxButtons.OK, MessageBoxIcon.Error);
  251. }
  252. HaarCascade = new CascadeClassifier(Config.HaarCascadePath);
  253. FaceList.Clear();
  254. // Создать директорию, если она отсутствовала
  255. if (!Directory.Exists(Config.FacePhotosPath))
  256. {
  257. Directory.CreateDirectory(Config.FacePhotosPath);
  258. }
  259. // Тренировать изображения
  260. if (ImageList.Size > 0)
  261. {
  262. recognizer = new EigenFaceRecognizer(ImageList.Size);
  263. recognizer.Train(ImageList, LabelList);
  264. }
  265. }
  266. protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
  267. {
  268. var handler = PropertyChanged;
  269. if (handler != null)
  270. handler(this, new PropertyChangedEventArgs(propertyName));
  271. }
  272. private void FormMain_Load(object sender, EventArgs e)
  273. {
  274. //скрытие заголовков вкладок в TabControl
  275. TabPages.Appearance = TabAppearance.FlatButtons;
  276. TabPages.ItemSize = new Size(0, 1);
  277. TabPages.SizeMode = TabSizeMode.Fixed;
  278. TabPages.SelectTab(4);
  279. }
  280. private void PbxMenu_Click(object sender, EventArgs e)
  281. {
  282. IsMenuOpened = !IsMenuOpened;
  283. if(SplitContainer.Panel1.Width != 45)
  284. {
  285. SplitContainer.SplitterDistance = 45;
  286. PanHome.BackColor = Color.FromArgb(206, 208, 223);
  287. PanAdd.BackColor = Color.FromArgb(206, 208, 223);
  288. PanIdentification.BackColor = Color.FromArgb(206, 208, 223);
  289. PanJournal.BackColor = Color.FromArgb(206, 208, 223);
  290. PanSettings.BackColor = Color.FromArgb(206, 208, 223);
  291. }
  292. else
  293. {
  294. SplitContainer.SplitterDistance = 250;
  295. PanHome.BackColor = Color.FromArgb(58, 166, 64);
  296. PanAdd.BackColor = Color.FromArgb(58, 166, 64);
  297. PanIdentification.BackColor = Color.FromArgb(58, 166, 64);
  298. PanJournal.BackColor = Color.FromArgb(58, 166, 64);
  299. PanSettings.BackColor = Color.FromArgb(58, 166, 64);
  300. }
  301. }
  302. /// <summary>
  303. /// котроль размеров меню
  304. /// </summary>
  305. /// <param name="isMenuOpened">открыто меню или нет</param>
  306. private void ControlSizeMenu(bool isMenuOpened)
  307. {
  308. if (isMenuOpened)
  309. {
  310. SplitContainer.SplitterDistance = 250;
  311. }
  312. else
  313. {
  314. SplitContainer.SplitterDistance = 45;
  315. }
  316. }
  317. private void FormMain_Resize(object sender, EventArgs e)
  318. {
  319. ControlSizeMenu(IsMenuOpened);
  320. }
  321. private void FormMain_ResizeEnd(object sender, EventArgs e)
  322. {
  323. //PbxMenu_Click(sender, e);
  324. }
  325. private void BtnMain_Click(object sender, EventArgs e)
  326. {
  327. Task.Factory.StartNew(() =>
  328. {
  329. RecognizeOff();
  330. });
  331. TabPages.SelectTab(4);
  332. }
  333. private void BtnAddUser_Click(object sender, EventArgs e)
  334. {
  335. //RecognizeOff();
  336. CaptureTimer = new Timer()
  337. {
  338. Interval = Config.TimerResponseValue
  339. };
  340. CaptureTimer.Tick += CaptureTimer_Tick;
  341. if (ImageList.Size == 0)
  342. {
  343. GetFacesList();
  344. }
  345. TabPages.SelectTab(0);
  346. Capture = new VideoCapture(SelectedCameraID);
  347. Capture.SetCaptureProperty(CapProp.Fps, 30);
  348. Capture.SetCaptureProperty(CapProp.FrameHeight, 450);
  349. Capture.SetCaptureProperty(CapProp.FrameWidth, 370);
  350. CaptureTimer.Start();
  351. }
  352. private void BtnIdent_Click(object sender, EventArgs e)
  353. {
  354. CaptureTimerIdent = new Timer()
  355. {
  356. Interval = Config.TimerResponseValue
  357. };
  358. CaptureTimerIdent.Tick += CaptureTimerIdent_Tick;
  359. //try
  360. //{
  361. // RecognizeOff();
  362. //}
  363. //catch (Exception ex)
  364. //{
  365. // MessageBox.Show(ex.Message, "Внимание!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  366. //}
  367. GetFacesListForIdentification();
  368. Capture = new VideoCapture(SelectedCameraID);
  369. //настройка кадров
  370. Capture.SetCaptureProperty(CapProp.Fps, 30);
  371. Capture.SetCaptureProperty(CapProp.FrameHeight, 450);
  372. Capture.SetCaptureProperty(CapProp.FrameWidth, 370);
  373. CaptureTimerIdent.Start();
  374. TabPages.SelectTab(1);
  375. }
  376. /// <summary>
  377. /// отключение камеры и распознавания
  378. /// </summary>
  379. private void RecognizeOff()
  380. {
  381. if (BgrFrame != null)
  382. {
  383. if (Capture != null)
  384. {
  385. Capture.Dispose();
  386. Capture = null;
  387. }
  388. //BgrFrame = null;
  389. if (CaptureTimer != null)
  390. {
  391. CaptureTimer.Enabled = false;
  392. }
  393. if(CaptureTimerIdent != null)
  394. {
  395. CaptureTimerIdent.Enabled = false;
  396. }
  397. }
  398. }
  399. private void CaptureTimerIdent_Tick(object sender, EventArgs e)
  400. {
  401. ProcessFrameIndentification();
  402. }
  403. /// <summary>
  404. /// получение данных с камеры и распознавание
  405. /// </summary>
  406. private void ProcessFrameIndentification()
  407. {
  408. try
  409. {
  410. BgrFrame = Capture.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal);
  411. }
  412. catch
  413. {
  414. return;
  415. }
  416. if (BgrFrame != null)
  417. {
  418. try
  419. {//for emgu cv bug
  420. Image<Gray, byte> grayframe = BgrFrame.Convert<Gray, byte>();
  421. Rectangle[] faces = HaarCascade.DetectMultiScale(grayframe, 1.2, 10, new System.Drawing.Size(50, 50), new System.Drawing.Size(200, 200));
  422. FaceName = "Лицо не обнаружено";
  423. foreach (var face in faces)
  424. {
  425. CurrentFace = face;
  426. BgrFrame.Draw(face, new Bgr(53, 23, 247), 2);
  427. DetectedFace = BgrFrame.Copy(face).Convert<Gray, byte>();
  428. FaceRecognition();
  429. break;
  430. }
  431. CameraCapture = BgrFrame.ToBitmap();
  432. }
  433. catch (Exception ex)
  434. {
  435. MessageBox.Show(ex.Message);
  436. }
  437. }
  438. }
  439. private void GetFacesListForIdentification()
  440. {
  441. //файл Хаара
  442. if (!File.Exists(Config.HaarCascadePath))
  443. {
  444. string text = "Не удаётся найти файл данных - каскад Хаара:\n\n";
  445. text += Config.HaarCascadePath;
  446. DialogResult result = MessageBox.Show(text, "Ошибка",
  447. MessageBoxButtons.OK, MessageBoxIcon.Error);
  448. }
  449. HaarCascade = new CascadeClassifier(Config.HaarCascadePath);
  450. FaceList.Clear();
  451. FaceData FaceItem = null;
  452. //создать папку для фото, если она отсутствовала
  453. if (!Directory.Exists(Config.FacePhotosPath))
  454. {
  455. Directory.CreateDirectory(Config.FacePhotosPath);
  456. }
  457. //получить из БД инфо о пользователе (id, имя, фамилия, путь до фото)
  458. SCon.Open();
  459. string QueryGetInfoAboutUser = $@"select UserID ,Users.Lastname, Users.Firstname, Users.Patronymic, Photo
  460. from Users";
  461. SqlCommand Cmd = new SqlCommand(QueryGetInfoAboutUser, SCon);
  462. SqlDataReader Res = Cmd.ExecuteReader();
  463. if (Res.HasRows)
  464. {
  465. while (Res.Read())
  466. {
  467. FaceItem = new FaceData();
  468. FaceItem.FaceImage = new Image<Gray, byte>(Application.StartupPath + "\\" + Res["Photo"].ToString());
  469. FaceItem.PersonName = Res["Firstname"].ToString();
  470. FaceItem.LastName = Res["Lastname"].ToString();
  471. FaceItem.Patronymic = Res["Patronymic"].ToString();
  472. FaceItem.UserID = Res["UserID"].ToString();
  473. FaceList.Add(FaceItem);
  474. }
  475. }
  476. else
  477. {
  478. SCon.Close();
  479. MessageBox.Show("Данные о пользователях отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  480. return;
  481. }
  482. SCon.Close();
  483. int i = 0;
  484. foreach (var face in FaceList)
  485. {
  486. ImageList.Push(face.FaceImage.Mat);
  487. NameList.Add(face.PersonName + " " + face.LastName);
  488. LabelList.Push(new[] { i++ });
  489. }
  490. // Тренировка распознавания
  491. if (ImageList.Size > 0)
  492. {
  493. recognizer = new EigenFaceRecognizer(ImageList.Size);
  494. recognizer.Train(ImageList, LabelList);
  495. }
  496. }
  497. private void BtnIn_Click(object sender, EventArgs e)
  498. {
  499. TypeOperation = 1;
  500. RegisterVisit(TypeOperation);
  501. }
  502. private void RegisterVisit(int typeOperation)
  503. {
  504. if (!IsRecognized)
  505. {
  506. MessageBox.Show("Убедитесь, что лицо находится в кадре и обведено красным прямоугольником!", "Ошибка распознавания!");
  507. return;
  508. }
  509. if (typeOperation == 1)
  510. {
  511. #region Предупреждение при попытке повторной идентификации пользователя за один день
  512. SCon.Open();
  513. string QueryCheckExistsVisit = $@"select Count(ID) as Cnt
  514. from Visits
  515. where UsersID = '{CurrentUserID}' and [Date] = CAST(GETDATE() as date)";
  516. SqlCommand CmdCheckVisit = new SqlCommand(QueryCheckExistsVisit, SCon);
  517. SqlDataReader Res = CmdCheckVisit.ExecuteReader();
  518. Res.Read();
  519. int n = int.Parse(Res["Cnt"].ToString());
  520. if (n >= 1)
  521. {
  522. MessageBox.Show("Сегодня данный пользователь уже прошёл идентификацию при входе!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  523. SCon.Close();
  524. return;
  525. }
  526. SCon.Close();
  527. #endregion
  528. //регистрация посещения
  529. SCon.Open();
  530. string QueryAddVisit = $@"set dateformat dmy
  531. insert into Visits (UsersID,[Date],TimeEntrance)
  532. values ('{CurrentUserID}',CAST(GETDATE() as date),'{DateTime.Now.ToString("HH:mm:ss")}')
  533. ";
  534. SqlCommand Cmd = new SqlCommand(QueryAddVisit, SCon);
  535. Cmd.ExecuteNonQuery();
  536. SCon.Close();
  537. MessageBox.Show("Вход прошёл!");
  538. }
  539. else
  540. {
  541. SCon.Open();
  542. string QueryCheckRecord = $@"set dateformat dmy
  543. select *
  544. from Visits
  545. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date) and TimeExit is null
  546. ";
  547. SqlCommand CmdCheck = new SqlCommand(QueryCheckRecord, SCon);
  548. SqlDataReader Res = CmdCheck.ExecuteReader();
  549. if (!Res.HasRows)
  550. {
  551. MessageBox.Show("Данный пользователь уже вышел!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  552. SCon.Close();
  553. return;
  554. }
  555. SCon.Close();
  556. //!!! Выход пользователя, который не прошёл идентификацию не регистрируется
  557. SCon.Open();
  558. string QueryTimeExit = $@"update Visits
  559. set TimeExit = '{DateTime.Now.ToString("HH:mm:ss")}'
  560. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date)";
  561. SqlCommand Cmd = new SqlCommand(QueryTimeExit, SCon);
  562. Cmd.ExecuteNonQuery();
  563. SCon.Close();
  564. MessageBox.Show("Выход зарегистрирован!");
  565. }
  566. }
  567. private void BtnOut_Click(object sender, EventArgs e)
  568. {
  569. TypeOperation = 0;
  570. RegisterVisit(TypeOperation);
  571. }
  572. private void BtnJournal_Click(object sender, EventArgs e)
  573. {
  574. Task.Factory.StartNew(() =>
  575. {
  576. RecognizeOff();
  577. });
  578. GetInformationAboutVisiting();
  579. TabPages.SelectTab(2);
  580. }
  581. /// <summary>
  582. /// получение списка пользователей для журнала посещений
  583. /// </summary>
  584. private void GetInformationAboutVisiting()
  585. {
  586. DgbJournal.Rows.Clear();
  587. SCon.Open();
  588. string QueryGetVisits = $@"select UserID,Lastname +' '+Firstname+' '+Patronymic as FIO,(select MAX([Date])
  589. from Visits
  590. where UsersID = Users.UserID) as LastDateVisit
  591. from Users";
  592. SqlCommand CommandGetVisits = new SqlCommand(QueryGetVisits, SCon);
  593. SqlDataReader Res = CommandGetVisits.ExecuteReader();
  594. if(Res.HasRows)
  595. {
  596. string DateTemplate = string.Empty;
  597. while(Res.Read())
  598. {
  599. DateTemplate = DateTime.Parse(Res["LastDateVisit"].ToString()).ToString("dd.MM.yyyy");
  600. DgbJournal.Rows.Add(Res["UserID"].ToString(), Res["FIO"].ToString(), DateTemplate);
  601. }
  602. }
  603. else
  604. {
  605. MessageBox.Show("Посещения пользователей отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  606. SCon.Close();
  607. return;
  608. }
  609. SCon.Close();
  610. }
  611. private void DgbJournal_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  612. {
  613. int RowIndex = e.RowIndex;
  614. int SelectedUserID = int.Parse(DgbJournal.Rows[RowIndex].Cells[0].Value.ToString());
  615. string SelectedUserName = DgbJournal.Rows[RowIndex].Cells[1].Value.ToString();
  616. FormVisiting FVisiting = new FormVisiting(SelectedUserID, SelectedUserName);
  617. this.Hide();
  618. FVisiting.ShowDialog();
  619. this.Show();
  620. }
  621. private void BtnSettings_Click(object sender, EventArgs e)
  622. {
  623. Task.Factory.StartNew(() =>
  624. {
  625. RecognizeOff();
  626. });
  627. TabPages.SelectTab(3);
  628. }
  629. private void PanelMenu_Paint(object sender, PaintEventArgs e)
  630. {
  631. Invalidate();
  632. }
  633. private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
  634. {
  635. RecognizeOff();
  636. Application.ExitThread();
  637. }
  638. }
  639. }