Pārlūkot izejas kodu

【软件版本】V
【模块名称】侧边栏功能.
【问题原因】
【修改描述】
【测试结果】

sat23 3 gadi atpakaļ
vecāks
revīzija
f2996b7b04

+ 53 - 1
FieldTestTool/FieldTestTool/FieldTestTool.vcproj

@@ -22,7 +22,7 @@
 			IntermediateDirectory="$(OutDir)$(ConfigurationName)"
 			ConfigurationType="1"
 			UseOfMFC="2"
-			CharacterSet="1"
+			CharacterSet="2"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -397,6 +397,58 @@
 				>
 			</File>
 		</Filter>
+		<Filter
+			Name="filehelper"
+			>
+			<File
+				RelativePath="..\..\SATHelper\filehelper\filehelper.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\SATHelper\filehelper\filehelper.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\SATHelper\filehelper\findfile.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\SATHelper\filehelper\findfile.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="tinyxml2"
+			>
+			<File
+				RelativePath="..\tinyxml2\stdint.h"
+				>
+			</File>
+			<File
+				RelativePath="..\tinyxml2\tinyxml2.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\tinyxml2\tinyxml2.h"
+				>
+			</File>
+		</Filter>
 		<File
 			RelativePath=".\ReadMe.txt"
 			>

+ 64 - 5
FieldTestTool/FieldTestTool/MainFrm.cpp

@@ -39,14 +39,27 @@ BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
     ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar)
 	ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar)
 #endif
+    // 摄像头;
     ON_COMMAND(ID_RIBBON_CAMERA_COMBOBOX, &CMainFrame::OnCameraCombobox)
     ON_UPDATE_COMMAND_UI(ID_RIBBON_CAMERA_COMBOBOX, &CMainFrame::OnUpdateCameraCombobox)
-
+    // 红外:测试精灵;
     ON_COMMAND(ID_RIBBON_INFRAED_COMBOBOX, &CMainFrame::OnInfraedCombobox)
     ON_UPDATE_COMMAND_UI(ID_RIBBON_INFRAED_COMBOBOX, &CMainFrame::OnUpdateInfraedCombobox)
-
+    ON_COMMAND(ID_RIBBON_INFRAED_CHECKBOX, &CMainFrame::OnInfraedCheckbox)
+    ON_UPDATE_COMMAND_UI(ID_RIBBON_INFRAED_CHECKBOX, &CMainFrame::OnUpdateInfraedCheckbox)
+    // USB切换器;
     ON_COMMAND(ID_RIBBON_SWITCHER_COMBOBOX, &CMainFrame::OnCameraCombobox)
     ON_UPDATE_COMMAND_UI(ID_RIBBON_SWITCHER_COMBOBOX, &CMainFrame::OnUpdateCameraCombobox)
+    // 打开USB切换器;
+    ON_COMMAND(ID_RIBBON_SWITCHER_CHECKBOX, &CMainFrame::OnSwitcherCheckbox)
+    ON_UPDATE_COMMAND_UI(ID_RIBBON_SWITCHER_CHECKBOX, &CMainFrame::OnUpdateSwitcherCheckbox)
+    // Switch A;
+    ON_COMMAND(ID_RIBBON_SWITCHER_CHECKBOXA, &CMainFrame::OnSwitcherCheckboxA)
+    ON_UPDATE_COMMAND_UI(ID_RIBBON_SWITCHER_CHECKBOXA, &CMainFrame::OnUpdateSwitcherCheckboxA)
+    // Switch B;
+    ON_COMMAND(ID_RIBBON_SWITCHER_CHECKBOXB, &CMainFrame::OnSwitcherCheckboxB)
+    ON_UPDATE_COMMAND_UI(ID_RIBBON_SWITCHER_CHECKBOXB, &CMainFrame::OnUpdateSwitcherCheckboxB)
+    // 计时器;
     ON_WM_TIMER()
 END_MESSAGE_MAP()
 
@@ -600,11 +613,23 @@ void CMainFrame::OnUpdateInfraedCombobox(CCmdUI* pCmdUI)
     //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
 }
 
+void CMainFrame::OnInfraedCheckbox()
+{
+    CMFCRibbonBar* pRibbon = GetRibbonBar();
+    ASSERT_VALID(pRibbon);
+    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_INFRAED_CHECKBOX));
+}
+
+void CMainFrame::OnUpdateInfraedCheckbox(CCmdUI* pCmdUI)
+{
+    //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
+}
+
 void CMainFrame::OnSwitcherCombobox()
 {
     CMFCRibbonBar* pRibbon = GetRibbonBar();
     ASSERT_VALID(pRibbon);
-    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_CAMERA_COMBOBOX));
+    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_SWITCHER_COMBOBOX));
 }
 
 void CMainFrame::OnUpdateSwitcherCombobox(CCmdUI* pCmdUI)
