| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CCarrierSlotGrid.h" |
| | | #include <gdiplus.h> |
| | | #pragma comment(lib, "gdiplus.lib") |
| | | |
| | | using namespace Gdiplus; |
| | | |
| | | #define SAFE_PORT(p) ((p) >= 0 && (p) < (int)m_ports.size()) |
| | | #define SAFE_SLOT(s) ((s) >= 0 && (s) < m_nSlots) |
| | | |
| | | static bool s_gdiplusInited = false; |
| | | static ULONG_PTR s_gdiplusToken = 0; |
| | | static void EnsureGdiplus() |
| | | { |
| | | if (!s_gdiplusInited) |
| | | { |
| | | GdiplusStartupInput in; |
| | | if (GdiplusStartup(&s_gdiplusToken, &in, nullptr) == Ok) |
| | | s_gdiplusInited = true; |
| | | } |
| | | } |
| | | |
| | | BEGIN_MESSAGE_MAP(CCarrierSlotGrid, CWnd) |
| | | ON_WM_ERASEBKGND() |
| | | ON_WM_PAINT() |
| | | ON_WM_CREATE() |
| | | ON_WM_SIZE() |
| | | ON_WM_HSCROLL() |
| | | ON_WM_VSCROLL() // â
æ°å¢ |
| | | ON_WM_LBUTTONDOWN() |
| | | ON_WM_LBUTTONUP() |
| | | ON_WM_MOUSEWHEEL() |
| | | ON_WM_MOUSEMOVE() |
| | | ON_WM_SETCURSOR() |
| | | ON_WM_SHOWWINDOW() |
| | | ON_WM_WINDOWPOSCHANGED() |
| | | END_MESSAGE_MAP() |
| | | |
| | | CCarrierSlotGrid::CCarrierSlotGrid() {} |
| | | CCarrierSlotGrid::~CCarrierSlotGrid() |
| | | { |
| | | if ((HFONT)m_fntText) m_fntText.DeleteObject(); |
| | | if ((HFONT)m_fntBold) m_fntBold.DeleteObject(); |
| | | if ((HFONT)m_fntSmall) m_fntSmall.DeleteObject(); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::PreSubclassWindow() |
| | | { |
| | | CWnd::PreSubclassWindow(); |
| | | if (GetParent() && GetParent()->GetFont()) SetFont(GetParent()->GetFont()); |
| | | EnsureFonts(); |
| | | EnsureGdiplus(); |
| | | // ç¡®ä¿æ ·å¼å
嫿»å¨æ¡ |
| | | ModifyStyle(0, WS_HSCROLL | WS_VSCROLL, 0); |
| | | SetWindowPos(nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); |
| | | } |
| | | |
| | | int CCarrierSlotGrid::OnCreate(LPCREATESTRUCT cs) |
| | | { |
| | | if (CWnd::OnCreate(cs) == -1) return -1; |
| | | if (GetParent() && GetParent()->GetFont()) SetFont(GetParent()->GetFont()); |
| | | EnsureFonts(); |
| | | EnsureGdiplus(); |
| | | ModifyStyle(0, WS_HSCROLL | WS_VSCROLL, 0); |
| | | return 0; |
| | | } |
| | | |
| | | void CCarrierSlotGrid::EnsureFonts() |
| | | { |
| | | if ((HFONT)m_fntText) return; |
| | | |
| | | LOGFONT lf{}; bool ok = false; |
| | | if (GetParent() && GetParent()->GetFont()) { GetParent()->GetFont()->GetLogFont(&lf); ok = true; } |
| | | else if (GetFont()) { GetFont()->GetLogFont(&lf); ok = true; } |
| | | else { |
| | | NONCLIENTMETRICS ncm = { 0 }; ncm.cbSize = sizeof(NONCLIENTMETRICS); |
| | | if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) { lf = ncm.lfMessageFont; ok = true; } |
| | | } |
| | | if (!ok) { CFont* pDef = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT)); pDef->GetLogFont(&lf); } |
| | | |
| | | m_fntText.CreateFontIndirect(&lf); |
| | | LOGFONT lfb = lf; lfb.lfWeight = FW_SEMIBOLD; m_fntBold.CreateFontIndirect(&lfb); |
| | | LOGFONT lfs = lf; lfs.lfHeight = (LONG)(lf.lfHeight * 0.9); if (lfs.lfHeight == 0) lfs.lfHeight = lf.lfHeight - 1; m_fntSmall.CreateFontIndirect(&lfs); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::InitGrid(int nPorts, int nSlots) |
| | | { |
| | | ASSERT(nPorts >= 1 && nSlots >= 1); |
| | | m_ports.assign(nPorts, PortColumn{}); |
| | | m_portColCXs.assign(nPorts, 180); |
| | | m_nSlots = nSlots; |
| | | for (auto& pc : m_ports) pc.slots.assign(m_nSlots, SlotCell{}); |
| | | UpdateScrollRange(); |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetColumnWidths(int slotColWidth, int portColWidth) |
| | | { |
| | | if (slotColWidth > 0) m_slotColCX = slotColWidth; |
| | | if (portColWidth > 0) |
| | | for (size_t i = 0; i < m_portColCXs.size(); ++i) m_portColCXs[i] = portColWidth; |
| | | UpdateScrollRange(); |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetRowHeight(int cy) { m_rowHeight = max(18, min(cy, 64)); UpdateScrollRange(); Invalidate(FALSE); } |
| | | void CCarrierSlotGrid::SetHeaderHeight(int cy) { m_headerCY = max(20, min(cy, 48)); UpdateScrollRange(); Invalidate(FALSE); } |
| | | void CCarrierSlotGrid::SetShowMaterialToggle(BOOL bShow) { m_bShowMatToggle = bShow; Invalidate(FALSE); } |
| | | |
| | | void CCarrierSlotGrid::SetPortInfo(int portIndex, LPCTSTR portName, LPCTSTR carrierName) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | if (portName) m_ports[portIndex].portName = portName; |
| | | if (carrierName) m_ports[portIndex].carrierName = carrierName; |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetPortAllocated(int portIndex, BOOL allocated, LPCTSTR byName) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | auto& pc = m_ports[portIndex]; |
| | | pc.allocated = !!allocated; |
| | | pc.allocatedBy = byName ? byName : _T(""); |
| | | if (pc.allocated) |
| | | for (auto& cell : pc.slots) cell.checked = false; |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | BOOL CCarrierSlotGrid::IsPortAllocated(int portIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return FALSE; return m_ports[portIndex].allocated; |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetSlotGlass(int portIndex, int slotIndex, BOOL hasGlass, LPCTSTR coreId, int material) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | cell.hasGlass = !!hasGlass; |
| | | cell.coreId = coreId ? coreId : _T(""); |
| | | cell.material = (material == MAT_G2) ? MAT_G2 : MAT_G1; |
| | | if (!cell.hasGlass) cell.checked = false; |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetSlotChecked(int portIndex, int slotIndex, BOOL checked) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | auto& pc = m_ports[portIndex]; |
| | | if (pc.allocated) return; |
| | | auto& cell = pc.slots[slotIndex]; |
| | | if (!cell.hasGlass) return; |
| | | cell.checked = !!checked; |
| | | NotifySelectionChanged(portIndex, slotIndex, cell.checked); |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | BOOL CCarrierSlotGrid::GetSlotChecked(int portIndex, int slotIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return FALSE; |
| | | return m_ports[portIndex].slots[slotIndex].checked ? TRUE : FALSE; |
| | | } |
| | | |
| | | int CCarrierSlotGrid::GetSlotMaterialType(int portIndex, int slotIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return MAT_G1; |
| | | return m_ports[portIndex].slots[slotIndex].material; |
| | | } |
| | | |
| | | void CCarrierSlotGrid::SetSlotMaterialType(int portIndex, int slotIndex, int material, BOOL bNotify) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | auto& pc = m_ports[portIndex]; |
| | | if (pc.allocated) return; |
| | | auto& cell = pc.slots[slotIndex]; |
| | | if (!cell.hasGlass) return; |
| | | int mt = (material == MAT_G2) ? MAT_G2 : MAT_G1; |
| | | if (cell.material != mt) { |
| | | cell.material = mt; |
| | | if (bNotify) NotifyMaterialChanged(portIndex, slotIndex, cell.material); |
| | | Invalidate(FALSE); |
| | | } |
| | | } |
| | | |
| | | CString CCarrierSlotGrid::GetDisplayId(int portIndex, int slotIndex) const |
| | | { |
| | | CString s(_T("â")); |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return s; |
| | | const auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | if (!cell.hasGlass) return s; |
| | | s.Format(_T("G%d-%s"), (cell.material == MAT_G2) ? 2 : 1, cell.coreId.GetString()); |
| | | return s; |
| | | } |
| | | |
| | | void CCarrierSlotGrid::CheckAllInPort(int portIndex, BOOL checked, BOOL bNotify) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | auto& pc = m_ports[portIndex]; |
| | | if (pc.allocated) return; |
| | | for (int r = 0; r < m_nSlots; ++r) { |
| | | auto& cell = pc.slots[r]; |
| | | if (!cell.hasGlass) continue; |
| | | if (cell.checked != !!checked) { |
| | | cell.checked = !!checked; |
| | | if (bNotify) NotifySelectionChanged(portIndex, r, cell.checked); |
| | | } |
| | | } |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::RebuildTexts() { Invalidate(FALSE); } |
| | | |
| | | CSize CCarrierSlotGrid::CalcBestClientSize(int nSlotsOverride) const |
| | | { |
| | | const int slots = (nSlotsOverride > 0) ? nSlotsOverride : m_nSlots; |
| | | int w = m_slotColCX; |
| | | for (int cx : m_portColCXs) w += cx; |
| | | int h = m_headerCY + slots * m_rowHeight; |
| | | return CSize(w, h); |
| | | } |
| | | |
| | | CSize CCarrierSlotGrid::CalcBestWindowSize(BOOL includeNonClient, int nSlotsOverride) const |
| | | { |
| | | CSize cli = CalcBestClientSize(nSlotsOverride); |
| | | if (!includeNonClient) return cli; |
| | | |
| | | RECT rc = { 0, 0, cli.cx, cli.cy }; |
| | | |
| | | // ç®æ æ¯âå好ä¸åºç°æ»å¨æ¡âççªå£å¤æ¡å¤§å°ï¼ |
| | | // ç¨å½åæ ·å¼å»æ WS_HSCROLL/WS_VSCROLL åå AdjustWindowRectEx |
| | | DWORD style = GetStyle(); |
| | | DWORD exStyle = GetExStyle(); |
| | | style &= ~(WS_HSCROLL | WS_VSCROLL); |
| | | |
| | | ::AdjustWindowRectEx(&rc, style, FALSE, exStyle); |
| | | return CSize(rc.right - rc.left, rc.bottom - rc.top); |
| | | } |
| | | |
| | | // ---------- å ä½ ---------- |
| | | CRect CCarrierSlotGrid::GetClientRectNoSB() const |
| | | { |
| | | CRect rc; GetClientRect(&rc); return rc; |
| | | } |
| | | CRect CCarrierSlotGrid::GetHeaderRect() const |
| | | { |
| | | CRect rc = GetClientRectNoSB(); rc.bottom = rc.top + m_headerCY; return rc; |
| | | } |
| | | int CCarrierSlotGrid::GetTotalContentWidth() const |
| | | { |
| | | int w = m_slotColCX; |
| | | for (int cx : m_portColCXs) w += cx; |
| | | return w; |
| | | } |
| | | CRect CCarrierSlotGrid::GetHeaderItemRect(int iItem) const |
| | | { |
| | | CRect rcHeader = GetHeaderRect(); |
| | | int x = rcHeader.left - m_scrollX; |
| | | if (iItem == 0) |
| | | return CRect(x, rcHeader.top, x + m_slotColCX, rcHeader.bottom); |
| | | |
| | | x += m_slotColCX; |
| | | for (int c = 1; c < iItem; ++c) x += m_portColCXs[c - 1]; |
| | | int w = m_portColCXs[iItem - 1]; |
| | | return CRect(x, rcHeader.top, x + w, rcHeader.bottom); |
| | | } |
| | | BOOL CCarrierSlotGrid::GetCellRect(int row, int sub, CRect& rc) const |
| | | { |
| | | CRect cli = GetClientRectNoSB(); |
| | | int y0 = cli.top + m_headerCY - m_scrollY; |
| | | int top = y0 + row * m_rowHeight; |
| | | int bottom = top + m_rowHeight; |
| | | if (bottom <= cli.top + m_headerCY || top >= cli.bottom) return FALSE; |
| | | |
| | | int x = cli.left - m_scrollX; |
| | | if (sub == 0) { rc = CRect(x, top, x + m_slotColCX, bottom); return TRUE; } |
| | | x += m_slotColCX; |
| | | for (int c = 1; c < sub; ++c) x += m_portColCXs[c - 1]; |
| | | int w = m_portColCXs[sub - 1]; |
| | | rc = CRect(x, top, x + w, bottom); |
| | | return TRUE; |
| | | } |
| | | CRect CCarrierSlotGrid::GetHeaderCheckboxRect(int iItem) const |
| | | { |
| | | CRect rItem = GetHeaderItemRect(iItem); |
| | | const int box = 16; |
| | | const int padR = 6; |
| | | int vpad = max(0, (rItem.Height() - box) / 2); |
| | | return CRect(rItem.right - padR - box, rItem.top + vpad, rItem.right - padR, rItem.bottom - vpad); |
| | | } |
| | | CRect CCarrierSlotGrid::GetCheckboxRect(const CRect& cell) const |
| | | { |
| | | int sz = max(14, min(int(m_rowHeight * 0.70), 20)); |
| | | int leftPad = 8; |
| | | int top = cell.top + (cell.Height() - sz) / 2; |
| | | return CRect(cell.left + leftPad, top, cell.left + leftPad + sz, top + sz); |
| | | } |
| | | CRect CCarrierSlotGrid::GetMaterialTagRect(const CRect& cell) const |
| | | { |
| | | int h = max(14, min(int(m_rowHeight * 0.65), m_rowHeight - 8)); |
| | | int w = 32; |
| | | int gap = 6; |
| | | int rightPadForDot = 16; |
| | | int top = cell.top + (cell.Height() - h) / 2; |
| | | int right = cell.right - rightPadForDot - gap; |
| | | return CRect(right - w, top, right, top + h); |
| | | } |
| | | CRect CCarrierSlotGrid::GetStatusDotRect(const CRect& cell) const |
| | | { |
| | | int d = max(8, min(int(m_rowHeight * 0.42), 12)); |
| | | int rightPad = 6; |
| | | int top = cell.top + (cell.Height() - d) / 2; |
| | | return CRect(cell.right - rightPad - d, top, cell.right - rightPad, top + d); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::UpdateScrollRange() |
| | | { |
| | | CRect rc; GetClientRect(&rc); |
| | | |
| | | // åç´ |
| | | const int contentH = m_headerCY + m_nSlots * m_rowHeight; |
| | | const int pageY = max(1, rc.Height()); |
| | | const int maxPosY = max(0, contentH - pageY); |
| | | m_scrollY = max(0, min(m_scrollY, maxPosY)); |
| | | SCROLLINFO siY = { sizeof(SCROLLINFO) }; |
| | | siY.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; |
| | | siY.nMin = 0; siY.nMax = contentH - 1; siY.nPage = pageY; siY.nPos = m_scrollY; |
| | | SetScrollInfo(SB_VERT, &siY, TRUE); |
| | | |
| | | // ˮƽ |
| | | const int contentW = GetTotalContentWidth(); |
| | | const int pageX = max(1, rc.Width()); |
| | | const int maxPosX = max(0, contentW - pageX); |
| | | m_scrollX = max(0, min(m_scrollX, maxPosX)); |
| | | SCROLLINFO siX = { sizeof(SCROLLINFO) }; |
| | | siX.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; |
| | | siX.nMin = 0; siX.nMax = contentW - 1; siX.nPage = pageX; siX.nPos = m_scrollX; |
| | | SetScrollInfo(SB_HORZ, &siX, TRUE); |
| | | } |
| | | |
| | | // ---------- 表头åé线å½ä¸ ---------- |
| | | int CCarrierSlotGrid::HitHeaderEdge(CPoint pt) const |
| | | { |
| | | if (!m_bAllowResize) return -1; // â æ°å¢ |
| | | if (!GetHeaderRect().PtInRect(pt)) return -1; |
| | | const int tol = 4; |
| | | int x = GetHeaderRect().left - m_scrollX + m_slotColCX; |
| | | if (abs(pt.x - x) <= tol) return 0; |
| | | |
| | | int cum = GetHeaderRect().left - m_scrollX + m_slotColCX; |
| | | for (int i = 0; i <= GetPortCount() - 2; ++i) { |
| | | cum += m_portColCXs[i]; |
| | | if (abs(pt.x - cum) <= tol) return i + 1; |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | // ---------- ç»å¶ ---------- |
| | | BOOL CCarrierSlotGrid::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } |
| | | |
| | | void CCarrierSlotGrid::DrawFlatCheckbox(CDC* pDC, const CRect& r, bool checked, bool disabled) |
| | | { |
| | | CBrush br(disabled ? RGB(245, 245, 245) : RGB(255, 255, 255)); |
| | | CPen pen(PS_SOLID, 1, disabled ? RGB(200, 200, 200) : RGB(130, 130, 135)); |
| | | CBrush* pOldB = pDC->SelectObject(&br); |
| | | CPen* pOldP = pDC->SelectObject(&pen); |
| | | pDC->RoundRect(r, CPoint(3, 3)); |
| | | pDC->SelectObject(pOldB); pDC->SelectObject(pOldP); |
| | | |
| | | if (!checked) return; |
| | | COLORREF c = disabled ? RGB(160, 160, 160) : RGB(40, 150, 90); |
| | | CPen penTick(PS_SOLID, max(2, r.Height() / 8), c); |
| | | CPen* pOld = pDC->SelectObject(&penTick); |
| | | POINT p1 = { r.left + r.Width() * 2 / 9, r.top + r.Height() * 5 / 9 }; |
| | | POINT p2 = { r.left + r.Width() * 4 / 9, r.top + r.Height() * 7 / 9 }; |
| | | POINT p3 = { r.left + r.Width() * 7 / 9, r.top + r.Height() * 3 / 9 }; |
| | | pDC->MoveTo(p1); pDC->LineTo(p2); pDC->LineTo(p3); |
| | | pDC->SelectObject(pOld); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::PaintTo(CDC* pDC) |
| | | { |
| | | EnsureGdiplus(); |
| | | |
| | | CRect cli = GetClientRectNoSB(); |
| | | pDC->FillSolidRect(cli, m_colBg); |
| | | |
| | | // Header |
| | | CRect rh = GetHeaderRect(); |
| | | pDC->FillSolidRect(rh, ::GetSysColor(COLOR_BTNFACE)); |
| | | CPen penSep(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); |
| | | CPen* pOldPen = pDC->SelectObject(&penSep); |
| | | pDC->MoveTo(rh.left, rh.bottom - 1); pDC->LineTo(rh.right, rh.bottom - 1); |
| | | pDC->SelectObject(pOldPen); |
| | | |
| | | for (int i = 0; i <= GetPortCount(); ++i) |
| | | { |
| | | CRect rItem = GetHeaderItemRect(i); |
| | | |
| | | // ä¿®æ¹ä¸ºï¼ |
| | | if (i < GetPortCount()) { // â
æåä¸åä¸ç»åé线 |
| | | CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); |
| | | pOldPen = pDC->SelectObject(&pen); |
| | | pDC->MoveTo(rItem.right - 1, rItem.top); |
| | | pDC->LineTo(rItem.right - 1, rItem.bottom); |
| | | pDC->SelectObject(pOldPen); |
| | | } |
| | | |
| | | CString text; |
| | | if (i == 0) { |
| | | text = _T("Slot"); |
| | | CRect rt = rItem; rt.DeflateRect(6, 0, 6, 0); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SelectObject(&m_fntBold); |
| | | pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); |
| | | pDC->DrawText(text, rt, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | } |
| | | else { |
| | | const auto& pc = m_ports[i - 1]; |
| | | int selected = 0; bool any = false, all = true; |
| | | for (const auto& cell : pc.slots) { |
| | | if (cell.hasGlass) { any = true; if (cell.checked) ++selected; else all = false; } |
| | | } |
| | | if (!any) all = false; |
| | | |
| | | CString leftTitle = pc.carrierName.IsEmpty() |
| | | ? pc.portName |
| | | : (pc.portName + _T(" (") + pc.carrierName + _T(")")); |
| | | |
| | | // å¾éæ¡é å³ |
| | | CRect rcCb = GetHeaderCheckboxRect(i); |
| | | DrawFlatCheckbox(pDC, rcCb, all, pc.allocated); |
| | | |
| | | // 计æ°è´´è¿å¾éæ¡å·¦ä¾§ |
| | | CString cnt; cnt.Format(_T("%d/%d"), selected, m_nSlots); |
| | | SIZE szCnt{ 0,0 }; |
| | | { CFont* o = pDC->SelectObject(&m_fntBold); |
| | | GetTextExtentPoint32(pDC->GetSafeHdc(), cnt, cnt.GetLength(), &szCnt); |
| | | pDC->SelectObject(o); } |
| | | const int gap = 6; |
| | | CRect rcCnt(rcCb.left - gap - szCnt.cx, rItem.top, rcCb.left - gap, rItem.bottom); |
| | | |
| | | // 左侧æ é¢ |
| | | CRect rt = rItem; rt.DeflateRect(6, 0, (rItem.right - rcCnt.left) + 6, 0); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SelectObject(&m_fntBold); |
| | | pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); |
| | | pDC->DrawText(leftTitle, rt, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | |
| | | // è®¡æ° |
| | | pDC->SelectObject(&m_fntBold); |
| | | pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); |
| | | pDC->DrawText(cnt, rcCnt, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); |
| | | } |
| | | } |
| | | |
| | | // Cells |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | for (int s = 0; s <= GetPortCount(); ++s) |
| | | { |
| | | CRect rc; |
| | | if (!GetCellRect(r, s, rc)) continue; |
| | | |
| | | COLORREF bk = m_colBg; |
| | | if (s >= 1) { |
| | | int port = s - 1; |
| | | if (port % 2 == 0) bk = m_colAlt; |
| | | if (SAFE_PORT(port) && m_ports[port].allocated) bk = m_colLock; |
| | | } |
| | | pDC->FillSolidRect(rc, bk); |
| | | |
| | | CPen penMajor(PS_SOLID, (s >= 1 && ((s - 1) % 2 == 0)) ? 2 : 1, m_gridMajor); |
| | | CPen* pOld = pDC->SelectObject(&penMajor); |
| | | pDC->MoveTo(rc.left, rc.top); pDC->LineTo(rc.right, rc.top); |
| | | pDC->MoveTo(rc.left, rc.top); pDC->LineTo(rc.left, rc.bottom); |
| | | pDC->SelectObject(pOld); |
| | | |
| | | CPen penMinor(PS_SOLID, 1, m_gridMinor); |
| | | pOld = pDC->SelectObject(&penMinor); |
| | | if (s == GetPortCount()) { pDC->MoveTo(rc.right - 1, rc.top); pDC->LineTo(rc.right - 1, rc.bottom); } |
| | | if (r == m_nSlots - 1) { pDC->MoveTo(rc.left, rc.bottom - 1); pDC->LineTo(rc.right, rc.bottom - 1); } |
| | | pDC->SelectObject(pOld); |
| | | |
| | | if (s == 0) { |
| | | CString sl; sl.Format(_T("Slot %d"), r + 1); |
| | | CRect rt = rc; rt.DeflateRect(8, 0, 8, 0); |
| | | pDC->SelectObject(&m_fntBold); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(RGB(60, 60, 64)); |
| | | pDC->DrawText(sl, rt, DT_LEFT | DT_VCENTER | DT_SINGLELINE); |
| | | } |
| | | else { |
| | | int port = s - 1; |
| | | const auto& pc = m_ports[port]; |
| | | const auto& cell = pc.slots[r]; |
| | | |
| | | CRect rChk = GetCheckboxRect(rc); |
| | | DrawFlatCheckbox(pDC, rChk, cell.checked, pc.allocated || !cell.hasGlass); |
| | | |
| | | CString t = GetDisplayId(port, r); |
| | | CRect rText = rc; |
| | | int leftPad = rChk.right + 6; |
| | | CRect rDot = GetStatusDotRect(rc); |
| | | CRect rTag = GetMaterialTagRect(rc); |
| | | int rightPad = rc.right - min(rTag.left - 6, rDot.left - 6); |
| | | rText.DeflateRect(leftPad - rc.left, 0, rightPad, 0); |
| | | |
| | | pDC->SelectObject(&m_fntText); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(cell.hasGlass ? m_text : m_textDim); |
| | | pDC->DrawText(t, rText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | |
| | | if (m_bShowMatToggle) |
| | | { |
| | | CRect rT = GetMaterialTagRect(rc); |
| | | COLORREF crBorder = (cell.material == MAT_G2) ? RGB(180, 150, 220) : RGB(120, 160, 220); |
| | | COLORREF crFill = (cell.material == MAT_G2) ? RGB(243, 235, 250) : RGB(233, 240, 252); |
| | | COLORREF crText = (cell.material == MAT_G2) ? RGB(90, 60, 150) : RGB(50, 90, 160); |
| | | if (pc.allocated || !cell.hasGlass) { crBorder = RGB(210, 210, 210); crFill = RGB(245, 245, 245); crText = RGB(160, 160, 160); } |
| | | CBrush br(crFill); CPen tagPen(PS_SOLID, 1, crBorder); |
| | | CPen* pOldP = pDC->SelectObject(&tagPen); |
| | | CBrush* pOldB = pDC->SelectObject(&br); |
| | | pDC->RoundRect(rT, CPoint(6, 6)); |
| | | pDC->SelectObject(pOldB); pDC->SelectObject(pOldP); |
| | | CString tx; tx.Format(_T("G%d"), (cell.material == MAT_G2) ? 2 : 1); |
| | | pDC->SelectObject(&m_fntSmall); |
| | | pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(crText); |
| | | pDC->DrawText(tx, rT, DT_CENTER | DT_VCENTER | DT_SINGLELINE); |
| | | } |
| | | |
| | | // ç¶æç¹ï¼GDI+ æé¯é½¿ï¼ |
| | | { |
| | | Graphics g(pDC->GetSafeHdc()); |
| | | g.SetSmoothingMode(SmoothingModeAntiAlias); |
| | | COLORREF c = cell.hasGlass ? (pc.allocated ? RGB(215, 160, 60) : RGB(60, 170, 80)) : RGB(160, 160, 160); |
| | | SolidBrush brush(Color(255, GetRValue(c), GetGValue(c), GetBValue(c))); |
| | | Pen outline(Color(255, 120, 120, 120), 1.f); |
| | | g.FillEllipse(&brush, rDot.left, rDot.top, rDot.Width(), rDot.Height()); |
| | | g.DrawEllipse(&outline, (REAL)rDot.left, (REAL)rDot.top, (REAL)rDot.Width(), (REAL)rDot.Height()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // ===== 卿¯ä¸ªå·²åé
(allocated)çåä¸å¤®ç»å¶åéæ LOCK æ°´å°ï¼ç¨ HDC+LOGFONT æé åä½ï¼===== |
| | | { |
| | | Gdiplus::Graphics g(pDC->GetSafeHdc()); |
| | | g.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); |
| | | |
| | | CRect cli = GetClientRectNoSB(); |
| | | CRect rh = GetHeaderRect(); |
| | | |
| | | // åå½å UI åä½ï¼ä¼å
ç²ä½ï¼ |
| | | LOGFONT lf{}; |
| | | if ((HFONT)m_fntBold) m_fntBold.GetLogFont(&lf); |
| | | else if ((HFONT)m_fntText) m_fntText.GetLogFont(&lf); |
| | | |
| | | for (int i = 0; i < GetPortCount(); ++i) |
| | | { |
| | | if (!m_ports[i].allocated) continue; |
| | | |
| | | // åç©å½¢ï¼é¤å»è¡¨å¤´ï¼èèæ°´å¹³æ»å¨ï¼ |
| | | CRect rCol = GetHeaderItemRect(i + 1); |
| | | rCol.top = rh.bottom; |
| | | rCol.bottom = cli.bottom; |
| | | if (rCol.right <= cli.left || rCol.left >= cli.right || rCol.Height() <= 0) continue; |
| | | |
| | | // èªéåºä¸ä¸ªåéçåç´ é«åº¦ |
| | | int availW = rCol.Width() - 12; |
| | | int availH = rCol.Height() - 12; |
| | | int emPx = max(16, min(min(availW / 3, availH / 5), 72)); |
| | | if (emPx < 16) emPx = 16; |
| | | // åå·ååï¼å¹¶ç»ä¸ªæ´ä½çå
åºï¼é¿å
太å°ï¼ |
| | | emPx = max(12, emPx / 2); |
| | | |
| | | // ç¨ LOGFONTW + HDC æé GDI+ åä½ |
| | | LOGFONTW lfw{}; |
| | | #ifdef UNICODE |
| | | lfw = *reinterpret_cast<LOGFONTW*>(&lf); |
| | | #else |
| | | lfw.lfHeight = lf.lfHeight; |
| | | lfw.lfWidth = lf.lfWidth; |
| | | lfw.lfEscapement = lf.lfEscapement; |
| | | lfw.lfOrientation = lf.lfOrientation; |
| | | lfw.lfWeight = lf.lfWeight; |
| | | lfw.lfItalic = lf.lfItalic; |
| | | lfw.lfUnderline = lf.lfUnderline; |
| | | lfw.lfStrikeOut = lf.lfStrikeOut; |
| | | lfw.lfCharSet = lf.lfCharSet; |
| | | lfw.lfOutPrecision = lf.lfOutPrecision; |
| | | lfw.lfClipPrecision = lf.lfClipPrecision; |
| | | lfw.lfQuality = lf.lfQuality; |
| | | lfw.lfPitchAndFamily = lf.lfPitchAndFamily; |
| | | MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, -1, lfw.lfFaceName, LF_FACESIZE); |
| | | #endif |
| | | lfw.lfHeight = -emPx; // è´å¼=æåç´ é«åº¦ |
| | | lfw.lfWeight = FW_BOLD; |
| | | |
| | | Gdiplus::Font gdifont(pDC->GetSafeHdc(), &lfw); // â
å ä¸ Gdiplus:: |
| | | Gdiplus::StringFormat fmt; |
| | | fmt.SetAlignment(Gdiplus::StringAlignmentCenter); |
| | | fmt.SetLineAlignment(Gdiplus::StringAlignmentCenter); |
| | | Gdiplus::Color col(140, 120, 100, 60); // åéæ |
| | | Gdiplus::SolidBrush brush(col); |
| | | Gdiplus::RectF box((Gdiplus::REAL)rCol.left, (Gdiplus::REAL)rCol.top, |
| | | (Gdiplus::REAL)rCol.Width(), (Gdiplus::REAL)rCol.Height()); |
| | | |
| | | if (gdifont.GetLastStatus() == Gdiplus::Ok) { |
| | | g.DrawString(L"LOCK", -1, &gdifont, box, &fmt, &brush); |
| | | } |
| | | else { |
| | | Gdiplus::Font fallback(L"Arial", (Gdiplus::REAL)emPx, Gdiplus::FontStyleBold, Gdiplus::UnitPixel); |
| | | g.DrawString(L"LOCK", -1, &fallback, box, &fmt, &brush); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // === 客æ·åºå
1px ç°è²è¾¹æ¡ï¼ä¸å
æ»å¨æ¡ï¼ä½ä¸ä¼ç¼ºè§/æ¢ç»å¶ï¼=== |
| | | { |
| | | CRect cli; GetClientRect(&cli); |
| | | |
| | | // ç¨ FrameRect æ´ç¨³ï¼é¿å
å³ä¸è§ä¸¢çº¿ï¼ |
| | | CBrush br; br.CreateSolidBrush(::GetSysColor(COLOR_3DSHADOW)); |
| | | CRect r = cli; |
| | | // 注æï¼å®¢æ·åºåæ æ¯ [0..width, 0..height]ï¼FrameRect ä¼å¨å
ä¾§ç» 1px |
| | | pDC->FrameRect(&r, &br); |
| | | br.DeleteObject(); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnPaint() |
| | | { |
| | | CPaintDC dc(this); |
| | | CRect rc; GetClientRect(&rc); |
| | | |
| | | CDC mem; mem.CreateCompatibleDC(&dc); |
| | | CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height()); |
| | | HGDIOBJ ob = mem.SelectObject(bmp); |
| | | |
| | | PaintTo(&mem); |
| | | dc.BitBlt(0, 0, rc.Width(), rc.Height(), &mem, 0, 0, SRCCOPY); |
| | | |
| | | mem.SelectObject(ob); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CWnd::OnSize(nType, cx, cy); |
| | | UpdateScrollRange(); |
| | | Invalidate(FALSE); |
| | | RedrawWindow(nullptr, nullptr, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pBar) |
| | | { |
| | | UNREFERENCED_PARAMETER(pBar); |
| | | |
| | | SCROLLINFO si = { sizeof(SCROLLINFO) }; |
| | | si.fMask = SIF_ALL; |
| | | GetScrollInfo(SB_HORZ, &si); |
| | | |
| | | int pos = m_scrollX; |
| | | const int maxPos = max(0, (int)si.nMax - (int)si.nPage + 1); |
| | | |
| | | switch (nSBCode) |
| | | { |
| | | case SB_LINELEFT: pos -= 30; break; |
| | | case SB_LINERIGHT: pos += 30; break; |
| | | case SB_PAGELEFT: pos -= (int)si.nPage; break; |
| | | case SB_PAGERIGHT: pos += (int)si.nPage; break; |
| | | case SB_THUMBTRACK: |
| | | case SB_THUMBPOSITION: |
| | | pos = (int)si.nTrackPos; // â
32 使å¨ä½ç½® |
| | | break; |
| | | default: |
| | | return; |
| | | } |
| | | |
| | | pos = max(0, min(pos, maxPos)); |
| | | if (pos != m_scrollX) { |
| | | m_scrollX = pos; |
| | | SetScrollPos(SB_HORZ, m_scrollX); |
| | | Invalidate(FALSE); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pBar) |
| | | { |
| | | UNREFERENCED_PARAMETER(pBar); |
| | | |
| | | SCROLLINFO si = { sizeof(SCROLLINFO) }; |
| | | si.fMask = SIF_ALL; |
| | | GetScrollInfo(SB_VERT, &si); |
| | | |
| | | int pos = m_scrollY; |
| | | const int maxPos = max(0, (int)si.nMax - (int)si.nPage + 1); |
| | | |
| | | switch (nSBCode) |
| | | { |
| | | case SB_LINEUP: pos -= m_rowHeight; break; |
| | | case SB_LINEDOWN: pos += m_rowHeight; break; |
| | | case SB_PAGEUP: pos -= (int)si.nPage; break; |
| | | case SB_PAGEDOWN: pos += (int)si.nPage; break; |
| | | case SB_THUMBTRACK: |
| | | case SB_THUMBPOSITION: |
| | | pos = (int)si.nTrackPos; // â
32 使å¨ä½ç½® |
| | | break; |
| | | default: |
| | | return; |
| | | } |
| | | |
| | | pos = max(0, min(pos, maxPos)); |
| | | if (pos != m_scrollY) { |
| | | m_scrollY = pos; |
| | | SetScrollPos(SB_VERT, m_scrollY); |
| | | Invalidate(FALSE); |
| | | } |
| | | } |
| | | |
| | | BOOL CCarrierSlotGrid::OnMouseWheel(UINT, short zDelta, CPoint) |
| | | { |
| | | int delta = (zDelta > 0 ? -1 : +1) * (m_rowHeight * 3); |
| | | m_scrollY = max(0, m_scrollY + delta); |
| | | UpdateScrollRange(); |
| | | Invalidate(FALSE); |
| | | return TRUE; |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnShowWindow(BOOL bShow, UINT nStatus) |
| | | { |
| | | CWnd::OnShowWindow(bShow, nStatus); |
| | | if (bShow) { UpdateScrollRange(); Invalidate(FALSE); } |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnWindowPosChanged(WINDOWPOS* wp) |
| | | { |
| | | CWnd::OnWindowPosChanged(wp); |
| | | if (wp && (wp->flags & SWP_SHOWWINDOW)) { UpdateScrollRange(); Invalidate(FALSE); } |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnLButtonDown(UINT nFlags, CPoint pt) |
| | | { |
| | | // æ¯å¦æå¨å宽 |
| | | int edge = m_bAllowResize ? HitHeaderEdge(pt) : -1; // â ä¿®æ¹ |
| | | if (edge >= 0) |
| | | { |
| | | m_bResizing = true; |
| | | m_resizeEdge = edge; |
| | | m_resizeStartX = pt.x; |
| | | m_slotColCXStart = m_slotColCX; |
| | | m_portColCXsStart = m_portColCXs; |
| | | SetCapture(); |
| | | return; |
| | | } |
| | | |
| | | // Header ç¹å»ï¼ä»
å¤éæ¡åºåï¼ |
| | | if (GetHeaderRect().PtInRect(pt)) |
| | | { |
| | | for (int i = 1; i <= GetPortCount(); ++i) |
| | | { |
| | | CRect rItem = GetHeaderItemRect(i); |
| | | if (!rItem.PtInRect(pt)) continue; |
| | | |
| | | CRect rcCb = GetHeaderCheckboxRect(i); |
| | | if (!rcCb.PtInRect(pt)) return; |
| | | |
| | | int port = i - 1; |
| | | if (!SAFE_PORT(port) || m_ports[port].allocated) return; |
| | | |
| | | bool any = false, all = true; |
| | | for (auto& cell : m_ports[port].slots) { |
| | | if (!cell.hasGlass) continue; |
| | | any = true; if (!cell.checked) { all = false; break; } |
| | | } |
| | | if (!any) return; |
| | | CheckAllInPort(port, all ? FALSE : TRUE, TRUE); |
| | | return; |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // Cell ç¹å» |
| | | CRect cli = GetClientRectNoSB(); |
| | | if (pt.y < cli.top + m_headerCY) return; |
| | | int yIn = pt.y - (cli.top + m_headerCY) + m_scrollY; |
| | | int row = yIn / m_rowHeight; |
| | | if (!SAFE_SLOT(row)) return; |
| | | |
| | | int x = pt.x + m_scrollX - cli.left; |
| | | int sub = 0; |
| | | if (x < m_slotColCX) sub = 0; |
| | | else { |
| | | x -= m_slotColCX; |
| | | sub = 1; |
| | | for (size_t i = 0; i < m_portColCXs.size(); ++i) { |
| | | if (x < m_portColCXs[i]) { sub = (int)i + 1; break; } |
| | | x -= m_portColCXs[i]; |
| | | sub = (int)i + 2; |
| | | } |
| | | if (sub < 1 || sub > GetPortCount()) return; |
| | | } |
| | | |
| | | if (sub == 0) return; |
| | | int port = sub - 1; |
| | | if (!SAFE_PORT(port)) return; |
| | | |
| | | auto& pc = m_ports[port]; |
| | | auto& cell = pc.slots[row]; |
| | | |
| | | CRect rc; if (!GetCellRect(row, sub, rc)) return; |
| | | |
| | | if (pc.allocated || !cell.hasGlass) return; |
| | | |
| | | if (GetCheckboxRect(rc).PtInRect(pt)) |
| | | { |
| | | cell.checked = !cell.checked; |
| | | NotifySelectionChanged(port, row, cell.checked); |
| | | Invalidate(FALSE); |
| | | return; |
| | | } |
| | | |
| | | if (m_bShowMatToggle && GetMaterialTagRect(rc).PtInRect(pt)) |
| | | { |
| | | cell.material = (cell.material == MAT_G1) ? MAT_G2 : MAT_G1; |
| | | NotifyMaterialChanged(port, row, cell.material); |
| | | Invalidate(FALSE); |
| | | return; |
| | | } |
| | | |
| | | CWnd::OnLButtonDown(nFlags, pt); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnLButtonUp(UINT nFlags, CPoint pt) |
| | | { |
| | | if (m_bResizing) |
| | | { |
| | | ReleaseCapture(); |
| | | m_bResizing = false; |
| | | m_resizeEdge = -1; |
| | | UpdateScrollRange(); |
| | | Invalidate(FALSE); |
| | | } |
| | | CWnd::OnLButtonUp(nFlags, pt); |
| | | } |
| | | |
| | | void CCarrierSlotGrid::OnMouseMove(UINT nFlags, CPoint pt) |
| | | { |
| | | if (m_bResizing) |
| | | { |
| | | int dx = pt.x - m_resizeStartX; |
| | | if (m_resizeEdge == 0) |
| | | { |
| | | int nw = max(m_slotColMin, m_slotColCXStart + dx); |
| | | if (nw != m_slotColCX) { m_slotColCX = nw; UpdateScrollRange(); Invalidate(FALSE); } |
| | | } |
| | | else |
| | | { |
| | | int idx = m_resizeEdge - 1; // è°æ´ Port idx ç宽度 |
| | | int nw = max(m_portColMin, m_portColCXsStart[idx] + dx); |
| | | if (nw != m_portColCXs[idx]) { m_portColCXs[idx] = nw; UpdateScrollRange(); Invalidate(FALSE); } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | int edge = HitHeaderEdge(pt); |
| | | if (edge != m_hitEdgeHover) |
| | | { |
| | | m_hitEdgeHover = edge; |
| | | if (m_hitEdgeHover >= 0) ::SetCursor(::LoadCursor(nullptr, IDC_SIZEWE)); |
| | | else ::SetCursor(::LoadCursor(nullptr, IDC_ARROW)); |
| | | } |
| | | } |
| | | |
| | | BOOL CCarrierSlotGrid::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) |
| | | { |
| | | CPoint pt; ::GetCursorPos(&pt); ScreenToClient(&pt); |
| | | if (m_bAllowResize && (m_bResizing || HitHeaderEdge(pt) >= 0)) |
| | | { |
| | | ::SetCursor(::LoadCursor(nullptr, IDC_SIZEWE)); |
| | | return TRUE; |
| | | } |
| | | return CWnd::OnSetCursor(pWnd, nHitTest, message); |
| | | } |
| | | |
| | | // ---------- ֪ͨ ---------- |
| | | void CCarrierSlotGrid::NotifySelectionChanged(int /*port*/, int /*slot*/, BOOL /*checked*/) |
| | | { |
| | | if (GetParent()) |
| | | { |
| | | const int code = 0x2001; |
| | | GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), code), (LPARAM)m_hWnd); |
| | | } |
| | | } |
| | | void CCarrierSlotGrid::NotifyMaterialChanged(int /*port*/, int /*slot*/, int /*material*/) |
| | | { |
| | | if (GetParent()) |
| | | { |
| | | const int code = 0x2002; |
| | | GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), code), (LPARAM)m_hWnd); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #pragma once |
| | | |
| | | #include <vector> |
| | | |
| | | #ifndef _AFX |
| | | #include <afxwin.h> |
| | | #endif |
| | | |
| | | class CCarrierSlotGrid : public CWnd |
| | | { |
| | | public: |
| | | enum MaterialType { MAT_G1 = 1, MAT_G2 = 2 }; |
| | | |
| | | struct SlotCell { |
| | | bool hasGlass = false; |
| | | CString coreId; |
| | | int material = MAT_G1; |
| | | bool checked = false; |
| | | }; |
| | | struct PortColumn { |
| | | CString portName; |
| | | CString carrierName; |
| | | bool allocated = false; |
| | | CString allocatedBy; |
| | | std::vector<SlotCell> slots; |
| | | }; |
| | | |
| | | public: |
| | | CCarrierSlotGrid(); |
| | | virtual ~CCarrierSlotGrid(); |
| | | |
| | | BOOL SubclassDlgItem(UINT nID, CWnd* pParent) { |
| | | BOOL ok = CWnd::SubclassDlgItem(nID, pParent); |
| | | if (ok) { |
| | | if (pParent && pParent->GetFont()) SetFont(pParent->GetFont()); |
| | | EnsureFonts(); |
| | | Invalidate(FALSE); |
| | | } |
| | | return ok; |
| | | } |
| | | virtual void PreSubclassWindow() override; |
| | | |
| | | // åå§å |
| | | void InitGrid(int nPorts, int nSlots); |
| | | void SetColumnWidths(int slotColWidth, int portColWidth); |
| | | void SetRowHeight(int cy); |
| | | void SetHeaderHeight(int cy); |
| | | void SetShowMaterialToggle(BOOL bShow); |
| | | |
| | | // 读/å |
| | | int GetPortCount() const { return (int)m_ports.size(); } |
| | | int GetSlotCount() const { return m_nSlots; } |
| | | |
| | | void SetPortInfo(int portIndex, LPCTSTR portName, LPCTSTR carrierName); |
| | | void SetPortAllocated(int portIndex, BOOL allocated, LPCTSTR byName = nullptr); |
| | | BOOL IsPortAllocated(int portIndex) const; |
| | | |
| | | void SetSlotGlass(int portIndex, int slotIndex, BOOL hasGlass, LPCTSTR coreId, int material); |
| | | void SetSlotChecked(int portIndex, int slotIndex, BOOL checked); |
| | | BOOL GetSlotChecked(int portIndex, int slotIndex) const; |
| | | |
| | | int GetSlotMaterialType(int portIndex, int slotIndex) const; |
| | | void SetSlotMaterialType(int portIndex, int slotIndex, int material, BOOL bNotify = TRUE); |
| | | |
| | | CString GetDisplayId(int portIndex, int slotIndex) const; |
| | | void CheckAllInPort(int portIndex, BOOL checked, BOOL bNotify = TRUE); |
| | | |
| | | void RebuildTexts(); |
| | | void EnableColumnResize(BOOL enable) { m_bAllowResize = !!enable; Invalidate(FALSE); } |
| | | |
| | | // è®¡ç®æä½³å¤§å°ï¼ |
| | | // - CalcBestClientSizeï¼å
容åºåï¼ä¸å«æ»å¨æ¡/é客æ·åºï¼å好容纳表头+ææè¡ãå
¨é¨å |
| | | // - CalcBestWindowSizeï¼å¨å½åçªå£æ ·å¼ä¸ï¼å°âå
容大å°â转æ¢ä¸ºçªå£å¤æ¡å¤§å°ï¼ä¼èè WS_BORDER/CLIENTEDGE çï¼ |
| | | // é»è®¤æâéèæ»å¨æ¡âçç®æ æ¥ç®ï¼å³ä¸æ WS_HSCROLL/WS_VSCROLL 计å
¥è°æ´ï¼ |
| | | CSize CalcBestClientSize(int nSlotsOverride = -1) const; |
| | | CSize CalcBestWindowSize(BOOL includeNonClient = TRUE, int nSlotsOverride = -1) const; |
| | | |
| | | |
| | | protected: |
| | | // æ°æ® |
| | | int m_nSlots = 0; |
| | | std::vector<PortColumn> m_ports; |
| | | BOOL m_bShowMatToggle = TRUE; |
| | | |
| | | // 尺寸/æ»å¨ |
| | | int m_rowHeight = 26; |
| | | int m_headerCY = 28; |
| | | int m_slotColCX = 100; |
| | | std::vector<int> m_portColCXs; |
| | | int m_scrollY = 0; |
| | | int m_scrollX = 0; |
| | | int m_slotColMin = 60; |
| | | int m_portColMin = 80; |
| | | |
| | | // é¢è² |
| | | COLORREF m_colBg = RGB(255, 255, 255); |
| | | COLORREF m_colAlt = RGB(240, 242, 245); |
| | | COLORREF m_colLock = RGB(255, 244, 214); |
| | | COLORREF m_gridMajor = RGB(210, 214, 220); |
| | | COLORREF m_gridMinor = RGB(220, 224, 230); |
| | | COLORREF m_text = RGB(40, 40, 40); |
| | | COLORREF m_textDim = RGB(150, 150, 150); |
| | | |
| | | // åä½ |
| | | CFont m_fntText; |
| | | CFont m_fntBold; |
| | | CFont m_fntSmall; |
| | | |
| | | // æå¨å宽 |
| | | bool m_bResizing = false; |
| | | int m_resizeEdge = -1; // 0=Slot|Port1ï¼1..N-1=Port i|i+1 |
| | | int m_resizeStartX = 0; |
| | | int m_slotColCXStart = 0; |
| | | std::vector<int> m_portColCXsStart; |
| | | int m_hitEdgeHover = -1; |
| | | bool m_bAllowResize = true; // â æ°å¢ï¼æ¯å¦å
许æå¨å宽 |
| | | |
| | | // å·¥å
· |
| | | void EnsureFonts(); |
| | | void UpdateScrollRange(); |
| | | int GetTotalContentWidth() const; |
| | | void NotifySelectionChanged(int port, int slot, BOOL checked); |
| | | void NotifyMaterialChanged(int port, int slot, int material); |
| | | |
| | | // å ä½ |
| | | CRect GetClientRectNoSB() const; |
| | | BOOL GetCellRect(int row, int sub, CRect& rc) const; // sub: 0=Slot, 1..N=Port |
| | | CRect GetHeaderRect() const; |
| | | CRect GetHeaderItemRect(int iItem) const; |
| | | CRect GetHeaderCheckboxRect(int iItem) const; |
| | | CRect GetCheckboxRect(const CRect& cell) const; |
| | | CRect GetMaterialTagRect(const CRect& cell) const; |
| | | CRect GetStatusDotRect(const CRect& cell) const; |
| | | BOOL IsColumnResizeEnabled() const { return m_bAllowResize ? TRUE : FALSE; } |
| | | |
| | | int HitHeaderEdge(CPoint pt) const; |
| | | |
| | | // ç»å¶ |
| | | void DrawFlatCheckbox(CDC* pDC, const CRect& r, bool checked, bool disabled); |
| | | void PaintTo(CDC* pDC); |
| | | |
| | | protected: |
| | | // æ¶æ¯ |
| | | afx_msg BOOL OnEraseBkgnd(CDC* pDC); |
| | | afx_msg void OnPaint(); |
| | | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); |
| | | afx_msg void OnSize(UINT nType, int cx, int cy); |
| | | afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); |
| | | afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); // â
çºµåæ»å¨æ¡ |
| | | afx_msg void OnLButtonDown(UINT nFlags, CPoint pt); |
| | | afx_msg void OnLButtonUp(UINT nFlags, CPoint pt); |
| | | afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); |
| | | afx_msg void OnMouseMove(UINT nFlags, CPoint pt); |
| | | afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); |
| | | afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); |
| | | afx_msg void OnWindowPosChanged(WINDOWPOS* wp); |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CCarrierSlotSelector.h" |
| | | |
| | | #define SAFE_PORT(p) ((p) >= 0 && (p) < (int)m_ports.size()) |
| | | #define SAFE_SLOT(s) ((s) >= 0 && (s) < m_nSlots) |
| | | |
| | | #ifndef LVS_EX_DOUBLEBUFFER |
| | | #define LVS_EX_DOUBLEBUFFER 0x00010000 |
| | | #endif |
| | | |
| | | BEGIN_MESSAGE_MAP(CCarrierSlotSelector, CListCtrl) |
| | | ON_WM_SHOWWINDOW() |
| | | ON_WM_WINDOWPOSCHANGED() |
| | | ON_WM_SIZE() |
| | | ON_WM_ERASEBKGND() |
| | | ON_WM_PAINT() // â
æ°å¢ |
| | | ON_WM_LBUTTONDOWN() |
| | | ON_WM_MOUSEMOVE() |
| | | ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CCarrierSlotSelector::OnCustomDraw) |
| | | END_MESSAGE_MAP() |
| | | |
| | | CCarrierSlotSelector::CCarrierSlotSelector() {} |
| | | CCarrierSlotSelector::~CCarrierSlotSelector() |
| | | { |
| | | if ((HFONT)m_fntText) m_fntText.DeleteObject(); |
| | | if ((HFONT)m_fntBold) m_fntBold.DeleteObject(); |
| | | if ((HFONT)m_fntSmall) m_fntSmall.DeleteObject(); |
| | | if ((HIMAGELIST)m_ilRowHeight) m_ilRowHeight.DeleteImageList(); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::PreSubclassWindow() |
| | | { |
| | | CListCtrl::PreSubclassWindow(); |
| | | |
| | | ModifyStyle(LVS_TYPEMASK, LVS_REPORT | LVS_SHOWSELALWAYS); |
| | | ModifyStyle(LVS_OWNERDRAWFIXED | LVS_OWNERDATA, 0); |
| | | |
| | | DWORD ex = GetExtendedStyle(); |
| | | ex |= LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER; |
| | | ex &= ~LVS_EX_GRIDLINES; // å
³éç³»ç»ç½æ ¼ï¼æ¹èªç» |
| | | SetExtendedStyle(ex); |
| | | |
| | | // 让é»è®¤ç»å¶ç¨æä»¬çåºè²ï¼è¿ä¸æ¥éä½ç½åºæºä¼ï¼å³ä½¿åªå¤èµ°äºé»è®¤è·¯å¾ï¼ |
| | | ListView_SetBkColor(m_hWnd, m_colBgNorm); |
| | | ListView_SetTextBkColor(m_hWnd, m_colBgNorm); |
| | | |
| | | EnsureFonts(); |
| | | SetRowHeight(m_rowHeight); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnShowWindow(BOOL bShow, UINT nStatus) |
| | | { |
| | | CListCtrl::OnShowWindow(bShow, nStatus); |
| | | if (bShow && !m_bFirstShown) |
| | | { |
| | | m_bFirstShown = TRUE; |
| | | RedrawWindow(nullptr, nullptr, |
| | | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN | RDW_UPDATENOW); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnWindowPosChanged(WINDOWPOS* wp) |
| | | { |
| | | CListCtrl::OnWindowPosChanged(wp); |
| | | if (wp && (wp->flags & SWP_SHOWWINDOW)) |
| | | { |
| | | RedrawWindow(nullptr, nullptr, |
| | | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN | RDW_UPDATENOW); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotSelector::EnsureFonts() |
| | | { |
| | | if (!(HFONT)m_fntText) |
| | | { |
| | | LOGFONT lf = { 0 }; |
| | | CFont* pSys = GetFont(); |
| | | if (pSys) pSys->GetLogFont(&lf); |
| | | else { lf.lfHeight = -14; lstrcpy(lf.lfFaceName, _T("Segoe UI")); } |
| | | m_fntText.CreateFontIndirect(&lf); |
| | | |
| | | lf.lfWeight = FW_SEMIBOLD; |
| | | m_fntBold.CreateFontIndirect(&lf); |
| | | |
| | | lf.lfWeight = FW_NORMAL; lf.lfHeight = -12; |
| | | m_fntSmall.CreateFontIndirect(&lf); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotSelector::InitGrid(int nPorts, int nSlots) |
| | | { |
| | | ASSERT(nPorts >= 1 && nSlots >= 1); |
| | | m_ports.clear(); |
| | | m_ports.resize(nPorts); |
| | | m_nSlots = nSlots; |
| | | for (auto& pc : m_ports) pc.slots.resize(m_nSlots); |
| | | |
| | | SetRedraw(FALSE); |
| | | DeleteAllItems(); |
| | | while (GetHeaderCtrl() && GetHeaderCtrl()->GetItemCount() > 0) |
| | | DeleteColumn(0); |
| | | |
| | | InsertColumn(0, _T("Slot"), LVCFMT_LEFT, m_slotColWidth); |
| | | for (int c = 0; c < nPorts; ++c) |
| | | { |
| | | CString col; col.Format(_T("Port %d"), c + 1); |
| | | InsertColumn(c + 1, col, LVCFMT_LEFT, m_portColWidth); |
| | | m_ports[c].portName = col; |
| | | m_ports[c].carrierName.Empty(); |
| | | } |
| | | |
| | | UpdateRowCount(); |
| | | RebuildTexts(); |
| | | SetRedraw(TRUE); |
| | | if (IsWindowVisible()) Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetColumnWidths(int slotColWidth, int portColWidth) |
| | | { |
| | | if (slotColWidth > 0) m_slotColWidth = slotColWidth; |
| | | if (portColWidth > 0) m_portColWidth = portColWidth; |
| | | SetColumnWidth(0, m_slotColWidth); |
| | | for (int c = 0; c < (int)m_ports.size(); ++c) SetColumnWidth(c + 1, m_portColWidth); |
| | | if (IsWindowVisible()) Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetRowHeight(int cy) |
| | | { |
| | | cy = max(18, min(cy, 64)); |
| | | m_rowHeight = cy; |
| | | |
| | | if ((HIMAGELIST)m_ilRowHeight) m_ilRowHeight.DeleteImageList(); |
| | | m_ilRowHeight.Create(1, m_rowHeight, ILC_COLOR32, 1, 1); |
| | | |
| | | // 1Ãcy éæä½å¾ |
| | | CBitmap bmp; bmp.CreateBitmap(1, m_rowHeight, 1, 32, nullptr); |
| | | m_ilRowHeight.Add(&bmp, RGB(0, 0, 0)); |
| | | SetImageList(&m_ilRowHeight, LVSIL_SMALL); |
| | | |
| | | if (IsWindowVisible()) Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::UpdateRowCount() |
| | | { |
| | | int cur = GetItemCount(); |
| | | if (cur < m_nSlots) |
| | | { |
| | | for (int i = cur; i < m_nSlots; ++i) |
| | | { |
| | | CString s; s.Format(_T("Slot %d"), i + 1); |
| | | InsertItem(i, s, 0); // 设 iImage=0ï¼è¡é«æ¥èª small image list |
| | | } |
| | | } |
| | | else if (cur > m_nSlots) |
| | | { |
| | | for (int i = cur - 1; i >= m_nSlots; --i) DeleteItem(i); |
| | | } |
| | | |
| | | // å·²æè¡ä¹ç»ä¸è®¾ iImage=0 |
| | | LVITEM lvi = { 0 }; |
| | | lvi.mask = LVIF_IMAGE; lvi.iImage = 0; |
| | | for (int i = 0; i < m_nSlots; ++i) { lvi.iItem = i; SetItem(&lvi); } |
| | | } |
| | | |
| | | void CCarrierSlotSelector::RebuildTexts() |
| | | { |
| | | // åå¤´ï¼æ¾ç¤º â已鿰/æ»æ§½æ° ï¼ [x]/[ ]â |
| | | for (int c = 0; c < (int)m_ports.size(); ++c) |
| | | { |
| | | int selected = 0; |
| | | int total = m_nSlots; |
| | | |
| | | bool anyCheckable = false; |
| | | bool allChecked = true; |
| | | |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | const auto& cell = m_ports[c].slots[r]; |
| | | if (cell.hasGlass) |
| | | { |
| | | anyCheckable = true; |
| | | if (cell.checked) ++selected; else allChecked = false; |
| | | } |
| | | } |
| | | if (!anyCheckable) allChecked = false; |
| | | |
| | | CString head; |
| | | CString chk = allChecked ? _T("[x]") : _T("[ ]"); |
| | | |
| | | if (!m_ports[c].carrierName.IsEmpty()) |
| | | head.Format(_T("%s (%s) %d/%d %s%s"), |
| | | m_ports[c].portName.GetString(), m_ports[c].carrierName.GetString(), |
| | | selected, total, |
| | | m_ports[c].allocated ? _T("[LOCK] ") : _T(""), |
| | | chk.GetString()); |
| | | else |
| | | head.Format(_T("%s %d/%d %s%s"), |
| | | m_ports[c].portName.GetString(), selected, total, |
| | | m_ports[c].allocated ? _T("[LOCK] ") : _T(""), |
| | | chk.GetString()); |
| | | |
| | | LVCOLUMN lvc = { 0 }; lvc.mask = LVCF_TEXT; lvc.pszText = head.GetBuffer(); |
| | | SetColumn(c + 1, &lvc); |
| | | head.ReleaseBuffer(); |
| | | } |
| | | |
| | | // è¡å¤´ææ¬ |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | CString s; s.Format(_T("Slot %d"), r + 1); |
| | | SetItemText(r, 0, s); |
| | | } |
| | | |
| | | // åå
æ ¼ä¸´æ¶ææ¬ |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | for (int c = 0; c < (int)m_ports.size(); ++c) |
| | | SetItemText(r, c + 1, GetDisplayId(c, r)); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetShowMaterialToggle(BOOL bShow) |
| | | { |
| | | m_bShowMatToggle = bShow; |
| | | if (IsWindowVisible()) Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetPortInfo(int portIndex, LPCTSTR portName, LPCTSTR carrierName) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | if (portName) m_ports[portIndex].portName = portName; |
| | | if (carrierName) m_ports[portIndex].carrierName = carrierName; |
| | | RebuildTexts(); |
| | | if (IsWindowVisible()) Invalidate(FALSE); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetPortAllocated(int portIndex, BOOL allocated, LPCTSTR byName) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | m_ports[portIndex].allocated = !!allocated; |
| | | if (byName) m_ports[portIndex].allocatedBy = byName; else m_ports[portIndex].allocatedBy.Empty(); |
| | | |
| | | if (allocated) |
| | | for (int r = 0; r < m_nSlots; ++r) m_ports[portIndex].slots[r].checked = false; |
| | | |
| | | // å·æ°æ´å |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | CRect rc; GetSubItemRect(r, portIndex + 1, LVIR_BOUNDS, rc); |
| | | InvalidateRect(&rc, FALSE); |
| | | } |
| | | RebuildTexts(); |
| | | } |
| | | |
| | | BOOL CCarrierSlotSelector::IsPortAllocated(int portIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return FALSE; |
| | | return m_ports[portIndex].allocated; |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetSlotGlass(int portIndex, int slotIndex, BOOL hasGlass, LPCTSTR coreId, int material) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | cell.hasGlass = !!hasGlass; |
| | | cell.coreId = coreId ? coreId : _T(""); |
| | | cell.material = (material == MAT_G2) ? MAT_G2 : MAT_G1; |
| | | if (!cell.hasGlass) cell.checked = false; |
| | | |
| | | CRect rc; GetSubItemRect(slotIndex, portIndex + 1, LVIR_BOUNDS, rc); |
| | | InvalidateRect(&rc, FALSE); |
| | | RebuildTexts(); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetSlotChecked(int portIndex, int slotIndex, BOOL checked) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | if (m_ports[portIndex].allocated) return; |
| | | auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | if (!cell.hasGlass) return; |
| | | |
| | | cell.checked = !!checked; |
| | | NotifySelectionChanged(portIndex, slotIndex, cell.checked); |
| | | |
| | | CRect rc; GetSubItemRect(slotIndex, portIndex + 1, LVIR_BOUNDS, rc); |
| | | InvalidateRect(&rc, FALSE); |
| | | RebuildTexts(); |
| | | } |
| | | |
| | | BOOL CCarrierSlotSelector::GetSlotChecked(int portIndex, int slotIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return FALSE; |
| | | return m_ports[portIndex].slots[slotIndex].checked ? TRUE : FALSE; |
| | | } |
| | | |
| | | int CCarrierSlotSelector::GetSlotMaterialType(int portIndex, int slotIndex) const |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return MAT_G1; |
| | | return m_ports[portIndex].slots[slotIndex].material; |
| | | } |
| | | |
| | | void CCarrierSlotSelector::SetSlotMaterialType(int portIndex, int slotIndex, int material, BOOL bNotify) |
| | | { |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return; |
| | | if (m_ports[portIndex].allocated) return; |
| | | auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | if (!cell.hasGlass) return; |
| | | |
| | | int mt = (material == MAT_G2) ? MAT_G2 : MAT_G1; |
| | | if (cell.material != mt) |
| | | { |
| | | cell.material = mt; |
| | | if (bNotify) NotifyMaterialChanged(portIndex, slotIndex, cell.material); |
| | | CRect rc; GetSubItemRect(slotIndex, portIndex + 1, LVIR_BOUNDS, rc); |
| | | InvalidateRect(&rc, FALSE); |
| | | } |
| | | } |
| | | |
| | | CString CCarrierSlotSelector::GetDisplayId(int portIndex, int slotIndex) const |
| | | { |
| | | CString s(_T("â")); |
| | | if (!SAFE_PORT(portIndex) || !SAFE_SLOT(slotIndex)) return s; |
| | | const auto& cell = m_ports[portIndex].slots[slotIndex]; |
| | | if (!cell.hasGlass) return s; |
| | | s.Format(_T("G%d-%s"), (cell.material == MAT_G2) ? 2 : 1, cell.coreId.GetString()); |
| | | return s; |
| | | } |
| | | |
| | | void CCarrierSlotSelector::CheckAllInPort(int portIndex, BOOL checked, BOOL bNotify) |
| | | { |
| | | if (!SAFE_PORT(portIndex)) return; |
| | | if (m_ports[portIndex].allocated) return; |
| | | |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | auto& cell = m_ports[portIndex].slots[r]; |
| | | if (!cell.hasGlass) continue; |
| | | if (cell.checked != !!checked) |
| | | { |
| | | cell.checked = !!checked; |
| | | if (bNotify) NotifySelectionChanged(portIndex, r, cell.checked); |
| | | } |
| | | CRect rc; GetSubItemRect(r, portIndex + 1, LVIR_BOUNDS, rc); |
| | | InvalidateRect(&rc, FALSE); |
| | | } |
| | | RebuildTexts(); |
| | | } |
| | | |
| | | BOOL CCarrierSlotSelector::OnEraseBkgnd(CDC* /*pDC*/) |
| | | { |
| | | // å
³é®ï¼ä¸è®©ç³»ç»æ¦ç½èæ¯ï¼ç¨èªç»å¨ PREPAINT é¶æ®µç»ä¸éºåº |
| | | return TRUE; |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnPaint() |
| | | { |
| | | CPaintDC dc(this); |
| | | CRect rc; GetClientRect(&rc); |
| | | |
| | | CDC memDC; |
| | | memDC.CreateCompatibleDC(&dc); |
| | | CBitmap bmp; |
| | | bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height()); |
| | | HGDIOBJ hOldBmp = memDC.SelectObject(bmp); |
| | | |
| | | // ç»ä¸åºè²ï¼é¿å
任使¦ç½ï¼ |
| | | memDC.FillSolidRect(rc, m_colBgNorm); |
| | | |
| | | // 让æ§ä»¶æå®¢æ·åºå
容âç»å°âå
åDCï¼ä¼è§¦å NM_CUSTOMDRAWï¼èµ°ä½ ç°æèªç»é»è¾ï¼ |
| | | // PRF_ERASEBKGND 让å
é¨å¦ææ³æ¦èæ¯ï¼ä¹å¨å
å鿦ï¼ä¸ä¼éªå± |
| | | SendMessage(WM_PRINTCLIENT, |
| | | reinterpret_cast<WPARAM>(memDC.m_hDC), |
| | | PRF_CLIENT | PRF_ERASEBKGND | PRF_CHILDREN | PRF_OWNED); |
| | | |
| | | // åæ¾å°å±å¹ |
| | | dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memDC, 0, 0, SRCCOPY); |
| | | |
| | | memDC.SelectObject(hOldBmp); |
| | | // bmp, memDC ææèªå¨éæ¾ |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CListCtrl::OnSize(nType, cx, cy); |
| | | } |
| | | |
| | | CRect CCarrierSlotSelector::GetCheckboxRect(const CRect& cell) const |
| | | { |
| | | int sz = max(14, min(int(m_rowHeight * 0.70), 20)); |
| | | int leftPad = 8; |
| | | int top = cell.top + (m_rowHeight - sz) / 2; |
| | | return CRect(cell.left + leftPad, top, cell.left + leftPad + sz, top + sz); |
| | | } |
| | | |
| | | CRect CCarrierSlotSelector::GetMaterialTagRect(const CRect& cell) const |
| | | { |
| | | int tagH = max(14, min(int(m_rowHeight * 0.65), m_rowHeight - 8)); |
| | | int tagW = 32; |
| | | int rightPadForDot = 16; |
| | | int gap = 6; |
| | | int top = cell.top + (m_rowHeight - tagH) / 2; |
| | | int right = cell.right - rightPadForDot - gap; |
| | | return CRect(right - tagW, top, right, top + tagH); |
| | | } |
| | | |
| | | CRect CCarrierSlotSelector::GetStatusDotRect(const CRect& cell) const |
| | | { |
| | | int d = max(8, min(int(m_rowHeight * 0.42), 12)); |
| | | int rightPad = 6; |
| | | int top = cell.top + (m_rowHeight - d) / 2; |
| | | return CRect(cell.right - rightPad - d, top, cell.right - rightPad, top + d); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::DrawFlatCheckbox(CDC* pDC, const CRect& r, bool checked, bool disabled) |
| | | { |
| | | CBrush br(disabled ? RGB(245, 245, 245) : RGB(255, 255, 255)); |
| | | CPen pen(PS_SOLID, 1, disabled ? RGB(200, 200, 200) : RGB(130, 130, 135)); |
| | | CBrush* pOldB = pDC->SelectObject(&br); |
| | | CPen* pOldP = pDC->SelectObject(&pen); |
| | | pDC->RoundRect(r, CPoint(3, 3)); |
| | | pDC->SelectObject(pOldB); |
| | | pDC->SelectObject(pOldP); |
| | | br.DeleteObject(); pen.DeleteObject(); |
| | | |
| | | if (!checked) return; |
| | | |
| | | COLORREF c = disabled ? RGB(160, 160, 160) : RGB(40, 150, 90); |
| | | CPen penTick(PS_SOLID, max(2, r.Height() / 8), c); |
| | | CPen* pOld = pDC->SelectObject(&penTick); |
| | | POINT p1 = { r.left + r.Width() * 2 / 9, r.top + r.Height() * 5 / 9 }; |
| | | POINT p2 = { r.left + r.Width() * 4 / 9, r.top + r.Height() * 7 / 9 }; |
| | | POINT p3 = { r.left + r.Width() * 7 / 9, r.top + r.Height() * 3 / 9 }; |
| | | pDC->MoveTo(p1); pDC->LineTo(p2); pDC->LineTo(p3); |
| | | pDC->SelectObject(pOld); |
| | | penTick.DeleteObject(); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnLButtonDown(UINT nFlags, CPoint point) |
| | | { |
| | | LVHITTESTINFO ht = { 0 }; ht.pt = point; |
| | | int row = SubItemHitTest(&ht); |
| | | int sub = (row >= 0) ? ht.iSubItem : -1; |
| | | |
| | | if (row >= 0 && sub >= 1) |
| | | { |
| | | int port = sub - 1; |
| | | if (SAFE_PORT(port) && SAFE_SLOT(row)) |
| | | { |
| | | auto& pc = m_ports[port]; |
| | | auto& cell = pc.slots[row]; |
| | | CRect rcCell; GetSubItemRect(row, sub, LVIR_BOUNDS, rcCell); |
| | | |
| | | if (pc.allocated || !cell.hasGlass) |
| | | { |
| | | CListCtrl::OnLButtonDown(nFlags, point); |
| | | return; |
| | | } |
| | | |
| | | if (GetCheckboxRect(rcCell).PtInRect(point)) |
| | | { |
| | | cell.checked = !cell.checked; |
| | | NotifySelectionChanged(port, row, cell.checked); |
| | | InvalidateRect(&rcCell, FALSE); |
| | | RebuildTexts(); |
| | | return; |
| | | } |
| | | |
| | | if (m_bShowMatToggle && GetMaterialTagRect(rcCell).PtInRect(point)) |
| | | { |
| | | cell.material = (cell.material == MAT_G1) ? MAT_G2 : MAT_G1; |
| | | NotifyMaterialChanged(port, row, cell.material); |
| | | InvalidateRect(&rcCell, FALSE); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | CListCtrl::OnLButtonDown(nFlags, point); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnMouseMove(UINT nFlags, CPoint point) |
| | | { |
| | | CListCtrl::OnMouseMove(nFlags, point); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | NMLVCUSTOMDRAW* pCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR); |
| | | |
| | | switch (pCD->nmcd.dwDrawStage) |
| | | { |
| | | case CDDS_PREPAINT: |
| | | { |
| | | // å
³é®ï¼æ´æ§ä»¶é¢å
éºåºï¼é¿å
忬¡ hover/æ¾ç¤ºæ¶âå·ç½â |
| | | CDC* pDC = CDC::FromHandle(pCD->nmcd.hdc); |
| | | CRect rcClient; GetClientRect(&rcClient); |
| | | pDC->FillSolidRect(rcClient, m_colBgNorm); |
| | | *pResult = CDRF_NOTIFYITEMDRAW; |
| | | return; |
| | | } |
| | | |
| | | case CDDS_ITEMPREPAINT: |
| | | *pResult = CDRF_NOTIFYSUBITEMDRAW; |
| | | return; |
| | | |
| | | case (CDDS_SUBITEM | CDDS_ITEMPREPAINT): |
| | | { |
| | | CDC* pDC = CDC::FromHandle(pCD->nmcd.hdc); |
| | | int row = (int)pCD->nmcd.dwItemSpec; |
| | | int sub = pCD->iSubItem; |
| | | |
| | | CRect rc; GetSubItemRect(row, sub, LVIR_BOUNDS, rc); |
| | | |
| | | // èæ¯ |
| | | COLORREF bk = m_colBgNorm; |
| | | if (sub >= 1) |
| | | { |
| | | int port = sub - 1; |
| | | if (port % 2 == 0) bk = m_colBgAlt; // 交æ¿å |
| | | if (SAFE_PORT(port) && m_ports[port].allocated) // éå®å |
| | | bk = m_colLockBg; |
| | | } |
| | | pDC->FillSolidRect(rc, bk); |
| | | |
| | | // ç½æ ¼ï¼ä¸/å·¦å ç²ï¼å³/ä¸ç»çº¿ï¼ |
| | | CPen penTopLeft(PS_SOLID, (sub >= 1 && ((sub - 1) % 2 == 0)) ? 2 : 1, RGB(210, 214, 220)); |
| | | CPen* pOldPen = pDC->SelectObject(&penTopLeft); |
| | | pDC->MoveTo(rc.left, rc.top); pDC->LineTo(rc.right, rc.top); |
| | | pDC->MoveTo(rc.left, rc.top); pDC->LineTo(rc.left, rc.bottom); |
| | | pDC->SelectObject(pOldPen); penTopLeft.DeleteObject(); |
| | | |
| | | CPen penThin(PS_SOLID, 1, RGB(220, 224, 230)); |
| | | pOldPen = pDC->SelectObject(&penThin); |
| | | if (sub == GetHeaderCtrl()->GetItemCount() - 1) { pDC->MoveTo(rc.right - 1, rc.top); pDC->LineTo(rc.right - 1, rc.bottom); } |
| | | if (row == m_nSlots - 1) { pDC->MoveTo(rc.left, rc.bottom - 1); pDC->LineTo(rc.right, rc.bottom - 1); } |
| | | pDC->SelectObject(pOldPen); penThin.DeleteObject(); |
| | | |
| | | if (sub == 0) |
| | | { |
| | | CString s; s.Format(_T("Slot %d"), row + 1); |
| | | CFont* pOld = pDC->SelectObject(&m_fntBold); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(RGB(60, 60, 64)); |
| | | CRect rText = rc; rText.DeflateRect(8, 0, 8, 0); |
| | | pDC->DrawText(s, rText, DT_LEFT | DT_VCENTER | DT_SINGLELINE); |
| | | pDC->SelectObject(pOld); |
| | | } |
| | | else if (SAFE_PORT(sub - 1) && SAFE_SLOT(row)) |
| | | { |
| | | int port = sub - 1; |
| | | const auto& pc = m_ports[port]; |
| | | const auto& cell = pc.slots[row]; |
| | | |
| | | // æå¹³å¤éæ¡ |
| | | CRect rChk = GetCheckboxRect(rc); |
| | | DrawFlatCheckbox(pDC, rChk, cell.checked, pc.allocated || !cell.hasGlass); |
| | | |
| | | // ææ¬ |
| | | CString s = GetDisplayId(port, row); |
| | | CRect rText = rc; |
| | | int leftPad = rChk.right + 6; |
| | | CRect rDot = GetStatusDotRect(rc); |
| | | CRect rTag = GetMaterialTagRect(rc); |
| | | int rightPad = rc.right - min(rTag.left - 6, rDot.left - 6); |
| | | rText.DeflateRect(leftPad - rc.left, 0, rightPad, 0); |
| | | |
| | | CFont* pOld = pDC->SelectObject(&m_fntText); |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(cell.hasGlass ? RGB(40, 40, 40) : RGB(150, 150, 150)); |
| | | pDC->DrawText(s, rText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); |
| | | pDC->SelectObject(pOld); |
| | | |
| | | // ç©ææ ç¾ï¼å¯éèï¼ |
| | | if (m_bShowMatToggle) |
| | | { |
| | | CRect rT = rTag; |
| | | COLORREF crBorder = (cell.material == MAT_G2) ? RGB(180, 150, 220) : RGB(120, 160, 220); |
| | | COLORREF crFill = (cell.material == MAT_G2) ? RGB(243, 235, 250) : RGB(233, 240, 252); |
| | | COLORREF crText = (cell.material == MAT_G2) ? RGB(90, 60, 150) : RGB(50, 90, 160); |
| | | if (pc.allocated || !cell.hasGlass) { crBorder = RGB(210, 210, 210); crFill = RGB(245, 245, 245); crText = RGB(160, 160, 160); } |
| | | CBrush br(crFill); CPen tagPen(PS_SOLID, 1, crBorder); |
| | | CPen* pOldP = pDC->SelectObject(&tagPen); |
| | | CBrush* pOldB = pDC->SelectObject(&br); |
| | | pDC->RoundRect(rT, CPoint(6, 6)); |
| | | pDC->SelectObject(pOldB); pDC->SelectObject(pOldP); |
| | | br.DeleteObject(); tagPen.DeleteObject(); |
| | | |
| | | CString t; t.Format(_T("G%d"), (cell.material == MAT_G2) ? 2 : 1); |
| | | CFont* pOldS = pDC->SelectObject(&m_fntSmall); |
| | | pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(crText); |
| | | pDC->DrawText(t, rT, DT_CENTER | DT_VCENTER | DT_SINGLELINE); |
| | | pDC->SelectObject(pOldS); |
| | | } |
| | | |
| | | // ç¶æç¹ |
| | | CRect rD = GetStatusDotRect(rc); |
| | | COLORREF dot = cell.hasGlass ? (pc.allocated ? RGB(215, 160, 60) : RGB(60, 170, 80)) : RGB(160, 160, 160); |
| | | CBrush bDot(dot); CBrush* pOldB = pDC->SelectObject(&bDot); |
| | | pDC->Ellipse(rD); |
| | | pDC->SelectObject(pOldB); bDot.DeleteObject(); |
| | | } |
| | | |
| | | *pResult = CDRF_SKIPDEFAULT; // å项å®å
¨èªç» |
| | | return; |
| | | } |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | *pResult = 0; |
| | | } |
| | | |
| | | BOOL CCarrierSlotSelector::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) |
| | | { |
| | | NMHDR* pNM = reinterpret_cast<NMHDR*>(lParam); |
| | | if (pNM && pNM->hwndFrom == GetHeaderCtrl()->GetSafeHwnd()) |
| | | { |
| | | switch (pNM->code) |
| | | { |
| | | case HDN_ITEMCLICKA: |
| | | case HDN_ITEMCLICKW: |
| | | { |
| | | HD_NOTIFY* phdn = reinterpret_cast<HD_NOTIFY*>(lParam); |
| | | OnHeaderClick(phdn->iItem); |
| | | if (pResult) *pResult = 0; |
| | | return TRUE; // æä»¬å·²å¤ç |
| | | } |
| | | default: break; |
| | | } |
| | | } |
| | | return CListCtrl::OnNotify(wParam, lParam, pResult); |
| | | } |
| | | |
| | | void CCarrierSlotSelector::OnHeaderClick(int iItem) |
| | | { |
| | | // iItem: 0=Slot åï¼>=1 为 Port å |
| | | if (iItem <= 0) return; |
| | | int port = iItem - 1; |
| | | if (!SAFE_PORT(port) || m_ports[port].allocated) return; |
| | | |
| | | // è®¡ç®æ¯å¦âå
¨éâ |
| | | bool anyCheckable = false; |
| | | bool allChecked = true; |
| | | for (int r = 0; r < m_nSlots; ++r) |
| | | { |
| | | const auto& cell = m_ports[port].slots[r]; |
| | | if (!cell.hasGlass) continue; |
| | | anyCheckable = true; |
| | | if (!cell.checked) { allChecked = false; break; } |
| | | } |
| | | if (!anyCheckable) return; |
| | | |
| | | // 忢ï¼è¥å·²å
¨é -> åæ¶å
¨éï¼å¦å -> å
¨é |
| | | CheckAllInPort(port, allChecked ? FALSE : TRUE, TRUE); |
| | | } |
| | | |
| | | // ==== ֪ͨ ==== |
| | | void CCarrierSlotSelector::NotifySelectionChanged(int /*port*/, int /*slot*/, BOOL /*checked*/) |
| | | { |
| | | if (GetParent()) |
| | | { |
| | | const int code = 0x2001; // CSSN_SELECTION_CHANGED |
| | | GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), code), (LPARAM)m_hWnd); |
| | | } |
| | | } |
| | | |
| | | void CCarrierSlotSelector::NotifyMaterialChanged(int /*port*/, int /*slot*/, int /*material*/) |
| | | { |
| | | if (GetParent()) |
| | | { |
| | | const int code = 0x2002; // CSSN_MATERIAL_CHANGED |
| | | GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), code), (LPARAM)m_hWnd); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #pragma once |
| | | |
| | | #include <vector> |
| | | #include <string> |
| | | |
| | | #ifndef _AFX |
| | | #include <afxwin.h> |
| | | #include <afxcmn.h> |
| | | #endif |
| | | |
| | | class CCarrierSlotSelector : public CListCtrl |
| | | { |
| | | public: |
| | | enum MaterialType { MAT_G1 = 1, MAT_G2 = 2 }; |
| | | |
| | | struct SlotCell |
| | | { |
| | | bool hasGlass = false; // æ¯å¦æç |
| | | CString coreId; // åºå®æ ¸å¿IDï¼ä¸å«åç¼ï¼ |
| | | int material = MAT_G1; // ä»
å½±åå±ç¤ºï¼G1/G2ï¼ |
| | | bool checked = false; // æ¯å¦å¾éå å·¥ |
| | | }; |
| | | |
| | | struct PortColumn |
| | | { |
| | | CString portName; // "Port 1" ... |
| | | CString carrierName; // "Carrier A" ... |
| | | bool allocated = false; // æ´åéå® |
| | | CString allocatedBy; // å ç¨è
|
| | | std::vector<SlotCell> slots; // size = m_nSlots |
| | | }; |
| | | |
| | | public: |
| | | CCarrierSlotSelector(); |
| | | virtual ~CCarrierSlotSelector(); |
| | | |
| | | // åå§å / 尺寸 |
| | | void InitGrid(int nPorts, int nSlots); |
| | | void SetColumnWidths(int slotColWidth, int portColWidth); |
| | | void SetRowHeight(int cy); // small image list æ§å¶è¡é« |
| | | |
| | | // å¤è§ |
| | | void SetShowMaterialToggle(BOOL bShow); |
| | | BOOL GetShowMaterialToggle() const { return m_bShowMatToggle; } |
| | | |
| | | // Port æ¥å£ |
| | | int GetPortCount() const { return (int)m_ports.size(); } |
| | | int GetSlotCount() const { return m_nSlots; } |
| | | void SetPortInfo(int portIndex, LPCTSTR portName, LPCTSTR carrierName); |
| | | void SetPortAllocated(int portIndex, BOOL allocated, LPCTSTR byName = nullptr); |
| | | BOOL IsPortAllocated(int portIndex) const; |
| | | |
| | | // Slot æ¥å£ |
| | | void SetSlotGlass(int portIndex, int slotIndex, BOOL hasGlass, LPCTSTR coreId /*å¯ç©º*/, int material /*1=G1,2=G2*/); |
| | | void SetSlotChecked(int portIndex, int slotIndex, BOOL checked); |
| | | BOOL GetSlotChecked(int portIndex, int slotIndex) const; |
| | | |
| | | int GetSlotMaterialType(int portIndex, int slotIndex) const; // 1/2 |
| | | void SetSlotMaterialType(int portIndex, int slotIndex, int material, BOOL bNotify = TRUE); |
| | | |
| | | CString GetDisplayId(int portIndex, int slotIndex) const; // "Gx-core" æ "â" |
| | | void RebuildTexts(); // å头计æ°ãåå
æ ¼ä¸´æ¶ææ¬ |
| | | |
| | | // å·¥å
·ï¼æ´åå
¨é/å
¨ä¸éï¼åªå½±å hasGlass==true çæ ¼åï¼ |
| | | void CheckAllInPort(int portIndex, BOOL checked, BOOL bNotify = TRUE); |
| | | |
| | | protected: |
| | | // å
鍿°æ® |
| | | BOOL m_bFirstShown = FALSE; // å页é¢é¦æ¬¡æ¾ç¤ºå强å¶ä¸æ¬¡å
¨ééç» |
| | | int m_nSlots = 0; |
| | | std::vector<PortColumn> m_ports; |
| | | BOOL m_bShowMatToggle = TRUE; |
| | | |
| | | // UI metrics |
| | | int m_rowHeight = 24; |
| | | int m_slotColWidth = 100; |
| | | int m_portColWidth = 180; |
| | | |
| | | // è¡é«å¾åå表 |
| | | CImageList m_ilRowHeight; |
| | | |
| | | // é¢è² |
| | | COLORREF m_colBgAlt = RGB(240, 242, 245); // 交æ¿åæµ
ç° |
| | | COLORREF m_colBgNorm = RGB(255, 255, 255); |
| | | COLORREF m_colLockBg = RGB(255, 244, 214); // éå®åæ·¡é» |
| | | |
| | | // åä½ |
| | | CFont m_fntText; |
| | | CFont m_fntBold; |
| | | CFont m_fntSmall; |
| | | |
| | | // åºåè®¡ç® |
| | | CRect GetCheckboxRect(const CRect& cell) const; |
| | | CRect GetMaterialTagRect(const CRect& cell) const; |
| | | CRect GetStatusDotRect(const CRect& cell) const; |
| | | |
| | | // å·¥å
· |
| | | void EnsureFonts(); |
| | | void UpdateRowCount(); |
| | | void DrawFlatCheckbox(CDC* pDC, const CRect& r, bool checked, bool disabled); // æå¹³å¤éæ¡ |
| | | |
| | | // éç¥ç¶çªå£ï¼WM_COMMAND 飿 ¼ï¼ |
| | | void NotifySelectionChanged(int port, int slot, BOOL checked); |
| | | void NotifyMaterialChanged(int port, int slot, int material); |
| | | |
| | | protected: |
| | | // MFC |
| | | virtual void PreSubclassWindow() override; |
| | | afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); |
| | | afx_msg void OnWindowPosChanged(WINDOWPOS* lpwndpos); |
| | | afx_msg void OnSize(UINT nType, int cx, int cy); |
| | | afx_msg BOOL OnEraseBkgnd(CDC* pDC); |
| | | afx_msg void OnPaint(); // â
æ°å¢ï¼èªå¸¦åç¼å²ç»å¶ |
| | | afx_msg void OnLButtonDown(UINT nFlags, CPoint point); |
| | | afx_msg void OnMouseMove(UINT nFlags, CPoint point); |
| | | afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); // æè· Header éç¥ |
| | | void OnHeaderClick(int iItem); |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| | |
| | | ON_WM_DESTROY() |
| | | ON_EN_CHANGE(IDC_EDIT_PJ_ID, &CCjPage2::OnEnChangeEditPjId) |
| | | ON_CBN_SELCHANGE(IDC_COMBO_RECIPE, &CCjPage2::OnCbnSelchangeComboRecipe) |
| | | ON_BN_CLICKED(IDC_RADIO1, &CCjPage2::OnBnClickedRadio1) |
| | | ON_BN_CLICKED(IDC_RADIO2, &CCjPage2::OnBnClickedRadio2) |
| | | ON_BN_CLICKED(IDC_RADIO3, &CCjPage2::OnBnClickedRadio3) |
| | | ON_BN_CLICKED(IDC_RADIO4, &CCjPage2::OnBnClickedRadio4) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | UpdatePjData(); |
| | | } |
| | | |
| | | void CCjPage2::SetPjWarps(std::vector<PJWarp>& pjs) |
| | | { |
| | | m_pjWarps = pjs; |
| | | } |
| | | |
| | | BOOL CCjPage2::OnInitDialog() |
| | | { |
| | | CCjPageBase::OnInitDialog(); |
| | | |
| | | |
| | | m_grid.SubclassDlgItem(IDC_GRID1, this); |
| | | m_grid.InitGrid(4, 8); |
| | | m_grid.SetColumnWidths(100, 220); |
| | | m_grid.SetRowHeight(28); |
| | | m_grid.SetHeaderHeight(32); |
| | | m_grid.EnableColumnResize(FALSE); // ç¦æ¢æå¨å宽 |
| | | |
| | | m_grid.SetPortInfo(0, _T("Port 1"), _T("")); |
| | | m_grid.SetPortInfo(1, _T("Port 2"), _T("")); |
| | | m_grid.SetPortInfo(2, _T("Port 3"), _T("")); |
| | | m_grid.SetPortInfo(3, _T("Port 4"), _T("")); |
| | | |
| | | |
| | | UpdatePjData(); |
| | | |
| | | |
| | | ; |
| | | |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | | } |
| | |
| | | void CCjPage2::Resize() |
| | | { |
| | | CCjPageBase::Resize(); |
| | | /* |
| | | |
| | | |
| | | CWnd* pItem; |
| | | CRect rcClient, rcItem; |
| | | GetClientRect(&rcClient); |
| | | pItem = GetDlgItem(IDC_LABEL_TITLE); |
| | | pItem = GetDlgItem(IDC_GRID1); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(12, 8, rcClient.Width() - 24, rcItem.Height()); |
| | | */ |
| | | ScreenToClient(rcItem); |
| | | |
| | | // 让æ§ä»¶çªå£å°ºå¯¸èªå¨å¹é
å½åå宽/è¡æ°ï¼ä¸åºç°æ»å¨æ¡ï¼ |
| | | if (::IsWindow(m_grid.m_hWnd)) { |
| | | CSize best = m_grid.CalcBestWindowSize(TRUE); // 计ç®å°å«é客æ·åºçæç»çªå£å¤§å° |
| | | pItem->MoveWindow(rcItem.left, rcItem.top, best.cx, best.cy); |
| | | pItem->Invalidate(); |
| | | } |
| | | } |
| | | |
| | | void CCjPage2::OnApply() |
| | | { |
| | | //SERVO::CProcessJob* |
| | | if (m_pContext == nullptr) return; |
| | | SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)m_pContext; |
| | | PJWarp* pPjWarp = (PJWarp*)m_pContext; |
| | | SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)pPjWarp->pj; |
| | | |
| | | // æ´æ°åç§° |
| | | BOOL bOkName = TRUE; |
| | | char szBuffer[256]; |
| | | GetDlgItemText(IDC_EDIT_PJ_ID, szBuffer, 256); |
| | | for (auto item : m_pjWarps) { |
| | | if (item.pj != m_pContext) { |
| | | SERVO::CProcessJob* temp = (SERVO::CProcessJob*)item.pj; |
| | | if (temp->id().compare(std::string(szBuffer)) == 0) { |
| | | bOkName = FALSE; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | if (!bOkName) { |
| | | AfxMessageBox("ä¸è½ä½¿ç¨åå
¶å®Process Jobç¸åçID"); |
| | | return; |
| | | } |
| | | |
| | | |
| | | pProcessJob->setId(std::string(szBuffer)); |
| | | |
| | | // æ´æ°é
æ¹ |
| | | CString strRecipe; |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_RECIPE); |
| | | int idx = pComboBox->GetCurSel(); |
| | | if (idx >= 0) { |
| | | pComboBox->GetLBText(idx, strRecipe); |
| | | #ifdef UNICODE |
| | | CT2A utf8Str(strRecipe, CP_UTF8); |
| | | std::string recipe(utf8Str); |
| | | #else |
| | | std::string recipe(strRecipe.GetString()); |
| | | #endif |
| | | |
| | | pProcessJob->setRecipe(SERVO::RecipeMethod::NoTuning, recipe); |
| | | } |
| | | |
| | | |
| | | ContentChanged(1); |
| | | } |
| | |
| | | } |
| | | |
| | | if (m_pContext) { |
| | | SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)m_pContext; |
| | | PJWarp* pPjWarp = (PJWarp*)m_pContext; |
| | | SERVO::CProcessJob* pProcessJob = (SERVO::CProcessJob*)pPjWarp->pj; |
| | | SetDlgItemText(IDC_EDIT_PJ_ID, pProcessJob->id().c_str()); |
| | | int idx = pComboBox->FindStringExact(-1, pProcessJob->recipeSpec().c_str()); |
| | | if (idx != CB_ERR) pComboBox->SetCurSel(idx); |
| | | } |
| | | |
| | | // 示ä¾ï¼è®¾ç½®Portä¿¡æ¯ãéåãå¡«å
Glass |
| | | /* |
| | | m_grid.SetPortInfo(0, _T("Port 1"), _T("")); |
| | | m_grid.SetPortInfo(1, _T("Port 2"), _T("")); |
| | | m_grid.SetPortInfo(2, _T("Port 3"), _T("Carrier C")); |
| | | m_grid.SetPortInfo(3, _T("Port 4"), _T("Carrier D")); |
| | | m_grid.SetPortAllocated(2, TRUE, _T("ProcessJob 1")); |
| | | m_grid.SetSlotGlass(0, 0, TRUE, _T("A00123"), CCarrierSlotGrid::MAT_G1); |
| | | m_grid.SetSlotGlass(0, 1, TRUE, _T("A00124"), CCarrierSlotGrid::MAT_G1); |
| | | */ |
| | | |
| | | m_bContentChangedLock = FALSE; |
| | | } |
| | |
| | | { |
| | | ContentChanged(0); |
| | | } |
| | | |
| | | void CCjPage2::OnBnClickedRadio1() |
| | | { |
| | | m_grid.SetPortAllocated(0, FALSE, _T("")); |
| | | m_grid.SetPortAllocated(1, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(2, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(3, TRUE, _T("")); |
| | | } |
| | | |
| | | void CCjPage2::OnBnClickedRadio2() |
| | | { |
| | | m_grid.SetPortAllocated(0, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(1, FALSE, _T("")); |
| | | m_grid.SetPortAllocated(2, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(3, TRUE, _T("")); |
| | | } |
| | | |
| | | void CCjPage2::OnBnClickedRadio3() |
| | | { |
| | | m_grid.SetPortAllocated(0, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(1, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(2, FALSE, _T("")); |
| | | m_grid.SetPortAllocated(3, TRUE, _T("")); |
| | | } |
| | | |
| | | void CCjPage2::OnBnClickedRadio4() |
| | | { |
| | | m_grid.SetPortAllocated(0, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(1, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(2, TRUE, _T("")); |
| | | m_grid.SetPortAllocated(3, FALSE, _T("")); |
| | | } |
| | |
| | | #pragma once |
| | | #include "CCjPageBase.h" |
| | | #include "ProcessJob.h" |
| | | #include "CCarrierSlotGrid.h" |
| | | |
| | | |
| | | |
| | | struct PJWarp { |
| | | void* pj; |
| | | int port; |
| | | bool checkSlot[8]; |
| | | }; |
| | | |
| | | // CPjPage1 å¯¹è¯æ¡ |
| | | |
| | |
| | | CCjPage2(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CCjPage2(); |
| | | |
| | | public: |
| | | void SetPjWarps(std::vector<PJWarp>& pjs); |
| | | |
| | | protected: |
| | | void Resize(); |
| | | virtual void OnApply(); |
| | |
| | | |
| | | private: |
| | | void UpdatePjData(); |
| | | |
| | | private: |
| | | CCarrierSlotGrid m_grid; |
| | | std::vector<PJWarp> m_pjWarps; |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | |
| | | afx_msg void OnDestroy(); |
| | | afx_msg void OnEnChangeEditPjId(); |
| | | afx_msg void OnCbnSelchangeComboRecipe(); |
| | | afx_msg void OnBnClickedRadio1(); |
| | | afx_msg void OnBnClickedRadio2(); |
| | | afx_msg void OnBnClickedRadio3(); |
| | | afx_msg void OnBnClickedRadio4(); |
| | | }; |
| | |
| | | |
| | | CControlJobManagerDlg::~CControlJobManagerDlg() |
| | | { |
| | | for (auto pj : m_processJobs) { |
| | | delete pj; |
| | | for (auto item : m_pjWarps) { |
| | | delete (SERVO::CProcessJob*)item.pj; |
| | | } |
| | | m_processJobs.clear(); |
| | | m_pjWarps.clear(); |
| | | |
| | | if (m_pControlJob != nullptr) { |
| | | delete m_pControlJob; |
| | |
| | | void CControlJobManagerDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_LIST1, m_listBox); |
| | | DDX_Control(pDX, IDC_TREE1, m_tree); |
| | | } |
| | | |
| | |
| | | BEGIN_MESSAGE_MAP(CControlJobManagerDlg, CDialogEx) |
| | | ON_WM_SIZE() |
| | | ON_WM_GETMINMAXINFO() |
| | | ON_BN_CLICKED(IDC_BUTTON_CREATE_CJ, &CControlJobManagerDlg::OnBnClickedCreateCJ) |
| | | ON_BN_CLICKED(IDC_BUTTON_CREATE_PJ, &CControlJobManagerDlg::OnBnClickedButtonCreatePj) |
| | | ON_CLBN_CHKCHANGE(IDC_LIST1, &CControlJobManagerDlg::OnListChkChange) // å¤éç¶æåæ´éç¥ |
| | | ON_LBN_SELCHANGE(IDC_LIST1, &CControlJobManagerDlg::OnLbnSelchangeList1) |
| | | ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CControlJobManagerDlg::OnTvnSelchangedTree1) |
| | | ON_WM_DESTROY() |
| | | ON_BN_CLICKED(IDC_BUTTON_APPLY, &CControlJobManagerDlg::OnBnClickedButtonApply) |
| | |
| | | } |
| | | else if (1 == code) { |
| | | if (contextType == 1) { |
| | | UpProcessJobId((SERVO::CProcessJob*)pContext); |
| | | UpProcessJobId((PJWarp*)pContext); |
| | | } |
| | | } |
| | | }; |
| | |
| | | m_pages.push_back(pPage3); |
| | | |
| | | |
| | | // ListBox |
| | | m_listBox.ModifyStyle(0, LBS_OWNERDRAWFIXED | LBS_HASSTRINGS); |
| | | m_listBox.SetCheckStyle(BS_AUTOCHECKBOX); |
| | | m_listBox.SetItemHeight(0, max(22, ::GetSystemMetrics(SM_CYMENUCHECK) + 4)); |
| | | // tree |
| | | m_tree.ModifyStyle(0, TVS_CHECKBOXES); |
| | | |
| | | |
| | | InitData(); |
| | | UpdateControlJob(); |
| | | UpdateCtrlState(); |
| | | Resize(); |
| | | |
| | |
| | | |
| | | |
| | | // å
ç§»å¨æé® |
| | | pItem = GetDlgItem(IDC_BUTTON_CREATE_PJ); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x, y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x += rcItem.Width(); |
| | | x += 8; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_CREATE_CJ); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x, y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x += rcItem.Width(); |
| | | x += 8; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_BATH_COMPLETION); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x, y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x += rcItem.Width(); |
| | | x += 8; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_BATH_DELETE); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x, y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x += rcItem.Width(); |
| | | x += 8; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_APPLY); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x2 - rcItem.Width(), y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x2 -= rcItem.Width(); |
| | | x2 -= 8; |
| | | |
| | | pItem = GetDlgItem(IDC_BUTTON_BATH_COMPLETION); |
| | | pItem->GetWindowRect(&rcItem); |
| | | pItem->MoveWindow(x2 - rcItem.Width(), y2 - rcItem.Height(), rcItem.Width(), rcItem.Height()); |
| | | x += rcItem.Width(); |
| | | x += 8; |
| | | |
| | | y2 -= rcItem.Height(); |
| | | y2 -= 8; |
| | | |
| | | |
| | | // å表æ§ä»¶ |
| | | x = 12; |
| | | y = 12; |
| | | pItem = GetDlgItem(IDC_LIST1); |
| | | pItem->MoveWindow(x, y, LEFTWIDTH, 180); |
| | | x += LEFTWIDTH; |
| | | x += 5; |
| | | y += 180; |
| | | y += 5; |
| | | |
| | | |
| | | // æ æ§ä»¶ |
| | | x = 12; |
| | | y = 12; |
| | | pItem = GetDlgItem(IDC_TREE1); |
| | | pItem->MoveWindow(x, y, LEFTWIDTH, y2 - y); |
| | | x += LEFTWIDTH; |
| | |
| | | |
| | | |
| | | // åé¡µé¢ |
| | | x2 = rcClient.right - 12; |
| | | for (auto page : m_pages) { |
| | | page->MoveWindow(x, 12, x2 - x, y2 - 12); |
| | | } |
| | |
| | | void CControlJobManagerDlg::UpdateCtrlState() |
| | | { |
| | | auto& master = theApp.m_model.getMaster(); |
| | | auto cj = master.getControlJob(); |
| | | GetDlgItem(IDC_BUTTON_CREATE_PJ)->EnableWindow(TRUE); |
| | | GetDlgItem(IDC_BUTTON_CREATE_CJ)->EnableWindow( |
| | | m_pControlJob == nullptr |
| | | ); |
| | | GetDlgItem(IDC_BUTTON_BATH_COMPLETION)->EnableWindow(false); |
| | | GetDlgItem(IDC_BUTTON_BATH_DELETE)->EnableWindow(true); |
| | | } |
| | | |
| | | |
| | | void CControlJobManagerDlg::OnBnClickedButtonCreatePj() |
| | | { |
| | | static int index = 0; |
| | | char szBuffer[256]; |
| | | sprintf_s(szBuffer, 256, "PJ%03d", ++index); |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob(std::string(szBuffer)); |
| | | m_processJobs.push_back(pj); |
| | | UpdateProcessJobs(); |
| | | UpdateCtrlState(); |
| | | } |
| | | |
| | | void CControlJobManagerDlg::OnBnClickedCreateCJ() |
| | | { |
| | | if (m_pControlJob != nullptr) { |
| | | return; |
| | | } |
| | | |
| | | m_pControlJob = new SERVO::CControlJob("CJ" + CToolUnits::NowStrSec()); |
| | | UpdateControlJob(); |
| | | UpdateCtrlState(); |
| | | } |
| | | |
| | | void CControlJobManagerDlg::UpdateProcessJobs() |
| | | { |
| | | m_listBox.ResetContent(); |
| | | for (auto item : m_processJobs) { |
| | | int index = m_listBox.InsertString(m_listBox.GetCount(), item->id().c_str()); |
| | | m_listBox.SetItemDataPtr(index, item); |
| | | } |
| | | } |
| | | |
| | | void CControlJobManagerDlg::UpdateControlJob() |
| | |
| | | |
| | | HTREEITEM hRoot = m_tree.InsertItem(m_pControlJob->id().c_str(), 0, 0); |
| | | m_tree.SetItemData(hRoot, (DWORD_PTR)m_pControlJob); |
| | | auto& pjs = m_pControlJob->getPjs(); |
| | | for (auto pj : pjs) { |
| | | HTREEITEM hItem = m_tree.InsertItem(pj->id().c_str(), 0, 0, hRoot); |
| | | m_tree.SetItemData(hItem, (DWORD_PTR)pj); |
| | | m_tree.SetItemState(hRoot, 0, TVIS_STATEIMAGEMASK); |
| | | for (auto& item : m_pjWarps) { |
| | | HTREEITEM hItem = m_tree.InsertItem(((SERVO::CProcessJob*)item.pj)->id().c_str(), 0, 0, hRoot); |
| | | m_tree.SetItemData(hItem, (DWORD_PTR)&item); |
| | | m_tree.SetItemState(hItem, INDEXTOSTATEIMAGEMASK(false ? 2 : 1), TVIS_STATEIMAGEMASK); |
| | | } |
| | | m_tree.Expand(hRoot, TVE_EXPAND); |
| | | } |
| | | |
| | | void CControlJobManagerDlg::OnListChkChange() |
| | | { |
| | | int idx = m_listBox.GetCurSel(); |
| | | if (idx != LB_ERR) { |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)m_listBox.GetItemDataPtr(idx); |
| | | BOOL checked = m_listBox.GetCheck(idx); // è¥ä¸æ: 0/1/2 |
| | | if (checked) { |
| | | if (AddPorcessJob(pj)) { |
| | | UpdateControlJob(); |
| | | } |
| | | } |
| | | else { |
| | | if (RemovePorcessJob(pj)) { |
| | | UpdateControlJob(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | bool CControlJobManagerDlg::AddPorcessJob(SERVO::CProcessJob* pj) |
| | |
| | | { |
| | | if (m_pControlJob == nullptr) return false; |
| | | return m_pControlJob->removePjPointer(pj->id()); |
| | | } |
| | | |
| | | void CControlJobManagerDlg::OnLbnSelchangeList1() |
| | | { |
| | | int idx = m_listBox.GetCurSel(); |
| | | if (idx != LB_ERR) { |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)m_listBox.GetItemDataPtr(idx); |
| | | |
| | | ASSERT(m_pages.size() == 3); |
| | | m_pages[0]->ShowWindow(SW_HIDE); |
| | | m_pages[1]->ShowWindow(SW_SHOW); |
| | | m_pages[2]->ShowWindow(SW_HIDE); |
| | | |
| | | m_pages[1]->SetContext(pj, 1); |
| | | } |
| | | } |
| | | |
| | | void CControlJobManagerDlg::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult) |
| | |
| | | m_pages[2]->ShowWindow(SW_SHOW); |
| | | } |
| | | else if (m_tree.GetParentItem(hParent) == nullptr) { |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)m_tree.GetItemData(hSel); |
| | | PJWarp* pjWarp = (PJWarp*)m_tree.GetItemData(hSel); |
| | | m_pages[0]->ShowWindow(SW_HIDE); |
| | | m_pages[1]->ShowWindow(SW_SHOW); |
| | | m_pages[2]->ShowWindow(SW_HIDE); |
| | | m_pages[1]->SetContext(pjWarp, 1); |
| | | |
| | | m_pages[1]->SetContext(pj, 1); |
| | | ((CCjPage2*)m_pages[1])->SetPjWarps(m_pjWarps); |
| | | } |
| | | else { |
| | | // æç¥å
â 第ä¸å±åä»¥ä¸ â Glass |
| | |
| | | } |
| | | } |
| | | |
| | | void CControlJobManagerDlg::InitData() |
| | | { |
| | | ASSERT(m_pControlJob == nullptr); |
| | | m_pControlJob = new SERVO::CControlJob("CJ" + CToolUnits::NowStrSec()); |
| | | |
| | | char szBuffer[256]; |
| | | for (int i = 0; i < 4; i++) { |
| | | sprintf_s(szBuffer, 256, "PJ%03d", i + 1); |
| | | SERVO::CProcessJob* pj = new SERVO::CProcessJob(std::string(szBuffer)); |
| | | PJWarp pjWarp; |
| | | pjWarp.pj = pj; |
| | | pjWarp.port = -1; |
| | | m_pjWarps.push_back(pjWarp); |
| | | } |
| | | } |
| | | |
| | | void CControlJobManagerDlg::OnBnClickedButtonApply() |
| | | { |
| | |
| | | GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(FALSE); |
| | | } |
| | | |
| | | void CControlJobManagerDlg::UpProcessJobId(SERVO::CProcessJob* pJob) |
| | | void CControlJobManagerDlg::UpProcessJobId(PJWarp* pjWarp) |
| | | { |
| | | int count = m_listBox.GetCount(); |
| | | for (int idx = 0; idx < count; idx++) { |
| | | if ((m_listBox.GetItemDataPtr(idx) == (void*)pJob)) { |
| | | BOOL check = m_listBox.GetCheck(idx); |
| | | BOOL wasCurSel = (m_listBox.GetCurSel() == idx); // å鿍¡å¼ |
| | | m_listBox.DeleteString(idx); |
| | | int newIdx = m_listBox.InsertString(idx, pJob->id().c_str()); |
| | | m_listBox.SetItemDataPtr(newIdx, pJob); |
| | | m_listBox.SetCheck(newIdx, check); |
| | | if (wasCurSel) { |
| | | m_listBox.SetCurSel(newIdx); |
| | | // æ´æ°æ æ§ä»¶ |
| | | // éåæ ¹èç¹ |
| | | HTREEITEM hRoot = m_tree.GetRootItem(); |
| | | while (hRoot) { |
| | | // éå第äºå±åèç¹ |
| | | HTREEITEM hChild = m_tree.GetChildItem(hRoot); |
| | | while (hChild) { |
| | | DWORD_PTR data = m_tree.GetItemData(hChild); |
| | | if ((void*)data == pjWarp) { |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)pjWarp->pj; |
| | | m_tree.SetItemText(hChild, pj->id().c_str()); |
| | | return; // æ¾å°å°±è¿å |
| | | } |
| | | hChild = m_tree.GetNextSiblingItem(hChild); |
| | | } |
| | | |
| | | hRoot = m_tree.GetNextSiblingItem(hRoot); |
| | | } |
| | | } |
| | |
| | | private: |
| | | void Resize(); |
| | | void UpdateCtrlState(); |
| | | void UpdateProcessJobs(); |
| | | void UpdateControlJob(); |
| | | bool AddPorcessJob(SERVO::CProcessJob* pj); |
| | | bool RemovePorcessJob(SERVO::CProcessJob* pj); |
| | | void UpProcessJobId(SERVO::CProcessJob* pJob); |
| | | void UpProcessJobId(PJWarp* pjWarp); |
| | | void InitData(); |
| | | |
| | | private: |
| | | std::vector<CCjPageBase*> m_pages; |
| | | SERVO::CControlJob* m_pControlJob; |
| | | std::vector<SERVO::CProcessJob*> m_processJobs; |
| | | CCheckListBox m_listBox; |
| | | std::vector<PJWarp> m_pjWarps; |
| | | CApredTreeCtrl2 m_tree; |
| | | |
| | | |
| | |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnSize(UINT nType, int cx, int cy); |
| | | afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); |
| | | afx_msg void OnBnClickedCreateCJ(); |
| | | afx_msg void OnBnClickedButtonCreatePj(); |
| | | afx_msg void OnListChkChange(); |
| | | afx_msg void OnLbnSelchangeList1(); |
| | | afx_msg void OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnDestroy(); |
| | | afx_msg void OnBnClickedButtonApply(); |
| | |
| | | |
| | | // ä»é
置读åºçenableï¼åå§åæ¶åç»efem |
| | | static int i_enable[4] = { 0 }; |
| | | if ((++i_enable[m_nIndex]) == 10 + m_nIndex) { |
| | | if ((++i_enable[m_nIndex]) == 20 + m_nIndex) { |
| | | eablePort(m_bEnable, [&](int code) -> int { |
| | | LOGI("<LoadPort-%d>eablePort:code=%d", m_nIndex, code); |
| | | return 0; |
| | |
| | | <ClInclude Include="..\jsoncpp\include\json\writer.h" /> |
| | | <ClInclude Include="..\jsoncpp\lib_json\json_batchallocator.h" /> |
| | | <ClInclude Include="CBaseDlg.h" /> |
| | | <ClInclude Include="CCarrierSlotGrid.h" /> |
| | | <ClInclude Include="CCarrierSlotSelector.h" /> |
| | | <ClInclude Include="CCjPage2.h" /> |
| | | <ClInclude Include="CCjPage3.h" /> |
| | | <ClInclude Include="CCjPageBase.h" /> |
| | |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> |
| | | </ClCompile> |
| | | <ClCompile Include="CBaseDlg.cpp" /> |
| | | <ClCompile Include="CCarrierSlotGrid.cpp" /> |
| | | <ClCompile Include="CCarrierSlotSelector.cpp" /> |
| | | <ClCompile Include="CCjPage2.cpp" /> |
| | | <ClCompile Include="CCjPage3.cpp" /> |
| | | <ClCompile Include="CCjPageBase.cpp" /> |
| | |
| | | <ClCompile Include="CCjPage2.cpp" /> |
| | | <ClCompile Include="CCjPage3.cpp" /> |
| | | <ClCompile Include="CCjPageBase.cpp" /> |
| | | <ClCompile Include="CCarrierSlotSelector.cpp" /> |
| | | <ClCompile Include="CCarrierSlotGrid.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | <ClInclude Include="CCjPage2.h" /> |
| | | <ClInclude Include="CCjPage3.h" /> |
| | | <ClInclude Include="CCjPageBase.h" /> |
| | | <ClInclude Include="CCarrierSlotSelector.h" /> |
| | | <ClInclude Include="CCarrierSlotGrid.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |