CValueWnd.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. #include "../pch/pch.h"
  2. #include "CValueWnd.h"
  3. #include "../tool/CComHelper.h"
  4. #include "../tool/CSerialPort.h"
  5. #include "../helper/CBitmapHelper.h"
  6. void CValueWnd::Notify(TNotifyUI& msg)
  7. {
  8. if(msg.sType == _T("click"))
  9. {
  10. if(msg.pSender->GetName() == _T("closebtn"))
  11. {
  12. PostQuitMessage(0);
  13. return;
  14. }
  15. }
  16. }
  17. void CValueWnd::Init()
  18. {
  19. //初始化窗口位置
  20. InitWndPos();
  21. //抢焦点
  22. std::thread(&CValueWnd::TopMostWnd, this).detach();
  23. //添加托盘图标
  24. AddTrayIcon();
  25. //初始化菜单窗口
  26. pMenu = new CMenuWnd(this);
  27. pMenu->Create(NULL, L"智铺子收银插件菜单", WS_POPUP, WS_EX_TOOLWINDOW);
  28. pMenu->ShowWindow(false);
  29. //定位窗口的初始化
  30. pDingweiWnd = new CDingweiWnd();
  31. pDingweiWnd->Create(NULL, _T("智铺子收银插件窗口定位"), UI_WNDSTYLE_DIALOG, WS_EX_TOOLWINDOW, 0, 0, 0, 0, NULL);
  32. pDingweiWnd->ShowWindow(false);
  33. pDingweiInfoWnd = new CDingweiInfoWnd(this);
  34. pDingweiInfoWnd->Create(NULL, _T("智铺子收银插件窗口定位信息"), UI_WNDSTYLE_DIALOG, WS_EX_TOOLWINDOW, 0, 0, 0, 0, NULL);
  35. pDingweiInfoWnd->ShowWindow(false);
  36. //Ocr窗口初始化
  37. pOcrWnd = new COcrWnd(this);
  38. pOcrWnd->Create(NULL, _T("智铺子收银插件OCR定位"), UI_WNDSTYLE_FRAME, WS_EX_TOOLWINDOW , 0, 0, 0, 0, NULL);
  39. pOcrWnd->ShowWindow(false);
  40. //OCR的数据初始化
  41. if (m_tess.Init("./tessdata", "eng"))
  42. {
  43. std::cout << "OCRTesseract: Could not initialize tesseract." << std::endl;
  44. }
  45. m_tess.SetPageSegMode(tesseract::PageSegMode::PSM_SINGLE_LINE);
  46. m_tess.SetVariable("save_best_choices", "T");
  47. //再安装钩子
  48. //BOOL ret = InstallHook();
  49. //开始启动监听
  50. RestartWatch();
  51. }
  52. /*
  53. *抢窗口前端,抢焦点
  54. **/
  55. void CValueWnd::TopMostWnd()
  56. {
  57. while (true)
  58. {
  59. //::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  60. //if (m_is_show_shoukuan && m_shoukuanHWND != NULL)
  61. //{
  62. // ::SendMessage(m_shoukuanHWND, WM_SHOUKUAN_UPDATE_FOCUS, NULL, NULL);
  63. //}
  64. Sleep(300);
  65. }
  66. }
  67. void CValueWnd::RestartWatch()
  68. {
  69. std::thread(&CValueWnd::StartWatchWork, this).detach();
  70. }
  71. /*
  72. *根据当前数据库的设置,重启监听
  73. **/
  74. void CValueWnd::StartWatchWork()
  75. {
  76. //先暂停已有的监控
  77. m_isWatchWork = false;
  78. //等待2秒,这2秒就是等已有的监控线程自动退出
  79. Sleep(2000);
  80. //然后开始工作
  81. m_isWatchWork = true;
  82. std::string system_setting_jinezhuaqu_setting_type = CSetting::GetParam("system_setting_jinezhuaqu_setting_type");
  83. m_nWatchType = atoi(system_setting_jinezhuaqu_setting_type.c_str());
  84. if(m_nWatchType == 1)
  85. {
  86. //更新监听的端口号
  87. std::string system_setting_jinezhuaqu_setting_chuankou_num = CSetting::GetParam("system_setting_jinezhuaqu_setting_chuankou_num");
  88. if(system_setting_jinezhuaqu_setting_chuankou_num == "")
  89. {
  90. //参数错误
  91. return;
  92. }
  93. std::wstring ws_system_setting_jinezhuaqu_setting_chuankou_num = CLewaimaiString::UTF8ToUnicode(system_setting_jinezhuaqu_setting_chuankou_num);
  94. //设置窗口句柄
  95. ::SetHwnd(m_hWnd);
  96. //设置串口端口号
  97. std::transform(system_setting_jinezhuaqu_setting_chuankou_num.begin(), system_setting_jinezhuaqu_setting_chuankou_num.end(), system_setting_jinezhuaqu_setting_chuankou_num.begin(), ::toupper);
  98. std::transform(ws_system_setting_jinezhuaqu_setting_chuankou_num.begin(), ws_system_setting_jinezhuaqu_setting_chuankou_num.end(), ws_system_setting_jinezhuaqu_setting_chuankou_num.begin(), ::toupper);
  99. ::SetComNum(system_setting_jinezhuaqu_setting_chuankou_num.c_str(), ws_system_setting_jinezhuaqu_setting_chuankou_num.c_str(), system_setting_jinezhuaqu_setting_chuankou_num.size());
  100. }
  101. else if(m_nWatchType == 2)
  102. {
  103. //虚拟串口的模式
  104. std::thread(&CValueWnd::ReadXunichuankouValue, this).detach();
  105. }
  106. else if(m_nWatchType == 3)
  107. {
  108. //窗口模式
  109. m_watchWnd = NULL;
  110. std::thread(&CValueWnd::WatchWnd, this).detach();
  111. }
  112. else if (m_nWatchType == 4)
  113. {
  114. std::thread(&CValueWnd::StartOcrWork, this).detach();
  115. }
  116. }
  117. /*
  118. *读取客显金额的线程,一旦m_nWatchType不为2,那么就直接退出这个线程,下次设置的时候再开启
  119. **/
  120. void CValueWnd::ReadXunichuankouValue()
  121. {
  122. //读取虚拟串口的模式
  123. std::string system_setting_jinezhuaqu_setting_xunichuankou_num_2 = CSetting::GetParam("system_setting_jinezhuaqu_setting_xunichuankou_num_2");
  124. std::string system_setting_jinezhuaqu_setting_xunichuankou_botelv = CSetting::GetParam("system_setting_jinezhuaqu_setting_xunichuankou_botelv");
  125. CSerialPort serial(CLewaimaiString::UTF8ToUnicode(system_setting_jinezhuaqu_setting_xunichuankou_num_2), atoi(system_setting_jinezhuaqu_setting_xunichuankou_botelv.c_str()));
  126. bool ret = serial.openComm();
  127. if(!ret)
  128. {
  129. LOG_INFO("open com failed!");
  130. return;
  131. }
  132. char a[1024] = { 0 };
  133. //检查监控模式和波特率,如果变了就关闭掉
  134. while(m_nWatchType == 2 && m_isWatchWork)
  135. {
  136. memset(a, 0, 1024);
  137. //开始读取串口的数据
  138. DWORD nReaded = 0;
  139. serial.readFromComm(a, 1024, &nReaded);
  140. if(nReaded > 0)
  141. {
  142. UpdateKexian(a, nReaded);
  143. }
  144. Sleep(200);
  145. }
  146. serial.closeComm();
  147. }
  148. void CValueWnd::WatchWnd()
  149. {
  150. std::string system_setting_jinezhuaqu_setting_chuangkou_process_name = CSetting::GetParam("system_setting_jinezhuaqu_setting_chuangkou_process_name");
  151. std::string system_setting_jinezhuaqu_setting_chuangkou_title = CSetting::GetParam("system_setting_jinezhuaqu_setting_chuangkou_title");
  152. std::string system_setting_jinezhuaqu_setting_chuangkou_zorder = CSetting::GetParam("system_setting_jinezhuaqu_setting_chuangkou_zorder");
  153. //如果模式变了,或者参数变了,就退出(因为会重新启动一个新的监控)
  154. while(m_nWatchType == 3 && m_isWatchWork)
  155. {
  156. if(m_watchWnd != NULL)
  157. {
  158. char szTitle[MAX_PATH] = { 0 };
  159. LPSTR lpWindowName = szTitle;
  160. std::string value;
  161. int ret = ::SendMessageA(m_watchWnd, WM_GETTEXT, (WPARAM)(MAX_PATH), (LPARAM)lpWindowName);
  162. if(ret == 0)
  163. {
  164. //说明m_watchWnd已经失效了
  165. value = "0.00";
  166. m_watchWnd = NULL;
  167. }
  168. else
  169. {
  170. value = lpWindowName;
  171. }
  172. if(value != m_watchValue)
  173. {
  174. m_watchValue = value;
  175. SendMessage(WM_WATCH_WND_UPDATE, NULL, NULL);
  176. }
  177. }
  178. else
  179. {
  180. //获得进程名字
  181. std::wstring processName = CLewaimaiString::UTF8ToUnicode(system_setting_jinezhuaqu_setting_chuangkou_process_name);
  182. //根据进程名字,找到对应的主窗口
  183. HWND mainWnd = GetWndHwnd(processName.c_str(), system_setting_jinezhuaqu_setting_chuangkou_title);
  184. if(mainWnd == NULL)
  185. {
  186. //说明这个进程还没有启动
  187. m_watchWnd = NULL;
  188. }
  189. else
  190. {
  191. //根据Z序查找目标窗口
  192. ValueWnd newWnd;
  193. newWnd.wndTitle = system_setting_jinezhuaqu_setting_chuangkou_title;
  194. newWnd.TopWnd = mainWnd;
  195. newWnd.z_order = atoi(system_setting_jinezhuaqu_setting_chuangkou_zorder.c_str());
  196. newWnd.processName = processName;
  197. newWnd.selfWnd = NULL;
  198. g_zorder = 0;
  199. EnumChildWindows(mainWnd, EnumMainwndChildProc, (LPARAM)(&newWnd));
  200. if(newWnd.selfWnd != NULL)
  201. {
  202. //找到了
  203. m_watchWnd = newWnd.selfWnd;
  204. }
  205. }
  206. }
  207. Sleep(200);
  208. }
  209. }
  210. void CValueWnd::StartOcrWork()
  211. {
  212. int system_setting_jinezhuaqu_setting_ocr_left = atoi(CSetting::GetParam("system_setting_jinezhuaqu_setting_ocr_left").c_str());
  213. int system_setting_jinezhuaqu_setting_ocr_top = atoi(CSetting::GetParam("system_setting_jinezhuaqu_setting_ocr_top").c_str());
  214. int system_setting_jinezhuaqu_setting_ocr_right = atoi(CSetting::GetParam("system_setting_jinezhuaqu_setting_ocr_right").c_str());
  215. int system_setting_jinezhuaqu_setting_ocr_bottom = atoi(CSetting::GetParam("system_setting_jinezhuaqu_setting_ocr_bottom").c_str());
  216. //如果模式变了,或者参数变了,就退出(因为会重新启动一个新的监控)
  217. while (m_nWatchType == 4 && m_isWatchWork)
  218. {
  219. RECT rect;
  220. rect.left = system_setting_jinezhuaqu_setting_ocr_left;
  221. rect.top = system_setting_jinezhuaqu_setting_ocr_top;
  222. rect.right = system_setting_jinezhuaqu_setting_ocr_right;
  223. rect.bottom = system_setting_jinezhuaqu_setting_ocr_bottom;
  224. if (IsRectEmpty(&rect))
  225. {
  226. }
  227. else
  228. {
  229. CBitmapHelper helper;
  230. std::string ocr_result;
  231. bool ret = helper.OcrRect(m_tess, &rect, ocr_result);
  232. if (ret)
  233. {
  234. if (!atof(ocr_result.c_str()))
  235. {
  236. //识别结果不是有效的数字
  237. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  238. valueLabel->SetText(L"0.00");
  239. }
  240. else
  241. {
  242. std::string format_value = CLewaimaiString::DoubleToString(atof(ocr_result.c_str()), 2);
  243. std::wstring ws_ocr_result = CLewaimaiString::UTF8ToUnicode(format_value);
  244. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  245. valueLabel->SetText(ws_ocr_result.c_str());
  246. }
  247. }
  248. }
  249. Sleep(200);
  250. }
  251. }
  252. LRESULT CValueWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  253. {
  254. LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
  255. styleValue &= ~WS_CAPTION;
  256. ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  257. // 把自己的窗口句柄与窗口绘制管理器挂接在一起
  258. m_pm.Init(m_hWnd);
  259. m_pm.AddPreMessageFilter(this);
  260. CDialogBuilder builder;
  261. CControlUI* pRoot = builder.Create(_T("value.xml"), (UINT)0, NULL, &m_pm);
  262. ASSERT(pRoot && "Failed to parse XML");
  263. // 把这些控件绘制到本窗口上
  264. m_pm.AttachDialog(pRoot);
  265. // 把自己加入到CPaintManagerUI的m_aNotifiers数组中,用于处理Notify函数
  266. m_pm.AddNotifier(this);
  267. //进行一些初始化工作
  268. Init();
  269. return 0;
  270. }
  271. LRESULT CValueWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  272. {
  273. bHandled = FALSE;
  274. return 0;
  275. }
  276. /*
  277. *这个是窗口被销毁的时候调用的
  278. **/
  279. LRESULT CValueWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  280. {
  281. bHandled = FALSE;
  282. return 0;
  283. }
  284. LRESULT CValueWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  285. {
  286. if(::IsIconic(*this))
  287. {
  288. bHandled = FALSE;
  289. }
  290. return (wParam == 0) ? TRUE : FALSE;
  291. }
  292. LRESULT CValueWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  293. {
  294. return 0;
  295. }
  296. LRESULT CValueWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  297. {
  298. //在这里设置焦点才有用
  299. CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
  300. if(pAccountEdit)
  301. {
  302. pAccountEdit->SetFocus();
  303. }
  304. return 0;
  305. }
  306. LRESULT CValueWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  307. {
  308. POINT pt;
  309. pt.x = GET_X_LPARAM(lParam);
  310. pt.y = GET_Y_LPARAM(lParam);
  311. ::ScreenToClient(*this, &pt);
  312. RECT rcClient;
  313. ::GetClientRect(*this, &rcClient);
  314. RECT rcCaption = m_pm.GetCaptionRect();
  315. if(pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
  316. && pt.y >= rcCaption.top && pt.y < rcCaption.bottom)
  317. {
  318. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
  319. if(pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0)
  320. {
  321. return HTCAPTION;
  322. }
  323. }
  324. return HTCLIENT;
  325. }
  326. LRESULT CValueWnd::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  327. {
  328. pMenu->ShowWindow(false);
  329. bHandled = FALSE;
  330. return 0;
  331. }
  332. LRESULT CValueWnd::OnRButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  333. {
  334. RECT rect;
  335. GetWindowRect(m_hWnd, &rect);
  336. ::SetWindowPos(pMenu->GetHWND(), HWND_NOTOPMOST, rect.left, rect.bottom - 3, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  337. pMenu->ShowWindow(true);
  338. //右击后点别地可以清除“右击出来的菜单”
  339. SetForegroundWindow(pMenu->GetHWND());
  340. bHandled = FALSE;
  341. return 0;
  342. }
  343. LRESULT CValueWnd::OnKexianUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  344. {
  345. //如果当前不是串口模式,直接忽略
  346. if(m_nWatchType != 1)
  347. {
  348. bHandled = TRUE;
  349. return true;
  350. }
  351. //收到了客显数据消息,读取客显数据
  352. char data[MAX_DATA_LENGTH] = { 0 };
  353. int data_length = 0;
  354. HookGetData(data, &data_length);
  355. if(data_length == 0)
  356. {
  357. bHandled = TRUE;
  358. return true;
  359. }
  360. UpdateKexian(data, data_length);
  361. bHandled = TRUE;
  362. return true;
  363. }
  364. LRESULT CValueWnd::OnWatchWndUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  365. {
  366. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  367. std::string money_show = CLewaimaiString::DoubleToString(atof(m_watchValue.c_str()), 2);
  368. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  369. return TRUE;
  370. }
  371. LRESULT CValueWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  372. {
  373. LRESULT lRes = 0;
  374. BOOL bHandled = TRUE;
  375. switch(uMsg)
  376. {
  377. case WM_CREATE:
  378. lRes = OnCreate(uMsg, wParam, lParam, bHandled);
  379. break;
  380. case WM_CLOSE:
  381. lRes = OnClose(uMsg, wParam, lParam, bHandled);
  382. break;
  383. case WM_DESTROY:
  384. lRes = OnDestroy(uMsg, wParam, lParam, bHandled);
  385. break;
  386. case WM_NCACTIVATE:
  387. lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
  388. break;
  389. case WM_NCLBUTTONDOWN:
  390. lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled);
  391. break;
  392. case WM_NCRBUTTONDOWN:
  393. lRes = OnRButtonDown(uMsg, wParam, lParam, bHandled);
  394. break;
  395. case WM_NCCALCSIZE:
  396. lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
  397. break;
  398. case WM_NCPAINT:
  399. lRes = OnNcPaint(uMsg, wParam, lParam, bHandled);
  400. break;
  401. case WM_NCHITTEST:
  402. lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
  403. break;
  404. case WM_SHOWTASK:
  405. lRes = OnTrayIcon(uMsg, wParam, lParam, bHandled);
  406. break;
  407. case WM_HOOK_MESSAGE:
  408. lRes = OnKexianUpdate(uMsg, wParam, lParam, bHandled);
  409. break;
  410. case WM_WATCH_WND_UPDATE:
  411. lRes = OnWatchWndUpdate(uMsg, wParam, lParam, bHandled);
  412. break;
  413. default:
  414. bHandled = FALSE;
  415. }
  416. if(bHandled)
  417. {
  418. return lRes;
  419. }
  420. if(m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
  421. {
  422. return lRes;
  423. }
  424. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  425. }
  426. LRESULT CValueWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
  427. {
  428. return false;
  429. }
  430. void CValueWnd::ShowShoukuan()
  431. {
  432. if (m_is_show_shoukuan == true)
  433. {
  434. return;
  435. }
  436. pMenu->ShowWindow(false);
  437. CShoukuanWnd* pShoukuanWnd = new CShoukuanWnd;
  438. if (pShoukuanWnd != NULL)
  439. {
  440. pShoukuanWnd->Create(NULL, _T(""), UI_WNDSTYLE_DIALOG, WS_EX_TOOLWINDOW);
  441. pShoukuanWnd->SetIcon(IDI_ICON_DUILIB);
  442. pShoukuanWnd->CenterWindow();
  443. ::SetWindowPos(pShoukuanWnd->GetHWND(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  444. m_is_show_shoukuan = true;
  445. m_shoukuanWnd = pShoukuanWnd;
  446. m_shoukuanHWND = pShoukuanWnd->GetHWND();
  447. pShoukuanWnd->InitMoney(L"0.01");
  448. UINT ret = pShoukuanWnd->ShowModal();
  449. m_is_show_shoukuan = false;
  450. m_shoukuanWnd = NULL;
  451. m_shoukuanHWND = NULL;
  452. if (ret == IDOK)
  453. {
  454. }
  455. else if (ret == IDCANCEL)
  456. {
  457. }
  458. }
  459. }
  460. void CValueWnd::AddTrayIcon()
  461. {
  462. memset(&m_trayIcon, 0, sizeof(NOTIFYICONDATA));
  463. m_trayIcon.cbSize = sizeof(NOTIFYICONDATA);
  464. m_trayIcon.hIcon = ::LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON_DUILIB));
  465. m_trayIcon.hWnd = m_hWnd;
  466. lstrcpy(m_trayIcon.szTip, _T("智铺子收银插件"));
  467. m_trayIcon.uCallbackMessage = WM_SHOWTASK;
  468. m_trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
  469. Shell_NotifyIcon(NIM_ADD, &m_trayIcon);
  470. }
  471. LRESULT CValueWnd::OnTrayIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  472. {
  473. //如果在图标中单击左键则还原
  474. if(lParam == WM_LBUTTONDOWN)
  475. {
  476. ShowTrayMenu();
  477. }
  478. //如果在图标中单击右键则弹出声明式菜单
  479. else if(lParam == WM_RBUTTONDOWN)
  480. {
  481. ShowTrayMenu();
  482. }
  483. bHandled = true;
  484. return 0;
  485. }
  486. void CValueWnd::ShowSystemSetting()
  487. {
  488. //先隐藏目录
  489. pMenu->ShowWindow(false);
  490. //然后判断和显示系统设置
  491. if (m_is_show_setting == true)
  492. {
  493. return;
  494. }
  495. CSystemSettingWnd* pSystemSettingFrame = new CSystemSettingWnd(this);
  496. m_settingWnd = pSystemSettingFrame;
  497. if (pSystemSettingFrame != NULL)
  498. {
  499. m_is_show_setting = true;
  500. pSystemSettingFrame->Create(NULL, _T(""), UI_WNDSTYLE_DIALOG, WS_EX_TOOLWINDOW);
  501. pSystemSettingFrame->SetIcon(IDI_ICON_DUILIB);
  502. pSystemSettingFrame->CenterWindow();
  503. UINT ret = pSystemSettingFrame->ShowModal();
  504. m_is_show_setting = false;
  505. if (ret == IDOK)
  506. {
  507. }
  508. else if (ret == IDCANCEL)
  509. {
  510. }
  511. }
  512. }
  513. void CValueWnd::UpdateKexian(const char* data, int length)
  514. {
  515. std::string new_data = data;
  516. //清屏命令
  517. std::string clear_command = "\f";
  518. //4个信号灯全灭
  519. std::string quanmie_command = "\x1bs0";
  520. std::string show_command = "\x1bQA";
  521. std::string type_command = "\x1bs";
  522. if(new_data == clear_command || new_data == quanmie_command)
  523. {
  524. //清屏命令,或者是熄灭灯的命令
  525. return;
  526. }
  527. if(new_data.find(show_command) == new_data.npos)
  528. {
  529. return;
  530. }
  531. std::string money;
  532. int nPos = new_data.find(show_command);
  533. int nTypePos = new_data.find(type_command, nPos + 1);
  534. if(nTypePos == new_data.npos)
  535. {
  536. //没有类型信息,有些收银机(比如思迅天店)就是不传类型信息,这种只有传什么显示什么了
  537. int nTabPos = new_data.find("\r", nPos + 1);
  538. if(nTabPos == new_data.npos)
  539. {
  540. //制表符也没有
  541. return;
  542. }
  543. money = new_data.substr(nPos + 3, nTabPos - nPos - 3);
  544. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  545. std::string money_show = CLewaimaiString::DoubleToString(atof(money.c_str()), 2);
  546. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  547. }
  548. else
  549. {
  550. std::string value_type = new_data.substr(nTypePos + 2, 1);
  551. money = new_data.substr(nPos + 3, nTypePos - nPos - 3 - 1);
  552. if(value_type == "2")
  553. {
  554. //这个表示是总计的,那么就要刷新金额显示
  555. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  556. std::string money_show = CLewaimaiString::DoubleToString(atof(money.c_str()), 2);
  557. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  558. }
  559. else
  560. {
  561. //这种情况传输的是一些找零、单价之类的信息,不更新客显金额
  562. }
  563. }
  564. return;
  565. }
  566. void CValueWnd::InitWndPos()
  567. {
  568. ASSERT(::IsWindow(m_hWnd));
  569. ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD) == 0);
  570. RECT rcDlg = { 0 };
  571. ::GetWindowRect(m_hWnd, &rcDlg);
  572. RECT rcArea = { 0 };
  573. RECT rcCenter = { 0 };
  574. HWND hWnd = *this;
  575. HWND hWndParent = ::GetParent(m_hWnd);
  576. HWND hWndCenter = ::GetWindowOwner(m_hWnd);
  577. if(hWndCenter != NULL)
  578. {
  579. hWnd = hWndCenter;
  580. }
  581. // 处理多显示器模式下屏幕居中
  582. MONITORINFO oMonitor = {};
  583. oMonitor.cbSize = sizeof(oMonitor);
  584. ::GetMonitorInfo(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &oMonitor);
  585. rcArea = oMonitor.rcWork;
  586. if(hWndCenter == NULL)
  587. {
  588. rcCenter = rcArea;
  589. }
  590. else
  591. {
  592. ::GetWindowRect(hWndCenter, &rcCenter);
  593. }
  594. int DlgWidth = rcDlg.right - rcDlg.left;
  595. int DlgHeight = rcDlg.bottom - rcDlg.top;
  596. int xLeft = rcCenter.right - DlgWidth - 60;
  597. int yTop = 100;
  598. if(xLeft < rcArea.left)
  599. {
  600. xLeft = rcArea.left;
  601. }
  602. else if(xLeft + DlgWidth > rcArea.right)
  603. {
  604. xLeft = rcArea.right - DlgWidth;
  605. }
  606. if(yTop < rcArea.top)
  607. {
  608. yTop = rcArea.top;
  609. }
  610. else if(yTop + DlgHeight > rcArea.bottom)
  611. {
  612. yTop = rcArea.bottom - DlgHeight;
  613. }
  614. ::SetWindowPos(m_hWnd, HWND_TOPMOST, xLeft, yTop, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  615. }
  616. void CValueWnd::ShowTrayMenu()
  617. {
  618. //获取鼠标坐标
  619. POINT pt;
  620. GetCursorPos(&pt);
  621. //显示目录
  622. ::SetWindowPos(pMenu->GetHWND(), HWND_NOTOPMOST, pt.x, pt.y - 15 - 380, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  623. pMenu->ShowWindow(true);
  624. //右击后点别地可以清除“右击出来的菜单”
  625. SetForegroundWindow(pMenu->GetHWND());
  626. }
  627. void CValueWnd::StartDingweiWnd()
  628. {
  629. m_settingWnd->ShowWindow(false);
  630. m_is_dingwei_wnd = true;
  631. std::thread(&CValueWnd::StartDingweiWork, this).detach();
  632. }
  633. void CValueWnd::ConfirmDingweiWnd(std::wstring value, HWND hWnd)
  634. {
  635. m_is_dingwei_wnd = false;
  636. m_settingWnd->SetDingweiWnd(value, hWnd);
  637. }
  638. void CValueWnd::CancalDingweiWnd()
  639. {
  640. m_is_dingwei_wnd = false;
  641. }
  642. void CValueWnd::StartDingweiWork()
  643. {
  644. while (m_is_dingwei_wnd)
  645. {
  646. //这个时候,是开始定位窗口了
  647. POINT pt;
  648. GetCursorPos(&pt);
  649. //将屏幕坐标保存起来
  650. POINT ptScreen = pt;
  651. //转换成桌面坐标
  652. HWND hDeskHandle = GetDesktopWindow();
  653. ScreenToClient(hDeskHandle, &pt);
  654. HWND hParent = hDeskHandle;
  655. HWND hChild = ChildWindowFromPointEx(hParent, pt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT | CWP_SKIPDISABLED);
  656. if (hChild == pDingweiInfoWnd->GetHWND())
  657. {
  658. //这里表示是移动信息窗口了,这里就不要执行后面的刷新操作了
  659. }
  660. else
  661. {
  662. while (hChild != NULL && hChild != hParent)
  663. {
  664. //说明还有更下级的子窗口
  665. hParent = hChild;
  666. pt = ptScreen;
  667. ScreenToClient(hParent, &pt);
  668. hChild = ChildWindowFromPointEx(hParent, pt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  669. }
  670. HWND hWnd = hParent;
  671. RECT rect;
  672. GetWindowRect(hWnd, &rect);
  673. //在这个窗口上,画一个边框
  674. pDingweiWnd->ShowWindow(true);
  675. ::SetWindowPos(pDingweiWnd->GetHWND(), HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
  676. //显示定位信息
  677. TCHAR szTitle[MAX_PATH] = { 0 };
  678. LPWSTR lpWindowName = szTitle;
  679. ::SendMessageW(hWnd, WM_GETTEXT, (WPARAM)(MAX_PATH), (LPARAM)lpWindowName);
  680. //设置信息窗口的内容
  681. pDingweiInfoWnd->UpdateInfo(lpWindowName, hWnd);
  682. pDingweiInfoWnd->ShowWindow(true);
  683. ::SetWindowPos(pDingweiInfoWnd->GetHWND(), HWND_TOPMOST, rect.left, rect.bottom, rect.right - rect.left, 30, SWP_NOACTIVATE);
  684. }
  685. Sleep(100);
  686. }
  687. m_settingWnd->ShowWindow(true);
  688. pDingweiWnd->ShowWindow(false);
  689. pDingweiInfoWnd->ShowWindow(false);
  690. }
  691. void CValueWnd::StartOcrWnd()
  692. {
  693. m_settingWnd->ShowWindow(false);
  694. m_is_orc_wnd = true;
  695. pOcrWnd->ShowWindow(true);
  696. //先默认居中
  697. ::SetWindowPos(pOcrWnd->GetHWND(), HWND_TOPMOST, 0, 0, 320, 80, SWP_NOMOVE | SWP_NOACTIVATE);
  698. pOcrWnd->CenterWindow();
  699. }
  700. void CValueWnd::ConfirmOcrWnd(RECT rect)
  701. {
  702. m_is_orc_wnd = false;
  703. pOcrWnd->ShowWindow(false);
  704. //保存截屏的结果
  705. m_settingWnd->SetOcrWnd(rect);
  706. //显示设置窗口
  707. m_settingWnd->ShowWindow(true);
  708. }
  709. tesseract::TessBaseAPI& CValueWnd::GetTess()
  710. {
  711. return m_tess;
  712. }