@@ -612,6 +637,42 @@ void CMainFrame::OnUpdateSwitcherCombobox(CCmdUI* pCmdUI)
     //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
 }
 
+void CMainFrame::OnSwitcherCheckbox()
+{
+    CMFCRibbonBar* pRibbon = GetRibbonBar();
+    ASSERT_VALID(pRibbon);
+    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_SWITCHER_CHECKBOX));
+}
+
+void CMainFrame::OnUpdateSwitcherCheckbox(CCmdUI* pCmdUI)
+{
+    //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
+}
+
+void CMainFrame::OnSwitcherCheckboxA()
+{
+    CMFCRibbonBar* pRibbon = GetRibbonBar();
+    ASSERT_VALID(pRibbon);
+    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_SWITCHER_CHECKBOXA));
+}
+
+void CMainFrame::OnUpdateSwitcherCheckboxA(CCmdUI* pCmdUI)
+{
+    //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
+}
+
+void CMainFrame::OnSwitcherCheckboxB()
+{
+    CMFCRibbonBar* pRibbon = GetRibbonBar();
+    ASSERT_VALID(pRibbon);
+    CMFCRibbonComboBox* pCameraCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox, pRibbon->FindByID(ID_RIBBON_SWITCHER_CHECKBOXB));
+}
+
+void CMainFrame::OnUpdateSwitcherCheckboxB(CCmdUI* pCmdUI)
+{
+    //pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
+}
+
 BOOL CMainFrame::OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
 {
     CMFCRibbonBar* pRibbon = GetRibbonBar();
@@ -659,7 +720,6 @@ BOOL CMainFrame::OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
                     {
                         IsTestWizardPort(pbdp->dbcp_name);
                     }
-
                 }
             }
         }
@@ -697,7 +757,6 @@ BOOL CMainFrame::OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
                     {
                         IsUSBSwitchPort(pbdp->dbcp_name);
                     }
-
                 }
             }
         }

+ 11 - 2
FieldTestTool/FieldTestTool/MainFrm.h

@@ -72,14 +72,23 @@ protected:
 	afx_msg void OnViewCaptionBar();
 	afx_msg void OnUpdateViewCaptionBar(CCmdUI* pCmdUI);
 #endif
+    // 摄像头;
     afx_msg void OnCameraCombobox();
     afx_msg void OnUpdateCameraCombobox(CCmdUI* pCmdUI);
-
+    // 红外:测试精灵;
     afx_msg void OnInfraedCombobox();
     afx_msg void OnUpdateInfraedCombobox(CCmdUI* pCmdUI);
-
+    afx_msg void OnInfraedCheckbox();
+    afx_msg void OnUpdateInfraedCheckbox(CCmdUI* pCmdUI);
+    // USB切换器;
     afx_msg void OnSwitcherCombobox();
     afx_msg void OnUpdateSwitcherCombobox(CCmdUI* pCmdUI);
+    afx_msg void OnSwitcherCheckbox();
+    afx_msg void OnUpdateSwitcherCheckbox(CCmdUI* pCmdUI);
+    afx_msg void OnSwitcherCheckboxA();
+    afx_msg void OnUpdateSwitcherCheckboxA(CCmdUI* pCmdUI);
+    afx_msg void OnSwitcherCheckboxB();
+    afx_msg void OnUpdateSwitcherCheckboxB(CCmdUI* pCmdUI);
 
     afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData);
 	DECLARE_MESSAGE_MAP()

+ 543 - 41
FieldTestTool/FieldTestTool/PropertiesWnd.cpp

@@ -15,6 +15,11 @@
 #include "Resource.h"
 #include "MainFrm.h"
 #include "FieldTestTool.h"
+#include "filehelper.h"
+
+#define MINIMUM_WINDOWS_X 395  
+#define MINIMUM_WINDOWS_Y 535
+#define MAX_SWITCH_LEN 16
 
 #ifdef _DEBUG
 #undef THIS_FILE
@@ -22,6 +27,32 @@ static char THIS_FILE[]=__FILE__;
 #define new DEBUG_NEW
 #endif
 
+unsigned char TwoHexChar2Char(char ch1, char ch2)
+{
+    char Numb1;
+    char Numb2;
+
+    if (ch1 >= 'A')
+        Numb1 = (toupper(ch1) - '0' - 7) * 16;
+    else
+        Numb1 = (ch1 - '0') * 16;
+
+    if (ch2 >= 'A')
+        Numb2 = (toupper(ch2) - '0' - 7);
+    else
+        Numb2 = (ch2 - '0');
+
+    return (Numb1 + Numb2);
+}
+
+COLORREF HexColor2RGB(std::string strHexColor)
+{
+    DWORD r = TwoHexChar2Char(strHexColor[0], strHexColor[1]);
+    DWORD g = TwoHexChar2Char(strHexColor[2], strHexColor[3]);
+    DWORD b = TwoHexChar2Char(strHexColor[4], strHexColor[5]);
+
+    return RGB(r, g, b);
+}
 /////////////////////////////////////////////////////////////////////////////
 // CResourceViewBar
 
