CMainWnd.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. #include "../pch/pch.h"
  2. #include "CMainWnd.h"
  3. #include "CLoginWnd.h"
  4. #include "../control/ControlEx.h"
  5. #include "../page/CWaimaiOrderInfoPageUI.h"
  6. #include "../page/CDianneiOrderInfoPageUI.h"
  7. #include "../print/CPosPrinter.h"
  8. #include <urlmon.h>
  9. #include "../wnd/CToastWnd.h"
  10. #include "../worker/CMessagePushWorker.h"
  11. void CMainWnd::Init()
  12. {
  13. //设置店铺名字
  14. CLabelUI* pShopname = static_cast<CLabelUI*>(m_pm.FindControl(_T("main_shopname")));
  15. pShopname->SetText(CLewaimaiString::UTF8ToUnicode(CShopinfo::m_shopinfo.m_shop_name).c_str());
  16. //设置推送的消息窗口
  17. CMessagePushWorker::GetInstance()->SetHWND(GetHWND());
  18. //启动消息推送
  19. CMessagePushWorker::GetInstance()->Start();
  20. //默认选择点单页面
  21. m_curOptionName = L"main_diandan";
  22. m_curOption = static_cast<CControlUI*>(m_pm.FindControl(_T("main_diandan")));
  23. this->SwitchPage(DIANDAN);
  24. m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
  25. m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));
  26. m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));
  27. m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
  28. //开启键盘输入监听
  29. RegKeyboardRawInput();
  30. //启动一个线程,开始同步商品图片
  31. std::thread(&CMainWnd::UpdateFoodImage, this).detach();
  32. }
  33. void CMainWnd::UpdateFoodImage()
  34. {
  35. //先判断并创建临时目录
  36. string folderPath = CLewaimaiString::UnicodeToANSI(CSystem::GetProgramDir()) + "\\tmp\\image";
  37. std::wstring ws_folderPath = CLewaimaiString::ANSIToUnicode(folderPath);
  38. if (!CSystem::IsDirExist(ws_folderPath))
  39. {
  40. LOG_INFO("folderPath:" << folderPath.c_str() << ",没有找到对应的目录,即将创建");
  41. CSystem::CreateMultiLevel(folderPath);
  42. }
  43. CSqlite3 sqlite;
  44. std::vector<CFood> foodlist = sqlite.GetFoodByTypeid("0", true);
  45. for (std::vector<CFood>::iterator it = foodlist.begin(); it != foodlist.end(); it++)
  46. {
  47. CFood food = *it;
  48. if (food.goods_img.size() == 0)
  49. {
  50. //没有图片,直接跳过
  51. continue;
  52. }
  53. std::wstring ws_goods_img = food.getImageUrl();
  54. ws_goods_img += L"!max200"; //下载小图
  55. wstring imagePath = food.getImageTmpPath();
  56. if (CSystem::IsFileExist(imagePath))
  57. {
  58. //如果图片文件已经存在,直接跳过
  59. continue;
  60. }
  61. //图片还不存在,开始下载
  62. if (URLDownloadToFile(NULL, ws_goods_img.c_str(), imagePath.c_str(), 0, NULL) == S_OK)
  63. {
  64. //图片下载成功了,发个消息,更新图片
  65. }
  66. else
  67. {
  68. LOG_INFO("URLDownloadToFile Fail,Error"<<GetLastError());
  69. }
  70. }
  71. //再处理商品套餐的图片
  72. std::vector<CFoodpackage> foodpackagelist = sqlite.GetFoodpackages(true);
  73. for (std::vector<CFoodpackage>::iterator it = foodpackagelist.begin(); it != foodpackagelist.end(); it++)
  74. {
  75. CFoodpackage food = *it;
  76. if (food.goods_img.size() == 0)
  77. {
  78. //没有图片,直接跳过
  79. continue;
  80. }
  81. std::wstring ws_goods_img = food.getImageUrl();
  82. ws_goods_img += L"!max200"; //下载小图
  83. wstring imagePath = food.getImageTmpPath();
  84. if (CSystem::IsFileExist(imagePath))
  85. {
  86. //如果图片文件已经存在,直接跳过
  87. continue;
  88. }
  89. //图片还不存在,开始下载
  90. if (URLDownloadToFile(NULL, ws_goods_img.c_str(), imagePath.c_str(), 0, NULL) == S_OK)
  91. {
  92. //图片下载成功了,发个消息,更新图片
  93. }
  94. else
  95. {
  96. LOG_INFO("URLDownloadToFile Fail,Error" << GetLastError());
  97. }
  98. }
  99. }
  100. void CMainWnd::SwitchPage(MainPageName name)
  101. {
  102. if (m_curPageName == name)
  103. {
  104. return;
  105. }
  106. //先删除现在的子对象
  107. CContainerUI* pMainContentLayout = static_cast<CContainerUI*>(m_pm.FindControl(_T("main_content_layout")));
  108. pMainContentLayout->RemoveAll();
  109. //再创建一个对象
  110. CDialogBuilder builder;
  111. CDialogBuilderCallbackEx cb;
  112. CBasePageUI* pChildContainer = NULL;
  113. //注意事项:所有的子页面中的option不能带有selected="true"属性,如果带有这个属性,在下面的Create调用的时候就直接会生成一个selectchanged事件,但是这个时候
  114. //页面才刚刚Create,还没加入到窗口中,相关的变量对应关系也还没设置成功,会导致事件处理对象出现问题
  115. if (name == DIANDAN)
  116. {
  117. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("diandan_page.xml"), (UINT)0, &cb, &m_pm));
  118. }
  119. else if (name == DINGDAN)
  120. {
  121. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("waimaiorder_list_page.xml"), (UINT)0, &cb, &m_pm));
  122. }
  123. else if (name == SHEZHI)
  124. {
  125. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("setting_page.xml"), (UINT)0, &cb, &m_pm));
  126. }
  127. else if (name == HUIYUAN)
  128. {
  129. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("huiyuan_page.xml"), (UINT)0, &cb, &m_pm));
  130. }
  131. else if (name == WAIMAIINFO)
  132. {
  133. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("waimaiorder_info_page.xml"), (UINT)0, &cb, &m_pm));
  134. CWaimaiOrderInfoPageUI* pInfoPage = static_cast<CWaimaiOrderInfoPageUI*>(pChildContainer);
  135. pInfoPage->m_order_id = m_infopage_waimaiorder_id;
  136. pInfoPage->m_order_no = m_infopage_waimaiorder_no;
  137. }
  138. else if (name == DIANNEIDINGDAN)
  139. {
  140. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("dianneiorder_list_page.xml"), (UINT)0, &cb, &m_pm));
  141. }
  142. else if (name == DIANNEIINFO)
  143. {
  144. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("dianneiorder_info_page.xml"), (UINT)0, &cb, &m_pm));
  145. CDianneiOrderInfoPageUI* pInfoPage = static_cast<CDianneiOrderInfoPageUI*>(pChildContainer);
  146. pInfoPage->m_order_id = m_infopage_dianneiorder_id;
  147. }
  148. else if (name == BAOBIAO)
  149. {
  150. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("baobiao_page.xml"), (UINT)0, &cb, &m_pm));
  151. }
  152. else if (name == JIAOBAN)
  153. {
  154. pChildContainer = static_cast<CBasePageUI*>(builder.Create(_T("jiaoban_page.xml"), (UINT)0, &cb, &m_pm));
  155. }
  156. pChildContainer->SetMainWnd(this);
  157. pMainContentLayout->Add(pChildContainer);
  158. m_curPageName = name;
  159. m_curPageUI = pChildContainer;
  160. pChildContainer->InitShow();
  161. }
  162. LRESULT CMainWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  163. {
  164. LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
  165. styleValue &= ~WS_CAPTION;
  166. ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  167. m_pm.Init(m_hWnd);
  168. CDialogBuilder builder;
  169. CDialogBuilderCallbackEx cb;
  170. CControlUI* pRoot = builder.Create(_T("main.xml"), (UINT)0, &cb, &m_pm);
  171. ASSERT(pRoot && "Failed to parse XML");
  172. m_pm.AttachDialog(pRoot);
  173. m_pm.AddNotifier(this);
  174. Init();
  175. return 0;
  176. }
  177. void CMainWnd::Notify(TNotifyUI& msg)
  178. {
  179. if(msg.sType == _T("windowinit"))
  180. {
  181. }
  182. else if(msg.sType == _T("click"))
  183. {
  184. HandleClickMsg(msg);
  185. }
  186. else if(msg.sType == _T("selectchanged"))
  187. {
  188. HandleSelectChangeMsg(msg);
  189. }
  190. else if(msg.sType == _T("itemclick"))
  191. {
  192. }
  193. else if(msg.sType == _T("itemactivate"))
  194. {
  195. }
  196. else if(msg.sType == _T("itemselect"))
  197. {
  198. HandleItemSelectMsg(msg);
  199. }
  200. else if (msg.sType == _T("textchanged"))
  201. {
  202. //编辑框内容改变事件
  203. HandleTextChangedMsg(msg);
  204. }
  205. }
  206. void CMainWnd::HandleClickMsg(TNotifyUI& msg)
  207. {
  208. if(msg.pSender == m_pCloseBtn)
  209. {
  210. if(CSetting::GetParam("setting_is_close_min") == "1")
  211. {
  212. AddTrayIcon();
  213. }
  214. else
  215. {
  216. PostQuitMessage(0);
  217. }
  218. return;
  219. }
  220. else if(msg.pSender == m_pMinBtn)
  221. {
  222. SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
  223. return;
  224. }
  225. else if(msg.pSender == m_pMaxBtn)
  226. {
  227. SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  228. return;
  229. }
  230. else if(msg.pSender == m_pRestoreBtn)
  231. {
  232. SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
  233. return;
  234. }
  235. else if (msg.pSender->GetName() == L"main_web_login_btn")
  236. {
  237. ShellExecute(NULL, _T("open"), _T("explorer.exe"), _T("https://www.zhipuzi.com/login.html"), NULL, SW_SHOW);
  238. }
  239. CDuiString name = msg.pSender->GetName();
  240. if(name == _T("quitbtn"))
  241. {
  242. /*Close()*/
  243. PostQuitMessage(0); // 因为activex的原因,使用close可能会出现错误
  244. }
  245. else
  246. {
  247. this->m_curPageUI->HandleClickMsg(msg);
  248. }
  249. }
  250. /**
  251. * 这个处理Option的切换
  252. */
  253. void CMainWnd::HandleSelectChangeMsg(TNotifyUI& msg)
  254. {
  255. CDuiString name = msg.pSender->GetName();
  256. std::wstring ws_name = name;
  257. if (ws_name == _T("main_diandan") || ws_name == _T("main_dingdan") || ws_name == _T("main_huiyuan") || ws_name == _T("main_baobiao") || ws_name == _T("main_jiaoban") || ws_name == _T("main_setting") || ws_name == _T("main_gengduo"))
  258. {
  259. if (m_curOptionName != ws_name)
  260. {
  261. //表示切换了tab
  262. m_curOption->SetBkColor(0x00000000);
  263. msg.pSender->SetBkColor(0xFF3CB371);
  264. m_curOptionName = ws_name;
  265. m_curOption = static_cast<CControlUI*>(msg.pSender);
  266. }
  267. }
  268. //先判断主页面的tab
  269. if (name == _T("main_diandan"))
  270. {
  271. this->SwitchPage(DIANDAN);
  272. }
  273. else if(name == _T("main_dingdan"))
  274. {
  275. this->SwitchPage(DIANNEIDINGDAN);
  276. }
  277. else if (name == L"main_huiyuan")
  278. {
  279. this->SwitchPage(HUIYUAN);
  280. }
  281. else if (name == L"main_baobiao")
  282. {
  283. this->SwitchPage(BAOBIAO);
  284. }
  285. else if (name == L"main_jiaoban")
  286. {
  287. this->SwitchPage(JIAOBAN);
  288. }
  289. else if(name == _T("main_setting"))
  290. {
  291. this->SwitchPage(SHEZHI);
  292. }
  293. else if (name == L"main_gengduo")
  294. {
  295. }
  296. else
  297. {
  298. //除了主界面固定区域的事件,其他的事件全部分发给子页面
  299. this->m_curPageUI->HandleSelectChangeMsg(msg);
  300. }
  301. }
  302. void CMainWnd::HandleItemSelectMsg(TNotifyUI& msg)
  303. {
  304. this->m_curPageUI->HandleItemSelectMsg(msg);
  305. }
  306. void CMainWnd::HandleTextChangedMsg(TNotifyUI& msg)
  307. {
  308. this->m_curPageUI->HandleTextChangedMsg(msg);
  309. }
  310. LRESULT CMainWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  311. {
  312. LRESULT lRes = 0;
  313. BOOL bHandled = TRUE;
  314. switch(uMsg)
  315. {
  316. case WM_CREATE:
  317. lRes = OnCreate(uMsg, wParam, lParam, bHandled);
  318. break;
  319. case WM_CLOSE:
  320. lRes = OnClose(uMsg, wParam, lParam, bHandled);
  321. break;
  322. case WM_DESTROY:
  323. lRes = OnDestroy(uMsg, wParam, lParam, bHandled);
  324. break;
  325. case WM_NCACTIVATE:
  326. lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
  327. break;
  328. case WM_NCCALCSIZE:
  329. lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
  330. break;
  331. case WM_NCPAINT:
  332. lRes = OnNcPaint(uMsg, wParam, lParam, bHandled);
  333. break;
  334. case WM_NCHITTEST:
  335. lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
  336. break;
  337. case WM_SIZE:
  338. lRes = OnSize(uMsg, wParam, lParam, bHandled);
  339. break;
  340. case WM_GETMINMAXINFO:
  341. lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled);
  342. break;
  343. case WM_SYSCOMMAND:
  344. lRes = OnSysCommand(uMsg, wParam, lParam, bHandled);
  345. break;
  346. case WM_SHOWTASK:
  347. lRes = OnTrayIcon(uMsg, wParam, lParam, bHandled);
  348. break;
  349. case WM_INPUT:
  350. lRes = OnInput(uMsg, wParam, lParam, bHandled);
  351. break;
  352. case WM_KEYDOWN:
  353. lRes = OnKeydown(uMsg, wParam, lParam, bHandled);
  354. break;
  355. case WM_KILLFOCUS:
  356. break;
  357. default:
  358. bHandled = FALSE;
  359. }
  360. if(bHandled)
  361. {
  362. return lRes;
  363. }
  364. bool ret = this->HandleCustomMessage(uMsg, wParam, lParam);
  365. if (ret)
  366. {
  367. //自定义消息已经处理
  368. return 0;
  369. }
  370. if(m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
  371. {
  372. return lRes;
  373. }
  374. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  375. }
  376. bool CMainWnd::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  377. {
  378. if (uMsg == WM_LOGIN_AGAIN_OUT)
  379. {
  380. LoginOut(2);
  381. return true;
  382. }
  383. else
  384. {
  385. //走到这里,说明消息还没有被处理,那就不是MainWnd自己要处理的消息,应该是自定义的消息,交给各个子页面自己处理去
  386. if (m_curPageUI != NULL)
  387. {
  388. bool ret = this->m_curPageUI->HandleCustomMessage(uMsg, wParam, lParam);
  389. return ret;
  390. }
  391. }
  392. return false;
  393. }
  394. LRESULT CMainWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
  395. {
  396. return false;
  397. }
  398. LRESULT CMainWnd::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  399. {
  400. // 有时会在收到WM_NCDESTROY后收到wParam为SC_CLOSE的WM_SYSCOMMAND
  401. if(wParam == SC_CLOSE)
  402. {
  403. ::PostQuitMessage(0L);
  404. bHandled = TRUE;
  405. return 0;
  406. }
  407. BOOL bZoomed = ::IsZoomed(*this);
  408. LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  409. if(::IsZoomed(*this) != bZoomed)
  410. {
  411. if(!bZoomed)
  412. {
  413. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
  414. if(pControl)
  415. {
  416. pControl->SetVisible(false);
  417. }
  418. pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
  419. if(pControl)
  420. {
  421. pControl->SetVisible(true);
  422. }
  423. }
  424. else
  425. {
  426. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
  427. if(pControl)
  428. {
  429. pControl->SetVisible(true);
  430. }
  431. pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
  432. if(pControl)
  433. {
  434. pControl->SetVisible(false);
  435. }
  436. }
  437. }
  438. return lRes;
  439. }
  440. LRESULT CMainWnd::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  441. {
  442. int primaryMonitorWidth = ::GetSystemMetrics(SM_CXSCREEN);
  443. int primaryMonitorHeight = ::GetSystemMetrics(SM_CYSCREEN);
  444. MONITORINFO oMonitor = {};
  445. oMonitor.cbSize = sizeof(oMonitor);
  446. ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
  447. CDuiRect rcWork = oMonitor.rcWork;
  448. rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);
  449. if(rcWork.right > primaryMonitorWidth)
  450. {
  451. rcWork.right = primaryMonitorWidth;
  452. }
  453. if(rcWork.bottom > primaryMonitorHeight)
  454. {
  455. rcWork.right = primaryMonitorHeight;
  456. }
  457. LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
  458. lpMMI->ptMaxPosition.x = rcWork.left;
  459. lpMMI->ptMaxPosition.y = rcWork.top;
  460. lpMMI->ptMaxSize.x = rcWork.right;
  461. lpMMI->ptMaxSize.y = rcWork.bottom;
  462. bHandled = FALSE;
  463. return 0;
  464. }
  465. LRESULT CMainWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  466. {
  467. SIZE szRoundCorner = m_pm.GetRoundCorner();
  468. if(!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0))
  469. {
  470. CDuiRect rcWnd;
  471. ::GetWindowRect(*this, &rcWnd);
  472. rcWnd.Offset(-rcWnd.left, -rcWnd.top);
  473. rcWnd.right++;
  474. rcWnd.bottom++;
  475. HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
  476. ::SetWindowRgn(*this, hRgn, TRUE);
  477. ::DeleteObject(hRgn);
  478. }
  479. bHandled = FALSE;
  480. return 0;
  481. }
  482. LRESULT CMainWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  483. {
  484. bHandled = FALSE;
  485. return 0;
  486. }
  487. /*
  488. *这个是窗口被销毁的时候调用的
  489. **/
  490. LRESULT CMainWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  491. {
  492. //停止消息推送
  493. CMessagePushWorker::GetInstance()->Stop();
  494. bHandled = FALSE;
  495. return 0;
  496. }
  497. LRESULT CMainWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  498. {
  499. if(::IsIconic(*this))
  500. {
  501. bHandled = FALSE;
  502. }
  503. return (wParam == 0) ? TRUE : FALSE;
  504. }
  505. LRESULT CMainWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  506. {
  507. return 0;
  508. }
  509. LRESULT CMainWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  510. {
  511. return 0;
  512. }
  513. LRESULT CMainWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  514. {
  515. POINT pt;
  516. pt.x = GET_X_LPARAM(lParam);
  517. pt.y = GET_Y_LPARAM(lParam);
  518. ::ScreenToClient(*this, &pt);
  519. RECT rcClient;
  520. ::GetClientRect(*this, &rcClient);
  521. if(!::IsZoomed(*this))
  522. {
  523. RECT rcSizeBox = m_pm.GetSizeBox();
  524. if(pt.y < rcClient.top + rcSizeBox.top)
  525. {
  526. if(pt.x < rcClient.left + rcSizeBox.left)
  527. {
  528. return HTTOPLEFT;
  529. }
  530. if(pt.x > rcClient.right - rcSizeBox.right)
  531. {
  532. return HTTOPRIGHT;
  533. }
  534. return HTTOP;
  535. }
  536. else if(pt.y > rcClient.bottom - rcSizeBox.bottom)
  537. {
  538. if(pt.x < rcClient.left + rcSizeBox.left)
  539. {
  540. return HTBOTTOMLEFT;
  541. }
  542. if(pt.x > rcClient.right - rcSizeBox.right)
  543. {
  544. return HTBOTTOMRIGHT;
  545. }
  546. return HTBOTTOM;
  547. }
  548. if(pt.x < rcClient.left + rcSizeBox.left)
  549. {
  550. return HTLEFT;
  551. }
  552. if(pt.x > rcClient.right - rcSizeBox.right)
  553. {
  554. return HTRIGHT;
  555. }
  556. }
  557. RECT rcCaption = m_pm.GetCaptionRect();
  558. if(pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
  559. && pt.y >= rcCaption.top && pt.y < rcCaption.bottom)
  560. {
  561. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
  562. if(pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0 &&
  563. _tcscmp(pControl->GetClass(), DUI_CTR_OPTION) != 0 &&
  564. _tcscmp(pControl->GetClass(), DUI_CTR_TEXT) != 0)
  565. {
  566. return HTCAPTION;
  567. }
  568. }
  569. return HTCLIENT;
  570. }
  571. LRESULT CMainWnd::OnInput(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  572. {
  573. UINT dwSize = 0;
  574. GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));//取数据,第一次调用函数将获取需要的字节大小
  575. LPBYTE lpbBuffer = new BYTE[dwSize];//分配指定的缓冲区大小
  576. GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, (LPVOID)lpbBuffer, (PUINT)&dwSize, (UINT)sizeof(RAWINPUTHEADER));//第二次调用获取原始输入数据,读入lpbBuffer
  577. RAWINPUT * raw = (RAWINPUT *)lpbBuffer;
  578. if (raw->header.dwType == RIM_TYPEKEYBOARD)//这里可以截获所有键盘信息,如需区分不同的键盘输入信息,可以通过设备句柄判断。
  579. {
  580. if (raw->data.keyboard.Message == WM_KEYDOWN)
  581. {
  582. }
  583. else if (raw->data.keyboard.Message == WM_KEYUP)
  584. {
  585. char keytext[10] = { 0 };
  586. BYTE state[256] = { 0 };
  587. //通过虚拟键盘码得到名字
  588. ToAscii(raw->data.keyboard.VKey, raw->data.keyboard.MakeCode, state, (LPWORD)keytext, 0);
  589. LOG_INFO("vkey:" << raw->data.keyboard.VKey<<", keytext:"<<keytext);
  590. if (raw->data.keyboard.VKey >= 48 && raw->data.keyboard.VKey <= 122)
  591. {
  592. char keytext[10] = { 0 };
  593. BYTE state[256] = { 0 };
  594. //通过虚拟键盘码得到名字
  595. ToAscii(raw->data.keyboard.VKey, raw->data.keyboard.MakeCode, state, (LPWORD)keytext, 0);
  596. //这里是数字和英文字母之间的字符,包含部分标点
  597. if (m_is_start_catch == false)
  598. {
  599. //第一次点击,还无法判定是人工还是机器输入的,先保存下来
  600. m_is_start_catch = true;
  601. m_catch_string = "";
  602. m_is_next_daxie = false;
  603. m_catch_string += string(keytext);
  604. LOG_INFO("起始字符:" << keytext << ",累积:" << m_catch_string.c_str());
  605. m_last_catch_clock = clock();
  606. }
  607. else
  608. {
  609. //已经是在抓取过程中了
  610. clock_t now = clock();
  611. double total_t = (double)(now - m_last_catch_clock) / CLOCKS_PER_SEC;
  612. if (total_t > 0.05)
  613. {
  614. LOG_INFO("发现人工输入");
  615. //如果超过了50ms,说明是前面一个字符是人工输入的了,不能代表现在这个字符是人工输入的,把之前的字符清空,但是目前的这个字符还是要保存
  616. m_catch_string = "";
  617. m_is_next_daxie = false;
  618. //把当前字符保存下来
  619. m_catch_string += string(keytext);
  620. LOG_INFO("起始字符:" << keytext << ",累积:" << m_catch_string.c_str());
  621. m_last_catch_clock = clock();
  622. }
  623. else
  624. {
  625. //这种说明前一个和当前的字符,都是机器输入的,都保存下来
  626. std::string s_keytext = keytext;
  627. if (m_is_next_daxie == true)
  628. {
  629. //要把抓取的这个字符转为大写
  630. transform(s_keytext.begin(), s_keytext.end(), s_keytext.begin(), ::toupper);
  631. }
  632. //转换完了,再把状态还原
  633. m_is_next_daxie = false;
  634. m_catch_string += s_keytext;
  635. LOG_INFO("抓取字符:" << s_keytext.c_str() << ",累积:" << m_catch_string.c_str());
  636. m_last_catch_clock = clock();
  637. }
  638. }
  639. }
  640. else if (raw->data.keyboard.VKey == 13)
  641. {
  642. //输入了enter
  643. if (m_is_start_catch == true)
  644. {
  645. //正在抓取中,判断enter才有意义,否则没有意义
  646. clock_t now = clock();
  647. double total_t = (double)(now - m_last_catch_clock) / CLOCKS_PER_SEC;
  648. if (total_t > 0.05)
  649. {
  650. LOG_INFO("抓取enter人工");
  651. //如果超过了50ms,说明前面一个字符是人工输入的,那么相当于这次直接输入了一个enter,也没意义
  652. m_is_start_catch = false;
  653. m_catch_string = "";
  654. m_is_next_daxie = false;
  655. }
  656. else
  657. {
  658. LOG_INFO("抓取enter结束");
  659. //这种说明前一个字符和当前字符都是机器输入的,可以判定输入结束
  660. std::string last = m_catch_string;
  661. //对抓取结果,进行处理
  662. m_curPageUI->HandleTextCapture(last);
  663. //处理完成后,清空重来
  664. m_is_start_catch = false;
  665. m_catch_string = "";
  666. m_is_next_daxie = false;
  667. }
  668. }
  669. else
  670. {
  671. //还没开始抓取就输入了enter,没有意义,重新开始
  672. m_is_start_catch = false;
  673. m_catch_string = "";
  674. m_is_next_daxie = false;
  675. }
  676. }
  677. else if (raw->data.keyboard.VKey == 16)
  678. {
  679. //这个是大小写切换的按键,扫描大写字母的时候会用到,每个大写字母都是由2个组成,先来个16,再来个对应小写字母的asicc
  680. if (m_is_start_catch == false)
  681. {
  682. LOG_INFO("抓取第1个16");
  683. //说明第一个字符就是大写字母,暂时还无法判断是机器还是人工输入的,先开启抓取
  684. m_is_start_catch = true;
  685. m_catch_string = "";
  686. m_is_next_daxie = true;
  687. m_last_catch_clock = clock();
  688. }
  689. else
  690. {
  691. //已经在抓取中了
  692. clock_t now = clock();
  693. double total_t = (double)(now - m_last_catch_clock) / CLOCKS_PER_SEC;
  694. if (total_t > 0.05)
  695. {
  696. LOG_INFO("抓取16人工");
  697. //如果超过了50ms,只能说明之前的字符是人工输入的,不能代表目前的字符是人工输入的,把之前的清空
  698. m_catch_string = "";
  699. m_is_next_daxie = true;
  700. m_last_catch_clock = clock();
  701. }
  702. else
  703. {
  704. LOG_INFO("抓取16");
  705. //这个说明之前的和当前的都是机器输入的
  706. m_is_next_daxie = true;
  707. m_last_catch_clock = clock();
  708. }
  709. }
  710. }
  711. else
  712. {
  713. LOG_INFO("抓取结束,重新开始");
  714. //输入了无意义的字符,这种直接忽略,重新开始
  715. m_is_start_catch = false;
  716. m_catch_string = "";
  717. m_is_next_daxie = false;
  718. }
  719. }
  720. }
  721. delete[] lpbBuffer;
  722. bHandled = true;
  723. return 0;
  724. }
  725. LRESULT CMainWnd::OnKeydown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  726. {
  727. if (wParam == VK_RETURN)
  728. {
  729. //这里目前主要作用是,拦截按钮自带的焦点enter响应
  730. bHandled = true;
  731. return 0;
  732. }
  733. else if (wParam == VK_ESCAPE)
  734. {
  735. bHandled = true;
  736. return 0;
  737. }
  738. //其他的按键事件,不能返回0
  739. bHandled = false;
  740. return -1;
  741. }
  742. void CMainWnd::AddTrayIcon()
  743. {
  744. memset(&m_trayIcon, 0, sizeof(NOTIFYICONDATA));
  745. m_trayIcon.cbSize = sizeof(NOTIFYICONDATA);
  746. m_trayIcon.hIcon = ::LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON_DUILIB));
  747. m_trayIcon.hWnd = m_hWnd;
  748. lstrcpy(m_trayIcon.szTip, _T("智铺子收银系统"));
  749. m_trayIcon.uCallbackMessage = WM_SHOWTASK;
  750. m_trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
  751. Shell_NotifyIcon(NIM_ADD, &m_trayIcon);
  752. ShowWindow(SW_HIDE);
  753. }
  754. LRESULT CMainWnd::OnTrayIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  755. {
  756. //如果在图标中单击左键则还原
  757. if(lParam == WM_LBUTTONDOWN)
  758. {
  759. //删除托盘图标
  760. Shell_NotifyIcon(NIM_DELETE, &m_trayIcon);
  761. //显示主窗口
  762. ShowWindow(SW_SHOWNORMAL);
  763. //窗口最大化
  764. SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  765. }
  766. //如果在图标中单击右键则弹出声明式菜单
  767. if(lParam == WM_RBUTTONDOWN)
  768. {
  769. //获取鼠标坐标
  770. POINT pt;
  771. GetCursorPos(&pt);
  772. //右击后点别地可以清除“右击出来的菜单”
  773. SetForegroundWindow(m_hWnd);
  774. //托盘菜单 win32程序使用的是HMENU,如果是MFC程序可以使用CMenu
  775. HMENU hMenu;
  776. //生成托盘菜单
  777. hMenu = CreatePopupMenu();
  778. //添加菜单,关键在于设置的一个标识符 WM_ONCLOSE 点击后会用到
  779. AppendMenu(hMenu, MF_STRING, WM_ONCLOSE, _T("退出"));
  780. //弹出菜单,并把用户所选菜单项的标识符返回
  781. int cmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, NULL, m_hWnd, NULL);
  782. //如果标识符是WM_ONCLOSE则关闭
  783. if(cmd == WM_ONCLOSE)
  784. {
  785. m_trayIcon.hIcon = NULL;
  786. Shell_NotifyIcon(NIM_DELETE, &m_trayIcon);
  787. //退出程序
  788. ::PostQuitMessage(0);
  789. }
  790. }
  791. bHandled = true;
  792. return 0;
  793. }
  794. void CMainWnd::LoginOut(int mode)
  795. {
  796. CSetting::SetParam("setting_is_auto_login", "0", true);
  797. CLoginWnd* pLogin = new CLoginWnd();
  798. if(pLogin == NULL)
  799. {
  800. return;
  801. }
  802. //设置模式
  803. pLogin->SetMode(mode);
  804. pLogin->Create(NULL, _T("智铺子收银系统登录"), UI_WNDSTYLE_DIALOG, 0, 0, 0, 0, 0, NULL);
  805. pLogin->SetIcon(IDI_ICON_DUILIB);
  806. pLogin->CenterWindow();
  807. ::ShowWindow(*pLogin, SW_SHOWNORMAL);
  808. Close();
  809. }
  810. void CMainWnd::SetInfopageWaimaiorderParam(std::string order_id, std::string order_no)
  811. {
  812. m_infopage_waimaiorder_id = order_id;
  813. m_infopage_waimaiorder_no = order_no;
  814. }
  815. void CMainWnd::SetInfopageDianneiorderParam(std::string order_id)
  816. {
  817. m_infopage_dianneiorder_id = order_id;
  818. }
  819. void CMainWnd::ShowToast(std::wstring toast_value)
  820. {
  821. CToastWnd* pYouhuiDlg = new CToastWnd();
  822. if (pYouhuiDlg != NULL)
  823. {
  824. pYouhuiDlg->Create(m_pm.GetPaintWindow(), _T(""), UI_WNDSTYLE_DIALOG, WS_EX_WINDOWEDGE);
  825. pYouhuiDlg->SetIcon(IDI_ICON_DUILIB);
  826. pYouhuiDlg->CenterWindow();
  827. pYouhuiDlg->SetToast(toast_value);
  828. pYouhuiDlg->ShowWindow();
  829. }
  830. }
  831. //全局监听键盘输入
  832. void CMainWnd::RegKeyboardRawInput()
  833. {
  834. RAWINPUTDEVICE rawInputDevice[1];
  835. rawInputDevice[0].usUsagePage = 0x01;//设备类
  836. rawInputDevice[0].usUsage = 0x06;//设备类内的具体设备
  837. rawInputDevice[0].dwFlags = RIDEV_INPUTSINK;//意味着即使窗口失去焦点位置,仍然会一直接收输入消息
  838. rawInputDevice[0].hwndTarget = m_hWnd;
  839. if (RegisterRawInputDevices(rawInputDevice, 1, sizeof(rawInputDevice[0])) == FALSE)
  840. {
  841. printf("RegisterRawInputDevices failed");
  842. }
  843. }