PropertiesWnd.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. // 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
  2. // ("Fluent UI"),该示例仅作为参考资料提供,
  3. // 用以补充《Microsoft 基础类参考》和
  4. // MFC C++ 库软件随附的相关电子文档。
  5. // 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
  6. // 若要了解有关 Fluent UI 许可计划的详细信息,请访问
  7. // http://msdn.microsoft.com/officeui。
  8. //
  9. // 版权所有 (C) Microsoft Corporation
  10. // 保留所有权利。
  11. #include "stdafx.h"
  12. #include "PropertiesWnd.h"
  13. #include "Resource.h"
  14. #include "MainFrm.h"
  15. #include "FieldTestTool.h"
  16. #include "filehelper.h"
  17. #define MINIMUM_WINDOWS_X 395
  18. #define MINIMUM_WINDOWS_Y 535
  19. #define MAX_SWITCH_LEN 16
  20. #define MAX_SENDDATA 512
  21. #define TMSG_QUITE_THREAD 9
  22. #define TMSG_START_LEARN 10
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #define new DEBUG_NEW
  27. #endif
  28. unsigned char TwoHexChar2Char(char ch1, char ch2)
  29. {
  30. char Numb1;
  31. char Numb2;
  32. if (ch1 >= 'A')
  33. Numb1 = (toupper(ch1) - '0' - 7) * 16;
  34. else
  35. Numb1 = (ch1 - '0') * 16;
  36. if (ch2 >= 'A')
  37. Numb2 = (toupper(ch2) - '0' - 7);
  38. else
  39. Numb2 = (ch2 - '0');
  40. return (Numb1 + Numb2);
  41. }
  42. COLORREF HexColor2RGB(std::string strHexColor)
  43. {
  44. DWORD r = TwoHexChar2Char(strHexColor[0], strHexColor[1]);
  45. DWORD g = TwoHexChar2Char(strHexColor[2], strHexColor[3]);
  46. DWORD b = TwoHexChar2Char(strHexColor[4], strHexColor[5]);
  47. return RGB(r, g, b);
  48. }
  49. std::string RGBColor2Hex(DWORD dwRGB)
  50. {
  51. DWORD r = GetRValue(dwRGB);
  52. DWORD g = GetGValue(dwRGB);
  53. DWORD b = GetBValue(dwRGB);
  54. TCHAR szHex[8] = { 0 };
  55. _stprintf_s(szHex, _T("%02X%02X%02X"), r, g, b);
  56. return std::string(szHex);
  57. }
  58. /////////////////////////////////////////////////////////////////////////////
  59. // CResourceViewBar
  60. KeyInfo* CPropertiesWnd::m_pKeyInfo = NULL;
  61. CPropertiesWnd::CPropertiesWnd()
  62. {
  63. m_dwThreadId = 0;
  64. }
  65. CPropertiesWnd::~CPropertiesWnd()
  66. {
  67. }
  68. BEGIN_MESSAGE_MAP(CPropertiesWnd, CDockablePane)
  69. ON_WM_CREATE()
  70. ON_WM_SIZE()
  71. ON_WM_SETFOCUS()
  72. ON_WM_SETTINGCHANGE()
  73. ON_WM_PAINT()
  74. // 信号按钮;
  75. ON_COMMAND_RANGE(BTNID, BTNID + 100, OnSignalBtnClick)
  76. ON_UPDATE_COMMAND_UI_RANGE(BTNID, BTNID + 100, OnUpdateSignalBtnClick)
  77. // 下拉框事件;
  78. ON_CBN_SELCHANGE(1, &CPropertiesWnd::OnCbnSelchangeSingals)
  79. ON_WM_DESTROY()
  80. END_MESSAGE_MAP()
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CResourceViewBar 消息处理程序
  83. void CPropertiesWnd::AdjustLayout()
  84. {
  85. if (GetSafeHwnd() == NULL)
  86. {
  87. return;
  88. }
  89. CRect rectClient;
  90. GetClientRect(rectClient);
  91. m_wndSignalCombo.GetWindowRect(&m_rcCombobox);
  92. ScreenToClient(m_rcCombobox);
  93. int cyCmb = m_rcCombobox.Size().cy;
  94. m_wndSignalCombo.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), 200, SWP_NOACTIVATE | SWP_NOZORDER);
  95. TRACE2(_T("更新后的大小:%d,%d\n"), rectClient.Width(), rectClient.Height());
  96. int sx = 0, sy = m_rcCombobox.bottom + m_nTopMargin;
  97. int i = 0, id = 10000;
  98. int nWidth = (rectClient.Width() - 25) / m_nCols;
  99. DWORD dwStyle = WS_CHILD | WS_VISIBLE;
  100. for (std::vector<KeyInfo>::iterator it = m_vtKeyInfo.begin(); it != m_vtKeyInfo.end(); it++)
  101. {
  102. if (it->pbtnInfo->pBTN == NULL)
  103. continue;
  104. if (i != 0 && i % m_nCols == 0)
  105. {//换行;
  106. sy += it->height + m_nRowSpacing;
  107. }
  108. //sx = m_nLeftMargin + (i % m_nCols) * nWidth + (i % m_nCols + 1) * m_nColSpacing;
  109. sx = m_nLeftMargin + (i % m_nCols) * (nWidth + m_nColSpacing);
  110. it->pbtnInfo->pBTN->SetWindowPos(NULL, sx, sy, nWidth, it->height, SWP_NOACTIVATE | SWP_NOZORDER);
  111. i++;
  112. }
  113. }
  114. int CPropertiesWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  115. {
  116. if (CDockablePane::OnCreate(lpCreateStruct) == -1)
  117. return -1;
  118. CRect rectDummy;
  119. rectDummy.SetRectEmpty();
  120. // 创建组合:
  121. const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  122. if (!m_wndSignalCombo.Create(dwViewStyle | WS_VSCROLL | WS_HSCROLL, rectDummy, this, 1))
  123. {
  124. TRACE0("未能创建属性组合 \n");
  125. return -1; // 未能创建
  126. }
  127. InitPropList();
  128. // 设置最小窗体;
  129. SetMinSize((530, 260));
  130. LoadSignals();
  131. m_wndSignalCombo.SelectString(0, Global::g_Config.twUseSignal.c_str());
  132. m_strXMLPath = Global::g_Config.twSignaldir + _T("\\") + Global::g_Config.twUseSignal + _T(".xml");
  133. LoadKeyInfo(m_vtKeyInfo, m_strXMLPath);
  134. AdjustLayout();
  135. return 0;
  136. }
  137. void CPropertiesWnd::OnSize(UINT nType, int cx, int cy)
  138. {
  139. CDockablePane::OnSize(nType, cx, cy);
  140. AdjustLayout();
  141. }
  142. void CPropertiesWnd::InitPropList()
  143. {
  144. SetPropListFont();
  145. }
  146. void CPropertiesWnd::OnSetFocus(CWnd* pOldWnd)
  147. {
  148. CDockablePane::OnSetFocus(pOldWnd);
  149. }
  150. void CPropertiesWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  151. {
  152. CDockablePane::OnSettingChange(uFlags, lpszSection);
  153. SetPropListFont();
  154. }
  155. void CPropertiesWnd::OnSignalBtnClick(UINT uId) // 发送遥控信号;
  156. {
  157. CWnd* pWnd = GetFocus();
  158. int id = pWnd->GetDlgCtrlID();
  159. if (id >= BTNID && id <= BTNID + 100)
  160. {
  161. CString text;
  162. pWnd->GetWindowText(text);
  163. KeyInfo* pKey = m_map_key.find(id)->second;
  164. // 发送红外信号或学习;
  165. Global::g_bLearn ? LearnInfraedSignal(uId, pKey) : SendInfraedSignal(pKey);
  166. }
  167. }
  168. void CPropertiesWnd::OnUpdateSignalBtnClick(CCmdUI* pCmdUI)
  169. {
  170. pCmdUI->Enable(m_map_key.find(pCmdUI->m_nID)->second->bUse);
  171. }
  172. void CPropertiesWnd::OnCbnSelchangeSingals()
  173. {
  174. // TODO: 在此添加控件通知处理程序代码
  175. CString strSignal;
  176. int nCurSel = m_wndSignalCombo.GetCurSel();
  177. if (nCurSel != CB_ERR)
  178. {
  179. std::string signalpath;
  180. m_wndSignalCombo.GetLBText(nCurSel, strSignal);
  181. // 保存到配置文件中;
  182. Global::g_Config.twUseSignal = strSignal.GetString();
  183. WritePrivateProfileString("TestWizard", "useSignal", strSignal.GetString(), Global::g_szConfig);
  184. SetAllBTNUnUsed();
  185. m_strXMLPath = Global::g_Config.twSignaldir + _T("\\") + Global::g_Config.twUseSignal + _T(".xml");
  186. LoadKeyInfo(m_vtKeyInfo, m_strXMLPath);
  187. }
  188. }
  189. void CPropertiesWnd::SetPropListFont()
  190. {
  191. ::DeleteObject(m_fntPropList.Detach());
  192. LOGFONT lf;
  193. afxGlobalData.fontRegular.GetLogFont(&lf);
  194. NONCLIENTMETRICS info;
  195. info.cbSize = sizeof(info);
  196. afxGlobalData.GetNonClientMetrics(info);
  197. lf.lfHeight = info.lfMenuFont.lfHeight;
  198. lf.lfWeight = info.lfMenuFont.lfWeight;
  199. lf.lfItalic = info.lfMenuFont.lfItalic;
  200. m_fntPropList.CreateFontIndirect(&lf);
  201. }
  202. void CPropertiesWnd::LoadSignals()
  203. {
  204. filehelper fh;
  205. m_vtTWSignal.clear();
  206. fh.getfiles_findout_subfolder(Global::g_Config.twSignaldir.c_str(), _T("*.xml"), &m_vtTWSignal);
  207. m_wndSignalCombo.ResetContent();
  208. for (std::vector<TString>::iterator it = m_vtTWSignal.begin(); it != m_vtTWSignal.end(); it++)
  209. {
  210. m_wndSignalCombo.AddString(fh.getfilename(it->c_str()).c_str());
  211. }
  212. //AutoSetDroppedWidth(&m_cbSignals);
  213. }
  214. void CPropertiesWnd::LoadKeyInfo(std::vector<KeyInfo>& vtKeyInfo, TString path)
  215. {
  216. // 解析xml;
  217. tinyxml2::XMLDocument doc;
  218. if (tinyxml2::XML_SUCCESS != doc.LoadFile(path.c_str()))
  219. {
  220. return;
  221. }
  222. vtKeyInfo.clear();
  223. std::string data;
  224. tinyxml2::XMLElement* pXmlRoot = NULL;
  225. if ((pXmlRoot = doc.RootElement()) != NULL)
  226. {
  227. if (_tcsicmp(pXmlRoot->Value(), "KeyList") == 0)
  228. {
  229. //////////////////////////////////////////////////////////////////////////
  230. // 获取属性;
  231. m_curKeyLayout.cols = pXmlRoot->Attribute("cols") ? pXmlRoot->Attribute("cols") : "3";
  232. m_curKeyLayout.with = pXmlRoot->Attribute("with") ? pXmlRoot->Attribute("with") : "58";
  233. m_curKeyLayout.height = pXmlRoot->Attribute("height") ? pXmlRoot->Attribute("height") : "25";
  234. m_curKeyLayout.rowSpacing = pXmlRoot->Attribute("rowSpacing") ? pXmlRoot->Attribute("rowSpacing") : "5";
  235. m_curKeyLayout.colSpacing = pXmlRoot->Attribute("colSpacing") ? pXmlRoot->Attribute("colSpacing") : "5";
  236. m_curKeyLayout.leftMargin = pXmlRoot->Attribute("leftMargin") ? pXmlRoot->Attribute("leftMargin") : "8";
  237. m_curKeyLayout.topMargin = pXmlRoot->Attribute("topMargin") ? pXmlRoot->Attribute("topMargin") : "8";
  238. m_curKeyLayout.ver = pXmlRoot->Attribute("ver") ? pXmlRoot->Attribute("ver") : "1.0.0.1";
  239. m_curKeyLayout.desc = pXmlRoot->Attribute("desc") ? pXmlRoot->Attribute("desc") : "key info";
  240. m_nCols = _tstoi(m_curKeyLayout.cols.c_str());
  241. m_nRowSpacing = _tstoi(m_curKeyLayout.rowSpacing.c_str());
  242. m_nColSpacing = _tstoi(m_curKeyLayout.colSpacing.c_str());
  243. m_nTopMargin = _tstoi(m_curKeyLayout.topMargin.c_str());
  244. m_nLeftMargin = _tstoi(m_curKeyLayout.leftMargin.c_str());
  245. int nWidth = _tstoi(m_curKeyLayout.with.c_str());
  246. int nHeight = _tstoi(m_curKeyLayout.height.c_str());
  247. //////////////////////////////////////////////////////////////////////////
  248. // 子项;
  249. tinyxml2::XMLElement* pXmlElent = pXmlRoot->FirstChildElement();
  250. while (pXmlElent)
  251. {
  252. if (_tcsicmp(pXmlElent->Value(), _T("ITEM")) == 0)
  253. {
  254. KeyInfo keyInfo;
  255. // 获取属性值;
  256. keyInfo.width = pXmlElent->Attribute("with") ? _ttol(pXmlElent->Attribute("with")) : nWidth;
  257. keyInfo.height = pXmlElent->Attribute("height") ? _ttol(pXmlElent->Attribute("height")) : nHeight;
  258. keyInfo.color = HexColor2RGB(pXmlElent->Attribute("color") ? pXmlElent->Attribute("color") : "87CEFA");
  259. tinyxml2::XMLElement* pItem = pXmlElent->FirstChildElement();
  260. while (pItem)
  261. {
  262. if (_tcsicmp(pItem->Value(), _T("NAME")) == 0)
  263. {
  264. keyInfo.strName = pItem->GetText();
  265. }
  266. else if (_tcsicmp(pItem->Value(), _T("USE")) == 0)
  267. {
  268. keyInfo.bUse = pItem->BoolText(true);
  269. }
  270. else if (_tcsicmp(pItem->Value(), _T("DESC")) == 0)
  271. {
  272. keyInfo.strDesc = pItem->GetText();
  273. }
  274. else if (_tcsicmp(pItem->Value(), _T("TYPE")) == 0)
  275. {
  276. keyInfo.strType = pItem->GetText();
  277. }
  278. else if (_tcsicmp(pItem->Value(), _T("VALUE")) == 0)
  279. {
  280. keyInfo.strValue = pItem->GetText();
  281. }
  282. else if (_tcsicmp(pItem->Value(), _T("VALUE2")) == 0)
  283. {
  284. keyInfo.strValue2 = pItem->GetText();
  285. }
  286. else if (_tcsicmp(pItem->Value(), _T("VALUE3")) == 0)
  287. {
  288. keyInfo.strValue3 = pItem->GetText();
  289. }
  290. else if (_tcsicmp(pItem->Value(), _T("VALUE4")) == 0)
  291. {
  292. keyInfo.strValue4 = pItem->GetText();
  293. }
  294. pItem = pItem->NextSiblingElement();
  295. }
  296. keyInfo.pbtnInfo = GetUnUseBTN();
  297. if (keyInfo.pbtnInfo == NULL)
  298. {
  299. BTNInfo* pbtnInfo = new BTNInfo();
  300. pbtnInfo->pBTN = new CMFCButton();
  301. m_vtBTNInfo.push_back(pbtnInfo);
  302. keyInfo.pbtnInfo = pbtnInfo;
  303. }
  304. SetBTNStatus(keyInfo.pbtnInfo, TRUE);
  305. vtKeyInfo.push_back(keyInfo);
  306. }
  307. pXmlElent = pXmlElent->NextSiblingElement();
  308. }
  309. }
  310. }
  311. int sx = 0, sy = m_rcCombobox.bottom + m_nTopMargin;
  312. int i = 0, id = 10000;
  313. DWORD dwStyle = WS_CHILD | WS_VISIBLE;
  314. int maxX = 0, maxY = 0;
  315. for (std::vector<KeyInfo>::iterator it = vtKeyInfo.begin(); it != vtKeyInfo.end(); it++)
  316. {
  317. if (i != 0 && i % m_nCols == 0)
  318. {//换行;
  319. sy += it->height + m_nRowSpacing;
  320. }
  321. sx = (i % m_nCols) * it->width + (i % m_nCols + 1) * m_nColSpacing;
  322. //m_nDefaultWidth = m_nLeftMargin + m_nCols * it->width + m_nCols * m_nColSpacing;
  323. if (!it->pbtnInfo->bCreated)
  324. {
  325. it->pbtnInfo->pBTN->Create(it->strName.c_str(), dwStyle, CRect(sx, sy, sx + it->width, sy + it->height), this, BTNID + i);
  326. it->pbtnInfo->bCreated = true;
  327. // 设置透明false以显示背景色
  328. it->pbtnInfo->pBTN->m_bTransparent = FALSE;
  329. it->pbtnInfo->pBTN->m_bDontUseWinXPTheme = TRUE;
  330. // 消除单击时黑色内圈;
  331. it->pbtnInfo->pBTN->m_bDrawFocus = FALSE;
  332. // 设置按钮扁平样式;
  333. it->pbtnInfo->pBTN->m_nFlatStyle = CMFCButton::FlatStyle::BUTTONSTYLE_FLAT;
  334. // 设置鼠标形状;
  335. it->pbtnInfo->pBTN->SetMouseCursorHand();
  336. }
  337. else
  338. {
  339. it->pbtnInfo->pBTN->SetWindowText(it->strName.c_str());
  340. }
  341. // 设置背景色;
  342. it->pbtnInfo->pBTN->SetFaceColor(it->color, TRUE);
  343. // 显示窗口;
  344. it->pbtnInfo->pBTN->ShowWindow(SW_SHOW);
  345. // 是否禁用;
  346. it->pbtnInfo->pBTN->EnableWindow(it->bUse);
  347. // 存入map中;
  348. m_map_key.insert(std::pair<UINT, KeyInfo*>(BTNID + i, &*it));
  349. i++;
  350. }
  351. std::vector<KeyInfo>::iterator it = vtKeyInfo.begin();
  352. m_nDefaultHeight = m_rcCombobox.bottom + 15 + (vtKeyInfo.size() / m_nCols + (vtKeyInfo.size() % m_nCols > 0 ? 1 : 0)) * (it->height + m_nRowSpacing);
  353. m_nDefaultHeight = m_nDefaultHeight < MINIMUM_WINDOWS_Y ? MINIMUM_WINDOWS_Y : m_nDefaultHeight;
  354. m_nDefaultWidth = m_nLeftMargin * 2 + m_nCols * it->width + m_nCols * m_nColSpacing;
  355. m_nDefaultWidth = m_nDefaultWidth < MINIMUM_WINDOWS_X ? MINIMUM_WINDOWS_X : m_nDefaultWidth;
  356. // 获取标题栏高度;
  357. int nCaptionHeight = 39; //GetSystemMetrics(SM_CYCAPTION);不准 GetWindowRect - GetClientRect
  358. AdjustLayout();
  359. }
  360. void CPropertiesWnd::SaveKeyInfo()
  361. {
  362. tinyxml2::XMLDocument doc;
  363. tinyxml2::XMLElement* pXmlRoot = NULL;
  364. // 创建新的xml文件;
  365. const char* declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  366. doc.Parse(declaration); // 覆盖之前的xml;
  367. pXmlRoot = doc.NewElement("KeyList");
  368. if (pXmlRoot)
  369. {
  370. pXmlRoot->SetAttribute(_T("cols"), m_curKeyLayout.cols.c_str());
  371. pXmlRoot->SetAttribute(_T("with"), m_curKeyLayout.with.c_str());
  372. pXmlRoot->SetAttribute(_T("height"), m_curKeyLayout.height.c_str());
  373. pXmlRoot->SetAttribute(_T("rowSpacing"), m_curKeyLayout.rowSpacing.c_str());
  374. pXmlRoot->SetAttribute(_T("colSpacing"), m_curKeyLayout.colSpacing.c_str());
  375. pXmlRoot->SetAttribute(_T("leftMargin"), m_curKeyLayout.leftMargin.c_str());
  376. pXmlRoot->SetAttribute(_T("topMargin"), m_curKeyLayout.topMargin.c_str());
  377. pXmlRoot->SetAttribute(_T("ver"), m_curKeyLayout.ver.c_str());
  378. pXmlRoot->SetAttribute(_T("desc"), m_curKeyLayout.desc.c_str());
  379. doc.InsertEndChild(pXmlRoot);
  380. for (std::vector<KeyInfo>::iterator it = m_vtKeyInfo.begin(); it != m_vtKeyInfo.end(); it++)
  381. {
  382. tinyxml2::XMLElement* pXmlElent = doc.NewElement("ITEM");
  383. if (pXmlElent)
  384. {
  385. pXmlElent->SetAttribute(_T("color"), RGBColor2Hex(it->color).c_str());
  386. // 赋值各元素节点;
  387. tinyxml2::XMLElement* pUse = doc.NewElement("USE");
  388. pUse->SetText(1);
  389. pXmlElent->InsertEndChild(pUse);
  390. tinyxml2::XMLElement* pName = doc.NewElement("NAME");
  391. pName->SetText(it->strName.c_str());
  392. pXmlElent->InsertEndChild(pName);
  393. tinyxml2::XMLElement* pDesc = doc.NewElement("DESC");
  394. pDesc->SetText(it->strDesc.c_str());
  395. pXmlElent->InsertEndChild(pDesc);
  396. tinyxml2::XMLElement* pType = doc.NewElement("TYPE");
  397. pType->SetText(it->strType.c_str());
  398. pXmlElent->InsertEndChild(pType);
  399. tinyxml2::XMLElement* pValue = doc.NewElement("VALUE");
  400. pValue->SetText(it->strValue.c_str());
  401. pXmlElent->InsertEndChild(pValue);
  402. tinyxml2::XMLElement* pValue2 = doc.NewElement("VALUE2");
  403. pValue2->SetText(it->strValue2.c_str());
  404. pXmlElent->InsertEndChild(pValue2);
  405. tinyxml2::XMLElement* pValue3 = doc.NewElement("VALUE3");
  406. pValue3->SetText(it->strValue3.c_str());
  407. pXmlElent->InsertEndChild(pValue3);
  408. tinyxml2::XMLElement* pValue4 = doc.NewElement("VALUE4");
  409. pValue4->SetText(it->strValue4.c_str());
  410. pXmlElent->InsertEndChild(pValue4);
  411. pXmlRoot->InsertEndChild(pXmlElent);
  412. }
  413. }
  414. }
  415. doc.SaveFile(m_strXMLPath.c_str());
  416. }
  417. void CPropertiesWnd::ConvertOldSignalsToNew(std::string strOldSignal, std::string strNewSignal)
  418. {
  419. typedef struct
  420. {
  421. std::string name;
  422. std::string protocol;
  423. std::string key;
  424. //std::string color;
  425. }OldXML, * pOldXML;
  426. std::vector<OldXML> vtOldXML;
  427. tinyxml2::XMLDocument doc;
  428. if (tinyxml2::XML_SUCCESS != doc.LoadFile(strOldSignal.c_str()))
  429. {
  430. return;
  431. }
  432. tinyxml2::XMLElement* pXmlRoot = NULL;
  433. if ((pXmlRoot = doc.RootElement()) != NULL)
  434. {
  435. if (_tcsicmp(pXmlRoot->Value(), "KeyList") == 0)
  436. {
  437. // 子项;
  438. tinyxml2::XMLElement* pXmlElent = pXmlRoot->FirstChildElement();
  439. while (pXmlElent)
  440. {
  441. if (_tcsicmp(pXmlElent->Value(), _T("ITEM")) == 0)
  442. {
  443. OldXML oldxml;
  444. tinyxml2::XMLElement* pItem = pXmlElent->FirstChildElement();
  445. while (pItem)
  446. {
  447. if (_tcsicmp(pItem->Value(), _T("KeyName")) == 0)
  448. {
  449. oldxml.name = pItem->GetText();
  450. }
  451. else if (_tcsicmp(pItem->Value(), _T("KeyType")) == 0)
  452. {
  453. oldxml.protocol = pItem->GetText();
  454. }
  455. else if (_tcsicmp(pItem->Value(), _T("KeyCode")) == 0)
  456. {
  457. oldxml.key = pItem->GetText();
  458. }
  459. else if (_tcsicmp(pItem->Value(), _T("HexKey")) == 0)
  460. {
  461. oldxml.key = pItem->GetText();
  462. }
  463. pItem = pItem->NextSiblingElement();
  464. }
  465. vtOldXML.push_back(oldxml);
  466. }
  467. pXmlElent = pXmlElent->NextSiblingElement();
  468. }
  469. }
  470. }
  471. if (vtOldXML.size() == 0)
  472. return;
  473. // 创建新的xml文件;
  474. const char* declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  475. doc.Parse(declaration); // 覆盖之前的xml;
  476. pXmlRoot = doc.NewElement("KeyList");
  477. if (pXmlRoot)
  478. {
  479. pXmlRoot->SetAttribute(_T("cols"), _T("4"));
  480. pXmlRoot->SetAttribute(_T("with"), _T("60"));
  481. pXmlRoot->SetAttribute(_T("height"), _T("25"));
  482. pXmlRoot->SetAttribute(_T("rowSpacing"), _T("5"));
  483. pXmlRoot->SetAttribute(_T("colSpacing"), _T("3"));
  484. pXmlRoot->SetAttribute(_T("leftMargin"), _T("8"));
  485. pXmlRoot->SetAttribute(_T("topMargin"), _T("8"));
  486. pXmlRoot->SetAttribute(_T("ver"), _T("1.0.0.1"));
  487. pXmlRoot->SetAttribute(_T("desc"), _T("key info"));
  488. doc.InsertEndChild(pXmlRoot);
  489. for (std::vector<OldXML>::iterator it = vtOldXML.begin(); it != vtOldXML.end(); it++)
  490. {
  491. tinyxml2::XMLElement* pXmlElent = doc.NewElement("ITEM");
  492. if (pXmlElent)
  493. {
  494. pXmlElent->SetAttribute(_T("color"), _T("87CEFA"));
  495. // 赋值各元素节点;
  496. tinyxml2::XMLElement* pUse = doc.NewElement("USE");
  497. pUse->SetText(1);
  498. pXmlElent->InsertEndChild(pUse);
  499. tinyxml2::XMLElement* pName = doc.NewElement("NAME");
  500. pName->SetText(it->name.c_str());
  501. pXmlElent->InsertEndChild(pName);
  502. tinyxml2::XMLElement* pDesc = doc.NewElement("DESC");
  503. pDesc->SetText(_T(""));
  504. pXmlElent->InsertEndChild(pDesc);
  505. tinyxml2::XMLElement* pType = doc.NewElement("TYPE");
  506. pType->SetText(it->protocol.c_str());
  507. pXmlElent->InsertEndChild(pType);
  508. tinyxml2::XMLElement* pValue = doc.NewElement("VALUE");
  509. pValue->SetText(it->key.c_str());
  510. pXmlElent->InsertEndChild(pValue);
  511. pXmlRoot->InsertEndChild(pXmlElent);
  512. }
  513. }
  514. }
  515. doc.SaveFile(strNewSignal.c_str());
  516. }
  517. BTNInfo* CPropertiesWnd::GetUnUseBTN()
  518. {
  519. for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++)
  520. {
  521. if (!(*it)->bUsed)
  522. return *it;
  523. }
  524. return NULL;
  525. }
  526. void CPropertiesWnd::SetBTNStatus(BTNInfo* pbtnInfo, BOOL bStatus /* = TRUE */)
  527. {
  528. if (pbtnInfo)
  529. {
  530. pbtnInfo->bUsed = bStatus;
  531. }
  532. }
  533. void CPropertiesWnd::SetAllBTNUnUsed()
  534. {
  535. BTNInfo* pbtnInfo = NULL;
  536. for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++)
  537. {
  538. pbtnInfo = (*it);
  539. if (pbtnInfo)
  540. {
  541. pbtnInfo->bUsed = false;
  542. if (pbtnInfo->bCreated)
  543. {
  544. pbtnInfo->pBTN->ShowWindow(SW_HIDE);
  545. }
  546. }
  547. }
  548. }
  549. void CPropertiesWnd::ClearAllBTNInfo()
  550. {
  551. BTNInfo* pbtnInfo = NULL;
  552. for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++)
  553. {
  554. pbtnInfo = (*it);
  555. if (pbtnInfo)
  556. {
  557. pbtnInfo->pBTN->DestroyWindow();
  558. delete pbtnInfo->pBTN;
  559. pbtnInfo->pBTN = NULL;
  560. }
  561. delete pbtnInfo;
  562. pbtnInfo = NULL;
  563. }
  564. m_vtBTNInfo.clear();
  565. }
  566. void CPropertiesWnd::AutoSetDroppedWidth(CComboBox* pCombobox)
  567. {
  568. if (!pCombobox)
  569. return;
  570. // Find the longest string in the combo box.
  571. CString str;
  572. CSize sz;
  573. int dx = 0;
  574. TEXTMETRIC tm = { 0 };
  575. CDC* pDC = pCombobox->GetDC();
  576. CFont* pFont = pCombobox->GetFont();
  577. // Select the listbox font, save the old font
  578. CFont* pOldFont = pDC->SelectObject(pFont);
  579. // Get the text metrics for avg char width
  580. pDC->GetTextMetrics(&tm);
  581. for (int i = 0; i < pCombobox->GetCount(); i++)
  582. {
  583. pCombobox->GetLBText(i, str);
  584. sz = pDC->GetTextExtent(str);
  585. // Add the avg width to prevent clipping
  586. sz.cx += tm.tmAveCharWidth;
  587. if (sz.cx > dx)
  588. dx = sz.cx;
  589. }
  590. // Select the old font back into the DC
  591. pDC->SelectObject(pOldFont);
  592. pCombobox->ReleaseDC(pDC);
  593. // Set the horizontal extent so every character of all strings can
  594. // be scrolled to.
  595. pCombobox->SetHorizontalExtent(dx);
  596. }
  597. bool CPropertiesWnd::SendInfraedSignal(const KeyInfo* pKey)
  598. {
  599. CMainFrame* pMainWnd = (CMainFrame*)AfxGetApp()->m_pMainWnd;
  600. if (!pMainWnd)
  601. return false;
  602. if (!pMainWnd->m_SerialTW.IsOpen())
  603. {
  604. MessageBox(_T("The serial port is not open."), _T("Warnning"), MB_OK | MB_ICONWARNING);
  605. return false;
  606. }
  607. DWORD dwSendLen = 0;
  608. byte szSendData[MAX_SENDDATA] = { 0 };
  609. // 根据不同的版本号来发送;
  610. if (Global::g_nVersion == 1)
  611. {
  612. _stprintf_s((TCHAR*)szSendData, MAX_SENDDATA, _T("*INPUT %s %s\r"), pKey->strType.c_str(), pKey->strValue.c_str());
  613. dwSendLen = _tcslen((TCHAR*)szSendData);
  614. }
  615. else if (Global::g_nVersion == 2)
  616. {
  617. // 将十六进制的字符串转成字节流;
  618. std::string strBytes = utils::HexStringToBytes(pKey->strValue2, 2);
  619. memcpy_s(szSendData, MAX_SENDDATA, strBytes.c_str(), strBytes.size());
  620. dwSendLen = strBytes.size();
  621. }
  622. // 发送单信号;
  623. if (pMainWnd->m_SerialTW.WriteSync(szSendData, dwSendLen))
  624. {
  625. memset(szSendData, 0, MAX_SENDDATA);
  626. pMainWnd->m_SerialTW.ReadSync(szSendData, MAX_SENDDATA);
  627. TRACE("发送单信号成功\n");
  628. return true;
  629. }
  630. else
  631. {
  632. TRACE("发送单信号失败\n");
  633. }
  634. return false;
  635. }
  636. void CPropertiesWnd::LearnInfraedSignal(UINT uId, KeyInfo* pKey)
  637. {
  638. m_pKeyInfo = pKey;
  639. CMainFrame* pMainWnd = (CMainFrame*)AfxGetApp()->m_pMainWnd;
  640. if (!pMainWnd)
  641. return;
  642. if (!pMainWnd->m_SerialTW.IsOpen())
  643. {
  644. MessageBox(_T("The serial port is not open."), _T("Warnning"), MB_OK | MB_ICONWARNING);
  645. return;
  646. }
  647. DWORD dwSendLen = 0;
  648. byte szSendData[MAX_SENDDATA] = { 0 };
  649. // 根据不同的版本号来发送;
  650. if (Global::g_nVersion == 1)
  651. {
  652. }
  653. else if (Global::g_nVersion == 2)
  654. {
  655. // 将十六进制的字符串转成字节流;
  656. std::string strBytes = utils::HexStringToBytes(_T("FD FD F1 F2 DF"), 3);
  657. memcpy_s(szSendData, MAX_SENDDATA, strBytes.c_str(), strBytes.size());
  658. dwSendLen = strBytes.size();
  659. // 发送学习红外信号;
  660. if (pMainWnd->m_SerialTW.WriteSync(szSendData, dwSendLen))
  661. {
  662. // 自动化的红外不返回,如果没有收到任务红外,会等待10多秒后自动结束学习状态;
  663. TRACE("发送单信号成功\n");
  664. }
  665. else
  666. {
  667. TRACE("发送单信号失败\n");
  668. }
  669. }
  670. if (m_dwThreadId)
  671. {
  672. PostThreadMessage(m_dwThreadId, TMSG_START_LEARN, uId, 0);
  673. }
  674. }
  675. DWORD WINAPI CPropertiesWnd::ThreadLearn(LPVOID lpParam)
  676. {
  677. CPropertiesWnd* pthis = (CPropertiesWnd*)lpParam;
  678. CMainFrame* pMainWnd = (CMainFrame*)AfxGetApp()->m_pMainWnd;
  679. if (!pthis || !pMainWnd)
  680. return 0;
  681. DWORD dwSendLen = 0;
  682. byte szSendData[MAX_SENDDATA] = { 0 };
  683. while (Global::g_bLearn)
  684. {
  685. MSG msg;
  686. if (GetMessage(&msg, NULL, 0, 0))
  687. {
  688. // 当接收到退出消息,退出线程;
  689. if (msg.message == TMSG_QUITE_THREAD)
  690. {
  691. // 退出并保存学习数据;
  692. pthis->SaveKeyInfo();
  693. break;
  694. }
  695. else if (msg.message == TMSG_START_LEARN)
  696. {
  697. DWORD dwTickCount = ::GetTickCount64();
  698. while (GetTickCount64() - dwTickCount < 60000)
  699. {
  700. // 等待学习的红外信号发出;
  701. DWORD dwRealRead = 0;
  702. memset((char*)szSendData, 0, MAX_SENDDATA);
  703. if (dwRealRead = pMainWnd->m_SerialTW.ReadSync(szSendData, MAX_SENDDATA))
  704. {
  705. if (m_pKeyInfo)
  706. {
  707. if (Global::g_nVersion == 1)
  708. m_pKeyInfo->strValue = (TCHAR*)szSendData;
  709. else if (Global::g_nVersion == 2)
  710. {
  711. std::string val = utils::BytesToHexString(szSendData, dwRealRead, ' ');
  712. // 超时没有学习,该设备会自动返回数据,其中开头16字节如下.
  713. //if (_tcsncmp("fd fd 30 03 88 99 aa 34 ff ff ff ff ff ff ff ff", val.c_str(), 16))
  714. if (_tcsncmp("FD FD 30 03 88 99 AA 34 FF FF FF FF FF FF FF FF", val.c_str(), 16))
  715. {
  716. m_pKeyInfo->strValue2 = val;
  717. }
  718. else
  719. {
  720. break;
  721. }
  722. }
  723. // 学习成功的,将按钮颜色改成白色以区分未学习的.
  724. m_pKeyInfo->pbtnInfo->pBTN->SetFaceColor(RGB(255, 255, 255), TRUE);
  725. }
  726. break;
  727. }
  728. Sleep(200);
  729. }
  730. }
  731. }
  732. }
  733. OutputDebugString(_T("线程结束"));
  734. pthis->m_dwThreadId = 0;
  735. return 0;
  736. }
  737. // 如果CDockablePane无控件,改变大小时背景会刷新失败;
  738. // 所以要重载onpaint;
  739. void CPropertiesWnd::OnPaint()
  740. {
  741. CPaintDC dc(this); // device context for painting
  742. // TODO: 在此处添加消息处理程序代码
  743. // 不为绘图消息调用 CDockablePane::OnPaint()
  744. CRect rc;
  745. GetClientRect(rc);
  746. CBrush brush;
  747. // 获取office风格主题颜色;
  748. #if _MSC_VER <=1500
  749. // CMFCVisualManagerOffice2007继承于CMFCVisualManager,使用CMFCVisualManager的GetInstance获取父对象指针后转换为CMFCVisualManagerOffice2007对象指针;
  750. brush.CreateSolidBrush(((CMFCVisualManagerOffice2007*)CMFCVisualManagerOffice2007::GetInstance())->GetRibbonEditBackgroundColor(FALSE, FALSE));
  751. #else // VS2010之后,方法有变化;
  752. CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->GetMainWnd();
  753. brush.CreateSolidBrush(((CMFCVisualManagerOffice2007*)CMFCVisualManagerOffice2007::GetInstance())->GetRibbonEditBackgroundColor((CMFCRibbonRichEditCtrl*)pMainFrame->GetRibbonStatusBar(), FALSE, FALSE, FALSE));
  754. #endif
  755. dc.FillRect(&rc, &brush);
  756. }
  757. void CPropertiesWnd::OnDestroy()
  758. {
  759. CDockablePane::OnDestroy();
  760. // TODO: 在此处添加消息处理程序代码
  761. ClearAllBTNInfo();
  762. }
  763. BOOL CPropertiesWnd::PreTranslateMessage(MSG* pMsg)
  764. {
  765. // TODO: 在此添加专用代码和/或调用基类
  766. if (pMsg->message == WM_KEYDOWN)
  767. {
  768. if (pMsg->wParam == VK_F5)
  769. {
  770. Global::g_bLearn = !Global::g_bLearn;
  771. if (m_dwThreadId == 0 && Global::g_bLearn)
  772. CreateThread(NULL, 0, ThreadLearn, this, 0, &m_dwThreadId);
  773. // 关闭线程;
  774. if (!Global::g_bLearn)
  775. PostThreadMessage(m_dwThreadId, TMSG_QUITE_THREAD, 0, 0);
  776. MessageBox(Global::g_bLearn ? _T("开启学习红外") : _T("关闭红外学习"), _T("提示"), MB_OK);
  777. return TRUE;
  778. }
  779. else if ( pMsg->wParam == VK_F2 )
  780. {
  781. // 查找目录文件;
  782. filehelper fh;
  783. std::vector<std::string> vtSignals;
  784. fh.getfiles_findout_subfolder(Global::g_Config.twOldSignaldir.c_str(), _T("*.xml"), &vtSignals);
  785. // 逐个文件转换;
  786. for ( std::vector<std::string>::iterator it = vtSignals.begin(); it != vtSignals.end(); it++ )
  787. {
  788. std::string newfile = Global::g_Config.twSignaldir + _T("\\") + filehelper::getfilename(it->c_str()) + _T(".xml");
  789. ConvertOldSignalsToNew(*it, newfile);
  790. }
  791. MessageBox(_T("Convert old signals ok!"), _T("Convert"), MB_OK);
  792. LoadSignals();
  793. return TRUE;
  794. }
  795. }
  796. return CDockablePane::PreTranslateMessage(pMsg);
  797. }