@@ -34,11 +65,16 @@ CPropertiesWnd::~CPropertiesWnd()
 }
 
 BEGIN_MESSAGE_MAP(CPropertiesWnd, CDockablePane)
-	ON_WM_CREATE()
-	ON_WM_SIZE()
-	ON_WM_SETFOCUS()
-	ON_WM_SETTINGCHANGE()
+    ON_WM_CREATE()
+    ON_WM_SIZE()
+    ON_WM_SETFOCUS()
+    ON_WM_SETTINGCHANGE()
     ON_WM_PAINT()
+    // 信号按钮;
+    ON_COMMAND_RANGE(BTNID, BTNID + 100, OnSignalBtnClick)
+    ON_UPDATE_COMMAND_UI_RANGE(BTNID, BTNID + 100, OnUpdateSignalBtnClick)
+    // 下拉框事件;
+    ON_CBN_SELCHANGE(1, &CPropertiesWnd::OnCbnSelchangeSingals)
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
@@ -46,82 +82,548 @@ END_MESSAGE_MAP()
 
 void CPropertiesWnd::AdjustLayout()
 {
-	if (GetSafeHwnd() == NULL)
-	{
-		return;
-	}
-
-	CRect rectClient,rectCombo;
-	GetClientRect(rectClient);
-
-	
+    if (GetSafeHwnd() == NULL)
+    {
+        return;
+    }
+
+    CRect rectClient;
+    GetClientRect(rectClient);
+
+    m_wndSignalCombo.GetWindowRect(&m_rcCombobox);
+    ScreenToClient(m_rcCombobox);
+
+    int cyCmb = m_rcCombobox.Size().cy;
+    m_wndSignalCombo.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), 200, SWP_NOACTIVATE | SWP_NOZORDER);
+
+    TRACE2(_T("更新后的大小:%d,%d\n"), rectClient.Width(), rectClient.Height());
+
+    int sx = 0, sy = m_rcCombobox.bottom + m_nTopMargin;
+    int i = 0, id = 10000;
+    int nWidth = (rectClient.Width() - 25) / m_nCols;
+    DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+    for (std::vector<KeyInfo>::iterator it = m_vtKeyInfo.begin(); it != m_vtKeyInfo.end(); it++)
+    {
+        if (it->pbtnInfo->pBTN == NULL)
+            continue;
+        if (i != 0 && i % m_nCols == 0)
+        {//换行;
+            sy += it->height + m_nRowSpacing;
+        }
+
+        //sx = m_nLeftMargin + (i % m_nCols) * nWidth + (i % m_nCols + 1) * m_nColSpacing;
+        sx = m_nLeftMargin + (i % m_nCols) * (nWidth + m_nColSpacing);
+        it->pbtnInfo->pBTN->SetWindowPos(NULL, sx, sy, nWidth, it->height, SWP_NOACTIVATE | SWP_NOZORDER);
+        i++;
+    }
 }
 
 int CPropertiesWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
 {
-	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
-		return -1;
+    if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+        return -1;
 
-	CRect rectDummy;
-	rectDummy.SetRectEmpty();
+    CRect rectDummy;
+    rectDummy.SetRectEmpty();
 
-	// 创建组合:
-	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+    // 创建组合:
+    const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
 
+    if (!m_wndSignalCombo.Create(dwViewStyle|WS_VSCROLL | WS_HSCROLL, rectDummy, this, 1))
+    {
+        TRACE0("未能创建属性组合 \n");
+        return -1;      // 未能创建
+    }
 
 
-	InitPropList();
+    InitPropList();
 
     // 设置最小窗体;
     SetMinSize((530, 260));
 
-	AdjustLayout();
-	return 0;
+    LoadSignals();
+    m_wndSignalCombo.SelectString(0, Global::g_Config.twUseSignal.c_str());
+    LoadKeyInfo(m_vtKeyInfo, Global::g_Config.twSignaldir + _T("\\") + Global::g_Config.twUseSignal + _T(".xml"));
+
+    AdjustLayout();
+    return 0;
 }
 
 void CPropertiesWnd::OnSize(UINT nType, int cx, int cy)
 {
-	CDockablePane::OnSize(nType, cx, cy);
-	AdjustLayout();
+    CDockablePane::OnSize(nType, cx, cy);
+    AdjustLayout();
 }
 
 void CPropertiesWnd::InitPropList()
 {
-	SetPropListFont();
-
-
+    SetPropListFont();
 }
 
 void CPropertiesWnd::OnSetFocus(CWnd* pOldWnd)
 {
-	CDockablePane::OnSetFocus(pOldWnd);
-	
+    CDockablePane::OnSetFocus(pOldWnd);
 }
 
 void CPropertiesWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
 {
-	CDockablePane::OnSettingChange(uFlags, lpszSection);
-	SetPropListFont();
+    CDockablePane::OnSettingChange(uFlags, lpszSection);
+    SetPropListFont();
+}
+
+void CPropertiesWnd::OnSignalBtnClick(UINT uId) // 发送遥控信号;
+{
+    CWnd* pWnd = GetFocus();
+    int id = pWnd->GetDlgCtrlID();
+    if (id >= BTNID && id <= BTNID + 100)
+    {
+        CString text;
+        pWnd->GetWindowText(text);
+        KeyInfo *pKey = m_map_key.find(id)->second;
+
+#if 0
+        if ( m_SerialTW.IsOpen() ){
+            m_SerialTW.SetTimeouts();
+            // 封装发送包;
+            byte szSendData[MAX_PATH] = {0};
+            _stprintf_s((TCHAR*)szSendData, MAX_PATH, _T("*INPUT %s %s\r"), pKey->strType.c_str(), pKey->strValue.c_str());
+
+            // 发送单信号;
+            if ( m_SerialTW.WriteSync(szSendData, _tcslen((TCHAR*)szSendData)) )
+            {
+                memset(szSendData, 0, MAX_PATH);
+                m_SerialTW.ReadSync(szSendData, MAX_PATH);
+                TRACE("发送单信号成功\n");
+            }
+            else
+            {
+                TRACE("发送单信号失败\n");
+            }
+        }
+        else
+        {
+            MessageBox(_T("The serial port is not open."), _T("Warnning"), MB_OK|MB_ICONWARNING);
+        }
+#endif
+    }
+}
+
+void CPropertiesWnd::OnUpdateSignalBtnClick(CCmdUI* pCmdUI)
+{
+    pCmdUI->Enable(m_map_key.find(pCmdUI->m_nID)->second->bUse);
+}
+
+void CPropertiesWnd::OnCbnSelchangeSingals()
+{
+    // TODO: 在此添加控件通知处理程序代码
+    CString strSignal;
+    int nCurSel = m_wndSignalCombo.GetCurSel();
+    if (nCurSel != CB_ERR)
+    {
+        std::string signalpath;
+        m_wndSignalCombo.GetLBText(nCurSel, strSignal);
+
+        // 保存到配置文件中;
+        Global::g_Config.twUseSignal = strSignal.GetString();
+        WritePrivateProfileString("TestWizard", "useSignal", strSignal.GetString(), Global::g_szConfig);
+
+        SetAllBTNUnUsed();
+        LoadKeyInfo(m_vtKeyInfo, Global::g_Config.twSignaldir + _T("\\") +  Global::g_Config.twUseSignal + _T(".xml"));
+    }
 }
 
 void CPropertiesWnd::SetPropListFont()
 {
-	::DeleteObject(m_fntPropList.Detach());
+    ::DeleteObject(m_fntPropList.Detach());
+
+    LOGFONT lf;
+    afxGlobalData.fontRegular.GetLogFont(&lf);
+
+    NONCLIENTMETRICS info;
+    info.cbSize = sizeof(info);
+
+    afxGlobalData.GetNonClientMetrics(info);
+
+    lf.lfHeight = info.lfMenuFont.lfHeight;
+    lf.lfWeight = info.lfMenuFont.lfWeight;
+    lf.lfItalic = info.lfMenuFont.lfItalic;
+
+    m_fntPropList.CreateFontIndirect(&lf);
+}
+
+void CPropertiesWnd::LoadSignals()
+{
+    filehelper fh;
+    m_vtTWSignal.clear();
+    fh.getfiles_findout_subfolder(Global::g_Config.twSignaldir.c_str(), _T("*.xml"), &m_vtTWSignal);
+
+    m_wndSignalCombo.ResetContent();
+    for (std::vector<TString>::iterator it = m_vtTWSignal.begin(); it != m_vtTWSignal.end(); it++ )
+    {
+        m_wndSignalCombo.AddString(fh.getfilename(it->c_str()).c_str());
+    }
+
+    //AutoSetDroppedWidth(&m_cbSignals);
+}
+
+void CPropertiesWnd::LoadKeyInfo(std::vector<KeyInfo> &vtKeyInfo, TString path)
+{
+    // 解析xml;
+    tinyxml2::XMLDocument doc;
+    if (tinyxml2::XML_SUCCESS != doc.LoadFile(path.c_str()))
+    {
+        return;
+    }
+
+    vtKeyInfo.clear();
+    std::string data;
+    tinyxml2::XMLElement* pXmlRoot = NULL;
+    if ((pXmlRoot = doc.RootElement()) != NULL)
+    {
+        if (_tcsicmp(pXmlRoot->Value(), "KeyList") == 0)
+        {
+            //////////////////////////////////////////////////////////////////////////
+            // 获取属性;
+            m_nCols = _tstoi(pXmlRoot->Attribute("cols") ? pXmlRoot->Attribute("cols") : "3");
+            m_nRowSpacing = _tstoi(pXmlRoot->Attribute("rowSpacing") ? pXmlRoot->Attribute("rowSpacing") : "5");
+            m_nColSpacing = _tstoi(pXmlRoot->Attribute("colSpacing") ? pXmlRoot->Attribute("colSpacing") : "5");
+            m_nTopMargin = _tstoi(pXmlRoot->Attribute("topMargin") ? pXmlRoot->Attribute("topMargin") : "8");
+            m_nLeftMargin = _tstoi(pXmlRoot->Attribute("leftMargin") ? pXmlRoot->Attribute("leftMargin") : "8");
+            int nWidth = _tstoi(pXmlRoot->Attribute("with") ? pXmlRoot->Attribute("with") : "58");
+            int nHeight = _tstoi(pXmlRoot->Attribute("height") ? pXmlRoot->Attribute("height") : "25");
+            //////////////////////////////////////////////////////////////////////////
+
+            // 子项;
+            tinyxml2::XMLElement* pXmlElent = pXmlRoot->FirstChildElement();
+            while (pXmlElent)
+            {
+                if (_tcsicmp(pXmlElent->Value(), _T("ITEM")) == 0)
+                {
+                    KeyInfo keyInfo;
+                    // 获取属性值;
+                    keyInfo.width = pXmlElent->Attribute("with") ? _ttol(pXmlElent->Attribute("with")) : nWidth;
+                    keyInfo.height = pXmlElent->Attribute("height") ? _ttol(pXmlElent->Attribute("height")) : nHeight;
+                    keyInfo.color = HexColor2RGB(pXmlElent->Attribute("color") ? pXmlElent->Attribute("color") : "87CEFA");
+
+                    tinyxml2::XMLElement* pItem = pXmlElent->FirstChildElement();
+                    while (pItem)
+                    {
+                        if (_tcsicmp(pItem->Value(), _T("NAME")) == 0)
+                        {
+                            keyInfo.strName = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("USE")) == 0)
+                        {
+                            keyInfo.bUse = pItem->BoolText(true);
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("DESC")) == 0)
+                        {
+                            keyInfo.strDesc = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("TYPE")) == 0)
+                        {
+                            keyInfo.strType = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("VALUE")) == 0)
+                        {
+                            keyInfo.strValue = pItem->GetText();
+                        }
+
+                        pItem = pItem->NextSiblingElement();
+                    }
+
+                    keyInfo.pbtnInfo = GetUnUseBTN();
+                    if ( keyInfo.pbtnInfo == NULL)
+                    {
+                        BTNInfo *pbtnInfo = new BTNInfo();
+                        pbtnInfo->pBTN = new CMFCButton();
+                        m_vtBTNInfo.push_back(pbtnInfo);
+
+                        keyInfo.pbtnInfo = pbtnInfo;
+                    }
+                    SetBTNStatus(keyInfo.pbtnInfo, TRUE);
+
+                    vtKeyInfo.push_back(keyInfo);
+                }
+
+                pXmlElent = pXmlElent->NextSiblingElement();
+            }
+        }
+    }
+
+    int sx = 0, sy = m_rcCombobox.bottom + m_nTopMargin;
+    int i = 0, id = 10000;
+    DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+    int maxX = 0, maxY = 0;
+    for (std::vector<KeyInfo>::iterator it = vtKeyInfo.begin(); it != vtKeyInfo.end(); it++)
+    {
+        if (i != 0 && i % m_nCols == 0)
+        {//换行;
+            sy += it->height + m_nRowSpacing;
+        }
+
+        sx = (i % m_nCols) * it->width + (i % m_nCols + 1) * m_nColSpacing;
+        //m_nDefaultWidth = m_nLeftMargin + m_nCols * it->width + m_nCols * m_nColSpacing;
+
+        if ( !it->pbtnInfo->bCreated )
+        {
+            it->pbtnInfo->pBTN->Create(it->strName.c_str(), dwStyle, CRect(sx, sy, sx + it->width, sy + it->height), this, BTNID + i);
+            it->pbtnInfo->bCreated = true;
+
+            // 设置透明false以显示背景色
+            it->pbtnInfo->pBTN->m_bTransparent = FALSE;
+            it->pbtnInfo->pBTN->m_bDontUseWinXPTheme = TRUE;
+            // 消除单击时黑色内圈;
+            it->pbtnInfo->pBTN->m_bDrawFocus = FALSE;
+            // 设置按钮扁平样式;
+            it->pbtnInfo->pBTN->m_nFlatStyle = CMFCButton::FlatStyle::BUTTONSTYLE_FLAT;
+            // 设置鼠标形状;
+            it->pbtnInfo->pBTN->SetMouseCursorHand();
+        }
+        else
+        {
+            it->pbtnInfo->pBTN->SetWindowText(it->strName.c_str());
+        }
+
+        // 设置背景色;
+        it->pbtnInfo->pBTN->SetFaceColor(it->color, TRUE);
+        // 显示窗口;
+        it->pbtnInfo->pBTN->ShowWindow(SW_SHOW);
+        // 是否禁用;
+        it->pbtnInfo->pBTN->EnableWindow(it->bUse);
+
+        // 存入map中;
+        m_map_key.insert(std::pair<UINT, KeyInfo*>(BTNID + i, &*it));
+
+        i++;
+    }
+
+    std::vector<KeyInfo>::iterator it = vtKeyInfo.begin();
+    m_nDefaultHeight = m_rcCombobox.bottom + 15 + (vtKeyInfo.size()/m_nCols + (vtKeyInfo.size()%m_nCols > 0 ? 1 : 0)) * (it->height + m_nRowSpacing);
+    m_nDefaultHeight = m_nDefaultHeight < MINIMUM_WINDOWS_Y ? MINIMUM_WINDOWS_Y : m_nDefaultHeight;
+
+    m_nDefaultWidth = m_nLeftMargin*2 + m_nCols * it->width + m_nCols * m_nColSpacing;
+    m_nDefaultWidth = m_nDefaultWidth < MINIMUM_WINDOWS_X ? MINIMUM_WINDOWS_X : m_nDefaultWidth;
+
+    // 获取标题栏高度;
+    int nCaptionHeight = 39; //GetSystemMetrics(SM_CYCAPTION);不准 GetWindowRect - GetClientRect
+    // 设置窗口大小;
+    SetWindowPos(NULL, 0, 0, m_nDefaultWidth, m_nDefaultHeight + nCaptionHeight, SWP_NOMOVE|SWP_FRAMECHANGED);   //SWP_NOACTIVATE | SWP_NOZORDER
+
+    AdjustLayout();
+}
+
+void CPropertiesWnd::ConvertOldSignalsToNew(std::string strOldSignal, std::string strNewSignal)
+{
+    typedef struct
+    {
+        std::string name;
+        std::string protocol;
+        std::string key;
+        //std::string color;
+    }OldXML, *pOldXML;
+
+    std::vector<OldXML> vtOldXML;
+    tinyxml2::XMLDocument doc;
+    if (tinyxml2::XML_SUCCESS != doc.LoadFile(strOldSignal.c_str()))
+    {
+        return;
+    }
+
+    tinyxml2::XMLElement* pXmlRoot = NULL;
+    if ((pXmlRoot = doc.RootElement()) != NULL)
+    {
+        if (_tcsicmp(pXmlRoot->Value(), "KeyList") == 0)
+        {
+            // 子项;
+            tinyxml2::XMLElement* pXmlElent = pXmlRoot->FirstChildElement();
+            while (pXmlElent)
+            {
+                if (_tcsicmp(pXmlElent->Value(), _T("ITEM")) == 0)
+                {
+                    OldXML oldxml;
+                    tinyxml2::XMLElement* pItem = pXmlElent->FirstChildElement();
+                    while (pItem)
+                    {
+                        if (_tcsicmp(pItem->Value(), _T("KeyName")) == 0)
+                        {
+                            oldxml.name = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("KeyType")) == 0)
+                        {
+                            oldxml.protocol = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("KeyCode")) == 0)
+                        {
+                            oldxml.key = pItem->GetText();
+                        }
+                        else if (_tcsicmp(pItem->Value(), _T("KeyCode")) == 0)
+                        {
+                            oldxml.key = pItem->GetText();
+                        }
+
+                        pItem = pItem->NextSiblingElement();
+                    }
+
+                    vtOldXML.push_back(oldxml);
+                }
+
+                pXmlElent = pXmlElent->NextSiblingElement();
+            }
+        }
+    }
+
+    if ( vtOldXML.size() == 0 )
+        return;
+
+    // 创建新的xml文件;
+    const char* declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    doc.Parse(declaration); // 覆盖之前的xml;
+
+    pXmlRoot = doc.NewElement("KeyList");
+    if ( pXmlRoot )
+    {
+        pXmlRoot->SetAttribute(_T("cols"), _T("4"));
+        pXmlRoot->SetAttribute(_T("with"), _T("60"));
+        pXmlRoot->SetAttribute(_T("height"), _T("25"));
+        pXmlRoot->SetAttribute(_T("rowSpacing"), _T("5"));
+        pXmlRoot->SetAttribute(_T("colSpacing"), _T("3"));
+        pXmlRoot->SetAttribute(_T("leftMargin"), _T("8"));
+        pXmlRoot->SetAttribute(_T("topMargin"), _T("8"));
+        pXmlRoot->SetAttribute(_T("ver"), _T("1.0.0.1"));
+        pXmlRoot->SetAttribute(_T("desc"), _T("key info"));
+        doc.InsertEndChild(pXmlRoot);
+
+        for (std::vector<OldXML>::iterator it = vtOldXML.begin(); it != vtOldXML.end(); it++ )
+        {
+            tinyxml2::XMLElement* pXmlElent = doc.NewElement("ITEM");
+            if ( pXmlElent )
+            {
+                pXmlElent->SetAttribute(_T("color"), _T("87CEFA"));
+                // 赋值各元素节点;
+                tinyxml2::XMLElement *pUse = doc.NewElement("USE");
+                pUse->SetText(1);
+                pXmlElent->InsertEndChild(pUse);
+
+                tinyxml2::XMLElement *pName = doc.NewElement("NAME");
+                pName->SetText(it->name.c_str());
+                pXmlElent->InsertEndChild(pName);
+
+                tinyxml2::XMLElement *pDesc = doc.NewElement("DESC");
+                pDesc->SetText(_T(""));
+                pXmlElent->InsertEndChild(pDesc);
+
+                tinyxml2::XMLElement *pType = doc.NewElement("TYPE");
+                pType->SetText(it->protocol.c_str());
+                pXmlElent->InsertEndChild(pType);
+
+                tinyxml2::XMLElement *pValue = doc.NewElement("VALUE");
+                pValue->SetText(it->key.c_str());
+                pXmlElent->InsertEndChild(pValue);
+
+                pXmlRoot->InsertEndChild(pXmlElent);
+            }
+        }
+    }
+
+    doc.SaveFile(strNewSignal.c_str());
+}
 
