CValueWnd.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. #include "../pch/pch.h"
  2. #include "CValueWnd.h"
  3. #include "../tool/CComHelper.h"
  4. #include "../tool/CSerialPort.h"
  5. void CValueWnd::Notify(TNotifyUI& msg)
  6. {
  7. if(msg.sType == _T("click"))
  8. {
  9. if(msg.pSender->GetName() == _T("closebtn"))
  10. {
  11. PostQuitMessage(0);
  12. return;
  13. }
  14. }
  15. }
  16. void CValueWnd::Init()
  17. {
  18. //初始化窗口位置
  19. InitWndPos();
  20. //添加托盘图标
  21. AddTrayIcon();
  22. //初始化菜单窗口
  23. pMenu = new CMenuWnd();
  24. pMenu->Create(m_hWnd, L"智铺子收银插件菜单", WS_POPUP, WS_EX_TOOLWINDOW);
  25. pMenu->ShowWindow(false);
  26. //先暂停Hook工作(因为不一定是串口模式)
  27. ::SetHookStatus(false);
  28. //再安装钩子
  29. BOOL ret = InstallHook();
  30. //开始启动监听
  31. RestartWatch();
  32. /*
  33. std::thread(&CValueWnd::ReadValue, this).detach();
  34. std::thread(&CValueWnd::WatchWnd, this).detach();
  35. //开始测试ocr
  36. tesseract::TessBaseAPI tess;
  37. if(tess.Init("./tessdata", "eng"))
  38. {
  39. std::cout << "OCRTesseract: Could not initialize tesseract." << std::endl;
  40. return ;
  41. }
  42. // setup
  43. tess.SetPageSegMode(tesseract::PageSegMode::PSM_AUTO);
  44. tess.SetVariable("save_best_choices", "T");
  45. // read image
  46. auto pixs = pixRead("D:\\3.png");
  47. if(!pixs)
  48. {
  49. std::cout << "Cannot open input file: " << "D:\1.png" << std::endl;
  50. return ;
  51. }
  52. // recognize
  53. tess.SetImage(pixs);
  54. tess.Recognize(0);
  55. // get result and delete[] returned char* string
  56. std::string aaa = tess.GetUTF8Text();
  57. // cleanup
  58. tess.Clear();
  59. pixDestroy(&pixs);*/
  60. }
  61. void CValueWnd::RestartWatch()
  62. {
  63. std::string system_setting_jinezhuaqu_setting_type = CSetting::GetParam("system_setting_jinezhuaqu_setting_type");
  64. m_nWatchType = atoi(system_setting_jinezhuaqu_setting_type.c_str());
  65. if (m_nWatchType == 1)
  66. {
  67. //更新监听的端口号
  68. std::string system_setting_jinezhuaqu_setting_chuankou_num = CSetting::GetParam("system_setting_jinezhuaqu_setting_chuankou_num");
  69. if (system_setting_jinezhuaqu_setting_chuankou_num == "")
  70. {
  71. //参数错误
  72. return;
  73. }
  74. std::wstring ws_system_setting_jinezhuaqu_setting_chuankou_num = CLewaimaiString::UTF8ToUnicode(system_setting_jinezhuaqu_setting_chuankou_num);
  75. //设置窗口句柄
  76. ::SetHwnd(m_hWnd);
  77. //设置串口端口号
  78. //统一成大写
  79. std::transform(system_setting_jinezhuaqu_setting_chuankou_num.begin(), system_setting_jinezhuaqu_setting_chuankou_num.end(), system_setting_jinezhuaqu_setting_chuankou_num.begin(), ::toupper);
  80. 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);
  81. ::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());
  82. //开始监听工作
  83. ::SetHookStatus(true);
  84. //暂停其他监听的
  85. }
  86. }
  87. void CValueWnd::ReadValue()
  88. {
  89. //读取串口的模式
  90. //CComHelper helper;
  91. //std::vector<std::wstring> comVector = helper.getComPort();
  92. //for (std::vector<std::wstring>::iterator it = comVector.begin(); it != comVector.end(); it++)
  93. //{
  94. // std::wstring comName = *it;
  95. // LOG_INFO("comName:" << comName.c_str());
  96. //}
  97. //int nReadType = 1;
  98. //if (nReadType == 1)
  99. //{
  100. // std::wstring com_name = L"COM2";
  101. // CSerialPort serial(com_name.c_str(), 2400);
  102. // bool ret = serial.openComm();
  103. // if (!ret)
  104. // {
  105. // LOG_INFO("open com failed!");
  106. // return;
  107. // }
  108. // while (true)
  109. // {
  110. // //开始读取串口的数据
  111. // char a[1024] = { 0 };
  112. // serial.readFromComm(a, 1024);
  113. // LOG_INFO("a:" << a);
  114. // Sleep(200);
  115. // }
  116. // serial.closeComm();
  117. //}
  118. FindValueWnd(L"");
  119. }
  120. void CValueWnd::WatchWnd()
  121. {
  122. while(true)
  123. {
  124. if(m_watchWnd != NULL)
  125. {
  126. char szTitle[MAX_PATH] = { 0 };
  127. LPSTR lpWindowName = szTitle;
  128. std::string value;
  129. int ret = ::SendMessageA(m_watchWnd, WM_GETTEXT, (WPARAM)(MAX_PATH), (LPARAM)lpWindowName);
  130. if(ret == 0)
  131. {
  132. //说明m_watchWnd已经失效了
  133. value = "0.00";
  134. m_watchWnd = NULL;
  135. }
  136. else
  137. {
  138. value = lpWindowName;
  139. }
  140. if(value != m_watchValue)
  141. {
  142. m_watchValue = value;
  143. SendMessage(WM_WATCH_WND_UPDATE, NULL, NULL);
  144. }
  145. }
  146. else
  147. {
  148. //根据上次保存的记录,来查找符合条件的窗口
  149. if(g_valuewnd_vector.size() > 0)
  150. {
  151. ValueWnd lastWnd = g_valuewnd_vector[0];
  152. //获得进程名字
  153. std::wstring processName = lastWnd.processName;
  154. //根据进程名字,找到对应的主窗口
  155. HWND mainWnd = GetWndHwnd(processName.c_str(), lastWnd.wndTitle);
  156. if(mainWnd == NULL)
  157. {
  158. //说明这个进程还没有启动
  159. m_watchWnd = NULL;
  160. }
  161. else
  162. {
  163. //根据Z序查找目标窗口
  164. char szTitle[MAX_PATH] = { 0 };
  165. int nMaxCount = MAX_PATH;
  166. LPSTR lpWindowName = szTitle;
  167. GetWindowTextA(mainWnd, lpWindowName, nMaxCount);
  168. if(string(lpWindowName) != lastWnd.wndTitle)
  169. {
  170. //这次根据进程名字找到的主窗口,窗口名字和上次的不一样,无效
  171. m_watchWnd = NULL;
  172. }
  173. else
  174. {
  175. ValueWnd newWnd;
  176. newWnd.wndTitle = lpWindowName;
  177. newWnd.TopWnd = mainWnd;
  178. newWnd.z_order = lastWnd.z_order;
  179. newWnd.processName = lastWnd.processName;
  180. newWnd.selfWnd = NULL;
  181. g_zorder = 0;
  182. EnumChildWindows(mainWnd, EnumMainwndChildProc, (LPARAM)(&newWnd));
  183. if(newWnd.selfWnd != NULL)
  184. {
  185. //找到了
  186. m_watchWnd = newWnd.selfWnd;
  187. }
  188. }
  189. }
  190. }
  191. }
  192. Sleep(200);
  193. }
  194. }
  195. LRESULT CValueWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  196. {
  197. LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
  198. styleValue &= ~WS_CAPTION;
  199. ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  200. // 把自己的窗口句柄与窗口绘制管理器挂接在一起
  201. m_pm.Init(m_hWnd);
  202. m_pm.AddPreMessageFilter(this);
  203. CDialogBuilder builder;
  204. CControlUI* pRoot = builder.Create(_T("value.xml"), (UINT)0, NULL, &m_pm);
  205. ASSERT(pRoot && "Failed to parse XML");
  206. // 把这些控件绘制到本窗口上
  207. m_pm.AttachDialog(pRoot);
  208. // 把自己加入到CPaintManagerUI的m_aNotifiers数组中,用于处理Notify函数
  209. //m_pm.AddNotifier(this);
  210. //进行一些初始化工作
  211. Init();
  212. return 0;
  213. }
  214. LRESULT CValueWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  215. {
  216. bHandled = FALSE;
  217. return 0;
  218. }
  219. /*
  220. *这个是窗口被销毁的时候调用的
  221. **/
  222. LRESULT CValueWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  223. {
  224. bHandled = FALSE;
  225. return 0;
  226. }
  227. LRESULT CValueWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  228. {
  229. if(::IsIconic(*this))
  230. {
  231. bHandled = FALSE;
  232. }
  233. return (wParam == 0) ? TRUE : FALSE;
  234. }
  235. LRESULT CValueWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  236. {
  237. return 0;
  238. }
  239. LRESULT CValueWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  240. {
  241. //在这里设置焦点才有用
  242. CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
  243. if(pAccountEdit)
  244. {
  245. pAccountEdit->SetFocus();
  246. }
  247. return 0;
  248. }
  249. LRESULT CValueWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  250. {
  251. POINT pt;
  252. pt.x = GET_X_LPARAM(lParam);
  253. pt.y = GET_Y_LPARAM(lParam);
  254. ::ScreenToClient(*this, &pt);
  255. RECT rcClient;
  256. ::GetClientRect(*this, &rcClient);
  257. RECT rcCaption = m_pm.GetCaptionRect();
  258. if(pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
  259. && pt.y >= rcCaption.top && pt.y < rcCaption.bottom)
  260. {
  261. CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
  262. if(pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0)
  263. {
  264. return HTCAPTION;
  265. }
  266. }
  267. return HTCLIENT;
  268. }
  269. LRESULT CValueWnd::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  270. {
  271. /*
  272. //获取鼠标点击位置
  273. int xPos = LOWORD(lParam);
  274. int yPos = HIWORD(lParam);
  275. //將位置转换为屏幕坐标
  276. POINT pt = { xPos,yPos };
  277. ClientToScreen(m_hWnd, &pt);
  278. RECT menuWndRect = { 0 };
  279. ::GetWindowRect(pMenu->GetHWND(), &menuWndRect);
  280. if (pt.x <= menuWndRect.left || pt.x >= menuWndRect.right
  281. || pt.y <= menuWndRect.top || pt.y >= menuWndRect.bottom)
  282. {
  283. pMenu->ShowWindow(false);
  284. }
  285. bHandled = FALSE;
  286. return 0;*/
  287. bHandled = FALSE;
  288. return 0;
  289. }
  290. LRESULT CValueWnd::OnRButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  291. {
  292. /*
  293. int xPos = LOWORD(lParam);
  294. int yPos = HIWORD(lParam);
  295. POINT pt = { xPos,yPos };
  296. //可能是因为整个窗口都是标题区域,这里不需要做转换
  297. //ClientToScreen(m_hWnd, &pt);
  298. pMenu->ShowWindow(true);
  299. ::SetWindowPos(pMenu->GetHWND(), NULL, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  300. bHandled = FALSE;
  301. return 0;*/
  302. ShowMenu();
  303. bHandled = true;
  304. return 0;
  305. }
  306. LRESULT CValueWnd::OnKexianUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  307. {
  308. //如果当前不是串口模式,直接忽略
  309. if (m_nWatchType != 1)
  310. {
  311. bHandled = TRUE;
  312. return true;
  313. }
  314. //收到了客显数据消息,读取客显数据
  315. char data[MAX_DATA_LENGTH] = { 0 };
  316. int data_length = 0;
  317. HookGetData(data, &data_length);
  318. if(data_length == 0)
  319. {
  320. bHandled = TRUE;
  321. return true;
  322. }
  323. UpdateKexian(data, data_length);
  324. bHandled = TRUE;
  325. return true;
  326. }
  327. LRESULT CValueWnd::OnWatchWndUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  328. {
  329. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  330. std::string money_show = CLewaimaiString::DoubleToString(atof(m_watchValue.c_str()), 2);
  331. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  332. return TRUE;
  333. }
  334. LRESULT CValueWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  335. {
  336. LRESULT lRes = 0;
  337. BOOL bHandled = TRUE;
  338. switch(uMsg)
  339. {
  340. case WM_CREATE:
  341. lRes = OnCreate(uMsg, wParam, lParam, bHandled);
  342. break;
  343. case WM_CLOSE:
  344. lRes = OnClose(uMsg, wParam, lParam, bHandled);
  345. break;
  346. case WM_DESTROY:
  347. lRes = OnDestroy(uMsg, wParam, lParam, bHandled);
  348. break;
  349. case WM_NCACTIVATE:
  350. lRes = OnNcActivate(uMsg, wParam, lParam, bHandled);
  351. break;
  352. case WM_NCLBUTTONDOWN:
  353. lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled);
  354. break;
  355. case WM_NCRBUTTONDOWN:
  356. lRes = OnRButtonDown(uMsg, wParam, lParam, bHandled);
  357. break;
  358. case WM_NCCALCSIZE:
  359. lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
  360. break;
  361. case WM_NCPAINT:
  362. lRes = OnNcPaint(uMsg, wParam, lParam, bHandled);
  363. break;
  364. case WM_NCHITTEST:
  365. lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);
  366. break;
  367. case WM_SHOWTASK:
  368. lRes = OnTrayIcon(uMsg, wParam, lParam, bHandled);
  369. break;
  370. case WM_HOOK_MESSAGE:
  371. lRes = OnKexianUpdate(uMsg, wParam, lParam, bHandled);
  372. break;
  373. case WM_WATCH_WND_UPDATE:
  374. lRes = OnWatchWndUpdate(uMsg, wParam, lParam, bHandled);
  375. break;
  376. default:
  377. bHandled = FALSE;
  378. }
  379. if(bHandled)
  380. {
  381. return lRes;
  382. }
  383. if(m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
  384. {
  385. return lRes;
  386. }
  387. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  388. }
  389. LRESULT CValueWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
  390. {
  391. return false;
  392. }
  393. void CValueWnd::AddTrayIcon()
  394. {
  395. memset(&m_trayIcon, 0, sizeof(NOTIFYICONDATA));
  396. m_trayIcon.cbSize = sizeof(NOTIFYICONDATA);
  397. m_trayIcon.hIcon = ::LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON_DUILIB));
  398. m_trayIcon.hWnd = m_hWnd;
  399. lstrcpy(m_trayIcon.szTip, _T("智铺子收银插件"));
  400. m_trayIcon.uCallbackMessage = WM_SHOWTASK;
  401. m_trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
  402. Shell_NotifyIcon(NIM_ADD, &m_trayIcon);
  403. }
  404. LRESULT CValueWnd::OnTrayIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  405. {
  406. //如果在图标中单击左键则还原
  407. if(lParam == WM_LBUTTONDOWN)
  408. {
  409. }
  410. //如果在图标中单击右键则弹出声明式菜单
  411. if(lParam == WM_RBUTTONDOWN)
  412. {
  413. ShowMenu();
  414. }
  415. bHandled = true;
  416. return 0;
  417. }
  418. void CValueWnd::UpdateKexian(const char* data, int length)
  419. {
  420. std::string new_data = data;
  421. //清屏命令
  422. std::string clear_command = "\f";
  423. //4个信号灯全灭
  424. std::string quanmie_command = "\x1bs0";
  425. std::string show_command = "\x1bQA";
  426. std::string type_command = "\x1bs";
  427. if (new_data == clear_command || new_data == quanmie_command)
  428. {
  429. //清屏命令,或者是熄灭灯的命令
  430. return;
  431. }
  432. if(new_data.find(show_command) == new_data.npos)
  433. {
  434. return;
  435. }
  436. std::string money;
  437. int nPos = new_data.find(show_command);
  438. int nTypePos = new_data.find(type_command, nPos + 1);
  439. if(nTypePos == new_data.npos)
  440. {
  441. //没有类型信息,有些收银机(比如思迅天店)就是不传类型信息,这种只有传什么显示什么了
  442. int nTabPos = new_data.find("\r", nPos + 1);
  443. if(nTabPos == new_data.npos)
  444. {
  445. //制表符也没有
  446. return;
  447. }
  448. money = new_data.substr(nPos + 3, nTabPos - nPos - 3);
  449. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  450. std::string money_show = CLewaimaiString::DoubleToString(atof(money.c_str()), 2);
  451. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  452. }
  453. else
  454. {
  455. std::string value_type = new_data.substr(nTypePos + 2, 1);
  456. money = new_data.substr(nPos + 3, nTypePos - nPos - 3 - 1);
  457. if(value_type == "2")
  458. {
  459. //这个表示是总计的,那么就要刷新金额显示
  460. CLabelUI* valueLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("value")));
  461. std::string money_show = CLewaimaiString::DoubleToString(atof(money.c_str()), 2);
  462. valueLabel->SetText(CLewaimaiString::UTF8ToUnicode(money_show).c_str());
  463. }
  464. else
  465. {
  466. //这种情况传输的是一些找零、单价之类的信息,不更新客显金额
  467. }
  468. }
  469. return;
  470. }
  471. void CValueWnd::FindValueWnd(std::wstring value)
  472. {
  473. //先查找子窗口
  474. EnumWindows(EnumWindowsProc, NULL);
  475. //展示查找结果
  476. int nCount = (int)g_valuewnd_vector.size();
  477. if(nCount > 0)
  478. {
  479. //开始监听这个窗口的内容变化
  480. ValueWnd selectWnd = g_valuewnd_vector[0];
  481. m_watchWnd = selectWnd.selfWnd;
  482. }
  483. }
  484. void CValueWnd::InitWndPos()
  485. {
  486. ASSERT(::IsWindow(m_hWnd));
  487. ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD) == 0);
  488. RECT rcDlg = { 0 };
  489. ::GetWindowRect(m_hWnd, &rcDlg);
  490. RECT rcArea = { 0 };
  491. RECT rcCenter = { 0 };
  492. HWND hWnd = *this;
  493. HWND hWndParent = ::GetParent(m_hWnd);
  494. HWND hWndCenter = ::GetWindowOwner(m_hWnd);
  495. if(hWndCenter != NULL)
  496. {
  497. hWnd = hWndCenter;
  498. }
  499. // 处理多显示器模式下屏幕居中
  500. MONITORINFO oMonitor = {};
  501. oMonitor.cbSize = sizeof(oMonitor);
  502. ::GetMonitorInfo(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &oMonitor);
  503. rcArea = oMonitor.rcWork;
  504. if(hWndCenter == NULL)
  505. {
  506. rcCenter = rcArea;
  507. }
  508. else
  509. {
  510. ::GetWindowRect(hWndCenter, &rcCenter);
  511. }
  512. int DlgWidth = rcDlg.right - rcDlg.left;
  513. int DlgHeight = rcDlg.bottom - rcDlg.top;
  514. // Find dialog's upper left based on rcCenter
  515. int xLeft = rcCenter.right - DlgWidth - 60;
  516. int yTop = 100;
  517. // The dialog is outside the screen, move it inside
  518. if(xLeft < rcArea.left)
  519. {
  520. xLeft = rcArea.left;
  521. }
  522. else if(xLeft + DlgWidth > rcArea.right)
  523. {
  524. xLeft = rcArea.right - DlgWidth;
  525. }
  526. if(yTop < rcArea.top)
  527. {
  528. yTop = rcArea.top;
  529. }
  530. else if(yTop + DlgHeight > rcArea.bottom)
  531. {
  532. yTop = rcArea.bottom - DlgHeight;
  533. }
  534. ::SetWindowPos(m_hWnd, HWND_TOPMOST, xLeft, yTop, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  535. }
  536. void CValueWnd::ShowMenu()
  537. {
  538. //获取鼠标坐标
  539. POINT pt;
  540. GetCursorPos(&pt);
  541. //右击后点别地可以清除“右击出来的菜单”
  542. SetForegroundWindow(m_hWnd);
  543. //托盘菜单,win32程序使用的是HMENU,如果是MFC程序可以使用CMenu
  544. HMENU hMenu;
  545. //生成托盘菜单
  546. hMenu = CreatePopupMenu();
  547. //添加菜单,关键在于设置的一个标识符 WM_ONCLOSE 点击后会用到
  548. AppendMenu(hMenu, MF_STRING, WM_MENU_SYSTEM_SETTING, _T("系统设置"));
  549. AppendMenu(hMenu, MF_STRING, WM_ONCLOSE, _T("退出"));
  550. //弹出菜单,并把用户所选菜单项的标识符返回
  551. int cmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, NULL, m_hWnd, NULL);
  552. //如果标识符是WM_ONCLOSE则关闭
  553. if (cmd == WM_ONCLOSE)
  554. {
  555. //退出程序
  556. ::PostQuitMessage(0);
  557. }
  558. if (cmd == WM_MENU_SYSTEM_SETTING)
  559. {
  560. if (m_is_show_setting == true)
  561. {
  562. return;
  563. }
  564. CSystemSettingWnd* pSystemSettingFrame = new CSystemSettingWnd(this);
  565. if (pSystemSettingFrame != NULL)
  566. {
  567. m_is_show_setting = true;
  568. pSystemSettingFrame->Create(NULL, _T(""), UI_WNDSTYLE_DIALOG, WS_EX_TOOLWINDOW);
  569. pSystemSettingFrame->SetIcon(IDI_ICON_DUILIB);
  570. pSystemSettingFrame->CenterWindow();
  571. UINT ret = pSystemSettingFrame->ShowModal();
  572. m_is_show_setting = false;
  573. if (ret == IDOK)
  574. {
  575. }
  576. else if (ret == IDCANCEL)
  577. {
  578. }
  579. }
  580. }
  581. }