-	LOGFONT lf;
-	afxGlobalData.fontRegular.GetLogFont(&lf);
 
-	NONCLIENTMETRICS info;
-	info.cbSize = sizeof(info);
+BTNInfo *CPropertiesWnd::GetUnUseBTN()
+{
+    for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++ )
+    {
+        if ( !(*it)->bUsed )
+            return *it;
+    }
 
-	afxGlobalData.GetNonClientMetrics(info);
+    return NULL;
+}
 
-	lf.lfHeight = info.lfMenuFont.lfHeight;
-	lf.lfWeight = info.lfMenuFont.lfWeight;
-	lf.lfItalic = info.lfMenuFont.lfItalic;
+void CPropertiesWnd::SetBTNStatus(BTNInfo *pbtnInfo, BOOL bStatus /* = TRUE */)
+{
+    if ( pbtnInfo )
+    {
+        pbtnInfo->bUsed = bStatus;
+    }
+}
 
-	m_fntPropList.CreateFontIndirect(&lf);
+void CPropertiesWnd::SetAllBTNUnUsed()
+{
+    BTNInfo *pbtnInfo = NULL;
+    for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++ )
+    {
+        pbtnInfo = (*it);
+        if ( pbtnInfo )
+        {
+            pbtnInfo->bUsed = false;
+            if ( pbtnInfo->bCreated )
+            {
+                pbtnInfo->pBTN->ShowWindow(SW_HIDE);
+            }
+        }
+    }
+}
+
+void CPropertiesWnd::ClearAllBTNInfo()
+{
+    BTNInfo *pbtnInfo = NULL;
+    for (std::vector<BTNInfo*>::iterator it = m_vtBTNInfo.begin(); it != m_vtBTNInfo.end(); it++ )
+    {
+        pbtnInfo = (*it);
+        if ( pbtnInfo )
+        {
+            pbtnInfo->pBTN->DestroyWindow();
+            delete pbtnInfo->pBTN;
+            pbtnInfo->pBTN = NULL;
+        }
+
+        delete pbtnInfo;
+        pbtnInfo = NULL;
+    }
+
+    m_vtBTNInfo.clear();
+}
 
+void CPropertiesWnd::AutoSetDroppedWidth(CComboBox* pCombobox)
+{
+    if (!pCombobox)
+        return;
+    // Find the longest string in the combo box.
+    CString str;
+    CSize sz;
+    int dx = 0;
+
+    TEXTMETRIC tm = { 0 };
+    CDC* pDC = pCombobox->GetDC();
+    CFont* pFont = pCombobox->GetFont();
+
+    // Select the listbox font, save the old font
+    CFont* pOldFont = pDC->SelectObject(pFont);
+
+    // Get the text metrics for avg char width
+    pDC->GetTextMetrics(&tm);
+
+    for (int i = 0; i < pCombobox->GetCount(); i++)
+    {
+        pCombobox->GetLBText(i, str);
+        sz = pDC->GetTextExtent(str);
+
+        // Add the avg width to prevent clipping
+        sz.cx += tm.tmAveCharWidth;
+
+        if (sz.cx > dx)
+            dx = sz.cx;
+    }
+
+    // Select the old font back into the DC
+    pDC->SelectObject(pOldFont);
+    pCombobox->ReleaseDC(pDC);
+
+    // Set the horizontal extent so every character of all strings can
+    // be scrolled to.
+    pCombobox->SetHorizontalExtent(dx);
 }
 
 // 如果CDockablePane无控件,改变大小时背景会刷新失败;

+ 91 - 25
FieldTestTool/FieldTestTool/PropertiesWnd.h

@@ -11,32 +11,70 @@
 
 #pragma once
 
+// 按钮id起始值;
+#define BTNID 11000
+#define WM_IR_SHOT_IMG WM_USER + 10012
+
+#define NAME_LEN 32
+#define DESC_LEN 128
+#define VALUE_LEN 16
+
+typedef struct __BTN_INFO__
+{
+    CMFCButton *pBTN;
+    bool bUsed;
+    bool bCreated;
+    __BTN_INFO__(){
+        pBTN = NULL;
+        bUsed = false;
+        bCreated = false;
+    }
+}BTNInfo, *pBTNInfo;
+
+// layout.xml item;
+typedef struct __KEY_INFO__
+{
+    bool bUse;
+    std::string strName;
+    std::string strDesc;
+    std::string strValue;
+    std::string strType;
+    int width;
+    int height;
+    DWORD color;
+    BTNInfo *pbtnInfo;
+    __KEY_INFO__(){
+        pbtnInfo = NULL;
+        bUse = false;
+    }
+}KeyInfo, *pKeyInfo;
+
 class CPropertiesToolBar : public CMFCToolBar
 {
 public:
-	virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
-	{
-		CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
-	}
+    virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
+    {
+        CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
+    }
 
-	virtual BOOL AllowShowOnList() const { return FALSE; }
+    virtual BOOL AllowShowOnList() const { return FALSE; }
 };
 
 class CPropertiesWnd : public CDockablePane
 {
-// 构造
+    // 构造
 public:
-	CPropertiesWnd();
+    CPropertiesWnd();
 
-	void AdjustLayout();
+    void AdjustLayout();
 
-// 属性
+    // 属性
 public:
-	void SetVSDotNetLook(BOOL bSet)
-	{
-		//m_wndPropList.SetVSDotNetLook(bSet);
-		//m_wndPropList.SetGroupNameFullWidth(bSet);
-	}
+    void SetVSDotNetLook(BOOL bSet)
+    {
+        //m_wndPropList.SetVSDotNetLook(bSet);
+        //m_wndPropList.SetGroupNameFullWidth(bSet);
+    }
 
     // 去掉关闭按钮;但组合多个pane时无效;
     virtual BOOL CanBeClosed() const { return FALSE; };
@@ -46,23 +84,51 @@ public:
     virtual BOOL CanFloat() const { return FALSE; };
 
 protected:
-	CFont m_fntPropList;
+    CFont m_fntPropList;
+    CComboBox m_wndSignalCombo;
+
+    int m_nCols;
+    int m_nRowSpacing;
+    int m_nColSpacing;
+    int m_nDefaultWidth;
+    int m_nDefaultHeight;
+    int m_nTopMargin;
+    int m_nLeftMargin;
+
+    CRect m_rcCombobox;
+    std::vector<KeyInfo> m_vtKeyInfo;
+    std::map<UINT, KeyInfo*> m_map_key;
+    std::vector<TString> m_vtTWSignal;
+    std::vector<BTNInfo*> m_vtBTNInfo;
 
-// 实现
+    // 实现
 public:
-	virtual ~CPropertiesWnd();
+    virtual ~CPropertiesWnd();
 
 protected:
-	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
-	afx_msg void OnSize(UINT nType, int cx, int cy);
-	
-	afx_msg void OnSetFocus(CWnd* pOldWnd);
-	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+    afx_msg void OnSize(UINT nType, int cx, int cy);
 
-	DECLARE_MESSAGE_MAP()
+    afx_msg void OnSetFocus(CWnd* pOldWnd);
+    afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+    // 按钮事件;
+    afx_msg void OnSignalBtnClick(UINT uId);
+    afx_msg void OnUpdateSignalBtnClick(CCmdUI* pCmdUI);
+    // 下拉框选项变化事件;
+    afx_msg void OnCbnSelchangeSingals();
+    DECLARE_MESSAGE_MAP()
 
-	void InitPropList();
-	void SetPropListFont();
+    void InitPropList();
+    void SetPropListFont();
+    void LoadSignals();
+    void LoadKeyInfo(std::vector<KeyInfo> &vtKeyInfo, TString path);
+    void ConvertOldSignalsToNew(TString strOldSignal, TString strNewSignal);
+    BTNInfo *GetUnUseBTN();
+    void SetBTNStatus(BTNInfo *pbtnInfo, BOOL bStatus = TRUE);
+    void SetAllBTNUnUsed();
+    void ClearAllBTNInfo();
+    // 自动根据Combobox选项长度设置宽度;
+    void AutoSetDroppedWidth(CComboBox* pCombobox);
 public:
     afx_msg void OnPaint();
 };

+ 2 - 0
FieldTestTool/FieldTestTool/stdafx.h

@@ -51,6 +51,8 @@
 #include "Global.h"
 #include "Serial.h"
 #include "utils.h"
+#include <map>
+#include "tinyxml2.h"
 
 // ½ûÓñêÌâÀ¸;
 #define DISABLE_CAPTIONBAR