#include "stdafx.h" #include "EqsGraphWnd.h" #include "ColorTransfer.h" #include "MapPosWnd.h" #define INPIN 1 #define OUTPIN 2 #define ITEM_CX_SMALL 150 #define ITEM_CY_SMALL 90 #define ITEM_CX_NORMAL 250 #define ITEM_CY_NORMAL 150 #define ITEM_CX_LARGE 400 #define ITEM_CY_LARGE 240 #define HT_NOWHERE 0x1 #define HT_ITEM 0x2 #define HT_PIN 0x4 #define HT_LINE 0x8 #define PINWIDTH 8 #define PINHEIGHT 12 #define TIMER_FLASH 1 #define TIMER_ANIMATION_RECT 2 #define MAPPOSSIZE 150 #define MAPPOSWND_PADDING_RIGHT 12 #define MAPPOSWND_ID 1001 CEqsGraphWnd::CEqsGraphWnd() { m_bUseGdiPlus = TRUE; m_hWnd = NULL; m_crFrame = GetSysColor(COLOR_WINDOWFRAME); m_crBkgnd = RGB(255, 255, 255); m_listener.onConnectPin = nullptr; m_listener.onCheckConnectPin = nullptr; m_listener.onDisconnectPin = nullptr; m_listener.onDeleteEqItem = nullptr; m_listener.onEqItemPosChanged = nullptr; m_listener.onDblckEqItem = nullptr; m_listener.onRclickEqItem = nullptr; m_crItemBackground[0] = RGB(218, 218, 218); m_crItemBackground[1] = RGB(193, 208, 227); m_crItemFrame[0] = RGB(128, 128, 128); m_crItemFrame[1] = RGB(147, 172, 206); m_crItemNameText[0] = RGB(0, 0, 0); m_crItemNameText[1] = RGB(0, 0, 0); m_crItemIdText[0] = CColorTransfer::ApproximateColor(m_crItemNameText[0], -0.3f); m_crItemIdText[1] = m_crItemIdText[0]; m_nCurSel = -1; m_bMultiSelect = FALSE; m_nItemRound = 0; m_pCurItem = NULL; m_pCurPin = NULL; m_pSelLineOutPin = NULL; m_crPinBkgnd[0] = RGB(218, 218, 218); m_crPinBkgnd[1] = RGB(193, 0, 0); m_crPinBkgnd[2] = RGB(193, 0, 0); m_nStageCx = 4000; m_nStageCy = 3000; m_nOffsetX = 0; m_nOffsetY = 0; m_pFlashItem = NULL; m_nFlashCount = 0; m_hWndMapPos = NULL; m_bEnableScroll = FALSE; m_nMagneticLinHoz = 0; m_nMagneticLinVer = 0; m_hFontTitle = nullptr; } CEqsGraphWnd::~CEqsGraphWnd() { ReleaseAllItems(); } BOOL CEqsGraphWnd::RegisterWndClass() { WNDCLASS wc; wc.lpszClassName = EQSGRAPHWND_CLASS; wc.hInstance = AfxGetInstanceHandle(); wc.lpfnWndProc = WindowProc; wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hIcon = 0; wc.lpszMenuName = NULL; wc.hbrBackground = NULL; wc.style = CS_GLOBALCLASS | CS_DBLCLKS; wc.cbClsExtra = 0; wc.cbWndExtra = 0; // ×¢²á´°¿ÚÀà return (::RegisterClass(&wc) != 0); } CEqsGraphWnd* CEqsGraphWnd::FromHandle(HWND hWnd) { CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)::GetProp(hWnd, EQSGRAPHWND_TAG); return pEqsGraphWnd; } CEqsGraphWnd* CEqsGraphWnd::Hook(HWND hWnd) { CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd, EQSGRAPHWND_TAG); if (pEqsGraphWnd == NULL) { pEqsGraphWnd = new CEqsGraphWnd(); pEqsGraphWnd->m_hWnd = hWnd; SetProp(hWnd, EQSGRAPHWND_TAG, (HANDLE)pEqsGraphWnd); } return pEqsGraphWnd; } void CEqsGraphWnd::InitFont() { HDC hDC = GetDC(NULL); HFONT hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT); { LOGFONT lf = { 0 }; ::GetObject(hFont, sizeof(LOGFONT), &lf); m_hFontName = CreateFontIndirect(&lf); } { LOGFONT lf = { 0 }; ::GetObject(hFont, sizeof(LOGFONT), &lf); int nSize = int(-lf.lfHeight * 72.0 / GetDeviceCaps(hDC, LOGPIXELSY) + 0.5); lf.lfHeight = MulDiv(0 - (nSize - 2), GetDeviceCaps(hDC, LOGPIXELSX), 72); m_hFontId = CreateFontIndirect(&lf); } ::ReleaseDC(NULL, hDC); } void CEqsGraphWnd::SetItemRound(int nRound) { m_nItemRound = nRound; } void CEqsGraphWnd::SetDefaultItemBackgroundColor(COLORREF crNormal, COLORREF crSel) { m_crItemBackground[0] = crNormal; m_crItemBackground[1] = crSel; } void CEqsGraphWnd::SetDefaultItemFrameColor(COLORREF crNormal, COLORREF crSel) { m_crItemFrame[0] = crNormal; m_crItemFrame[1] = crSel; } void CEqsGraphWnd::SetDefaultItemTextColor(COLORREF crNormal, COLORREF crSel) { m_crItemNameText[0] = crNormal; m_crItemNameText[1] = crSel; m_crItemIdText[0] = CColorTransfer::ApproximateColor(m_crItemNameText[0], -0.3f); m_crItemIdText[1] = CColorTransfer::ApproximateColor(m_crItemNameText[1], -0.3f); } void CEqsGraphWnd::EnableScroll(BOOL bEnable) { m_bEnableScroll = bEnable; } void CEqsGraphWnd::EnableMultiSelect() { m_bMultiSelect = TRUE; } void CEqsGraphWnd::Init() { InitFont(); CalculateScollbar(); long style = GetWindowLong(m_hWnd, GWL_STYLE); SetWindowLong(m_hWnd, GWL_STYLE, style | WS_CLIPCHILDREN); // MapPosWnd if (m_hWndMapPos == NULL) { m_hWndMapPos = CreateWindowEx(0, MAPPOSWND_CLASS, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 400, 400, m_hWnd, (HMENU)MAPPOSWND_ID, NULL, NULL); long styleex = GetWindowLong(m_hWndMapPos, GWL_EXSTYLE); SetWindowLong(m_hWndMapPos, GWL_EXSTYLE, styleex | WS_EX_CLIENTEDGE); CMapPosWnd *pMapPosWnd = CMapPosWnd::FromHandle(m_hWndMapPos); pMapPosWnd->SetWndMaxSize(MAPPOSSIZE); pMapPosWnd->SetStageSize(m_nStageCx, m_nStageCy, TRUE); } } void CEqsGraphWnd::CalculateMapPos() { CRect rcClient; GetClientRect(m_hWnd, &rcClient); ::OffsetRect(&rcClient, m_nOffsetX, m_nOffsetY); CMapPosWnd *pMapPosWnd = CMapPosWnd::FromHandle(m_hWndMapPos); pMapPosWnd->SetViewPort(&rcClient, TRUE); } void CEqsGraphWnd::CalculateScollbar() { RECT rcClient; GetClientRect(m_hWnd, &rcClient); // vert scroll if(m_bEnableScroll) { SCROLLINFO scrinffo; scrinffo.cbSize = sizeof(SCROLLINFO); scrinffo.fMask = SIF_ALL; scrinffo.nMax = m_nStageCy; scrinffo.nMin = 0; scrinffo.nPos = m_nOffsetY; scrinffo.nTrackPos = 0; scrinffo.nPage = rcClient.bottom - rcClient.top; SetScrollInfo(m_hWnd, SB_VERT, &scrinffo, TRUE); } // horz scroll if (m_bEnableScroll) { SCROLLINFO scrinffo; scrinffo.cbSize = sizeof(SCROLLINFO); scrinffo.fMask = SIF_ALL; scrinffo.nMax = m_nStageCx; scrinffo.nMin = 0; scrinffo.nPos = m_nOffsetX; scrinffo.nTrackPos = 0; scrinffo.nPage = rcClient.right - rcClient.left; SetScrollInfo(m_hWnd, SB_HORZ, &scrinffo, TRUE); } } /* * ¼ÆËã´ÅÁ¦ÏßλÖà */ void CEqsGraphWnd::CalculateMagneticLine(EQITEM* pItem, LPRECT lprcItemRect, int &hoz, int &ver) { hoz = 0; ver = 0; #define MAGNETIC_DIS 10 // ¼ì²âÊÇ·ñ½Ó½ü»ò¶ÔÆë for (int i = 0; i < m_arItem.GetSize(); i++) { EQITEM *pTemp = (EQITEM*)m_arItem.GetAt(i); if (pTemp != pItem) { if (abs(lprcItemRect->left - pTemp->rect.left) < MAGNETIC_DIS) { ver = pTemp->rect.left; break; } else if (abs(lprcItemRect->right - pTemp->rect.right) < MAGNETIC_DIS) { ver = pTemp->rect.right - (lprcItemRect->right- lprcItemRect->left); break; } } } for (int i = 0; i < m_arItem.GetSize(); i++) { EQITEM* pTemp = (EQITEM*)m_arItem.GetAt(i); if (pTemp != pItem) { if (abs(lprcItemRect->top - pTemp->rect.top) < MAGNETIC_DIS) { hoz = pTemp->rect.top; break; } else if (abs(lprcItemRect->bottom - pTemp->rect.bottom) < MAGNETIC_DIS) { hoz = pTemp->rect.bottom - (lprcItemRect->bottom - lprcItemRect->top); break; } } } } void CEqsGraphWnd::Release() { ::DeleteObject(m_hFontName); ::DeleteObject(m_hFontId); if (m_hFontTitle != nullptr) { ::DeleteObject(m_hFontTitle); } // delete delete this; } /* * È¡µÃIn PinµÄÇøÓò * pItem -- EQITEM * lpRect -- µÃµ½µÄRect * ·µ»ØÊÇ·ñ³É¹¦ */ BOOL CEqsGraphWnd::GetItemRect(EQITEM* pItem, LPRECT lpRect) { ASSERT(pItem); if (pItem == m_pAnimationItem) { lpRect->left = (int)(m_rcAnimation.left - m_nOffsetX); lpRect->top = (int)(m_rcAnimation.top - m_nOffsetY); lpRect->right = (int)(m_rcAnimation.right - m_nOffsetX); lpRect->bottom = (int)(m_rcAnimation.bottom - m_nOffsetY); } else { lpRect->left = (int)(pItem->rect.left - m_nOffsetX); lpRect->top = (int)(pItem->rect.top - m_nOffsetY); lpRect->right = (int)(pItem->rect.right - m_nOffsetX); lpRect->bottom = (int)(pItem->rect.bottom - m_nOffsetY); } return TRUE; } BOOL CEqsGraphWnd::GetItemWarperRect(EQITEM* pItem, LPRECT lpRect) { CopyRect(lpRect, &pItem->rect); lpRect->left -= PINWIDTH; lpRect->right += PINWIDTH; return TRUE; } /* * È¡µÃIn PinµÄÇøÓò * pItem -- EQITEM * nPinIndex -- in pinË÷Òý * lpRect -- µÃµ½µÄRect * ·µ»ØÊÇ·ñ³É¹¦ */ BOOL CEqsGraphWnd::GetInPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect) { CPtrArray * pPins = (CPtrArray *)pItem->pInPins; if (nPinIndex >= pPins->GetSize()) { return FALSE; } int nBottomMargin = pPins->GetCount() >= 4 ? 8 : 0; int nSpace = ((pItem->rect.bottom - nBottomMargin - pItem->rect.top) - (int)pPins->GetSize() * PINHEIGHT) / (pPins->GetSize() + 1); lpRect->right = pItem->rect.left+1 - m_nOffsetX; lpRect->left = lpRect->right - PINWIDTH; lpRect->bottom = pItem->rect.top + (nSpace + PINHEIGHT) * (nPinIndex+1) - m_nOffsetY; lpRect->top = lpRect->bottom - PINHEIGHT; return TRUE; } /* * È¡µÃOut PinµÄÇøÓò * pItem -- EQITEM * nPinIndex -- in pinË÷Òý * lpRect -- µÃµ½µÄRect * ·µ»ØÊÇ·ñ³É¹¦ */ BOOL CEqsGraphWnd::GetOutPinRect(EQITEM* pItem, int nPinIndex, LPRECT lpRect) { CPtrArray * pPins = (CPtrArray *)pItem->pOutPins; if (nPinIndex >= pPins->GetSize()) { return FALSE; } int nSpace = ((pItem->rect.bottom - pItem->rect.top) - (int)pPins->GetSize() * PINHEIGHT) / (pPins->GetSize() + 1); lpRect->left = pItem->rect.right-1 - m_nOffsetX; lpRect->right = lpRect->left + PINWIDTH; lpRect->bottom = pItem->rect.top + (nSpace + PINHEIGHT) * (nPinIndex + 1) - m_nOffsetY; lpRect->top = lpRect->bottom - PINHEIGHT; return TRUE; } /* * È¡µÃPinµÄPoint * pItem -- EQITEM * nPinIndex -- in pinË÷Òý * lpRect -- µÃµ½µÄRect * ·µ»ØÊÇ·ñ³É¹¦ */ BOOL CEqsGraphWnd::GetPinPoint(PIN *pPin, LPPOINT lpPoint) { ASSERT(pPin); ASSERT(pPin->pItem); CPtrArray * pPins; RECT rcPin; // in pin? pPins = (CPtrArray *)pPin->pItem->pInPins; for(int i=0; iGetCount(); i++) { if (pPins->GetAt(i) == pPin) { if (GetInPinRect(pPin->pItem, i, &rcPin)) { lpPoint->x = rcPin.left + (rcPin.right - rcPin.left) / 2; lpPoint->y = rcPin.top + (rcPin.bottom - rcPin.top) / 2; return TRUE; } } } // out pin? pPins = (CPtrArray *)pPin->pItem->pOutPins; for (int i = 0; iGetCount(); i++) { if (pPins->GetAt(i) == pPin) { if (GetOutPinRect(pPin->pItem, i, &rcPin)) { lpPoint->x = rcPin.left + (rcPin.right - rcPin.left) / 2; lpPoint->y = rcPin.top + (rcPin.bottom - rcPin.top) / 2; return TRUE; } } } return FALSE; } void CEqsGraphWnd::ReleaseItem(EQITEM* pItem) { ASSERT(pItem); CPtrArray *pArray = (CPtrArray *)pItem->pInPins; for (int j = 0; j < pArray->GetSize(); j++) { PIN *pPin = (PIN *)pArray->GetAt(j); if (pPin->pConnectedPin != NULL) { pPin->pConnectedPin->pConnectedPin = NULL; } delete pPin; } delete pArray; pArray = (CPtrArray *)pItem->pOutPins; for (int j = 0; j < pArray->GetSize(); j++) { PIN *pPin = (PIN *)pArray->GetAt(j); if (pPin->pConnectedPin != NULL) { pPin->pConnectedPin->pConnectedPin = NULL; } delete pPin; } delete pArray; delete pItem; } void CEqsGraphWnd::ReleaseAllItems() { for (int i = 0; i < m_arItem.GetCount(); i++) { ReleaseItem((EQITEM*)m_arItem.GetAt(i)); } m_arItem.RemoveAll(); } int CEqsGraphWnd::GetPinState(PIN *pPin) { if (pPin == m_pCurPin) { return 1; } return 0; } /* * Çå¿ÕPINÁ¬½ÓÏß»º´æµã£¬ÒÔ±ãÖØÐ¼ÆËãºÍ»æÖÆ */ void CEqsGraphWnd::ClearConnectedLinePoint(EQITEM*& pItem) { ASSERT(pItem); CPtrArray *pPins; PIN *pPin; pPins = (CPtrArray *)pItem->pInPins; for (int j = 0; j < pPins->GetSize(); j++) { pPin = (PIN *)pPins->GetAt(j); if (pPin->pConnectedPin != NULL) { pPin->pConnectedPin->nLinePtCount = 0; } } pPins = (CPtrArray *)pItem->pOutPins; for (int j = 0; j < pPins->GetSize(); j++) { pPin = (PIN *)pPins->GetAt(j); pPin->nLinePtCount = 0; } } void CEqsGraphWnd::SetOnListener(EqsGraphListener& listener) { m_listener.onConnectPin = listener.onConnectPin; m_listener.onCheckConnectPin = listener.onCheckConnectPin; m_listener.onDisconnectPin = listener.onDisconnectPin; m_listener.onDeleteEqItem = listener.onDeleteEqItem; m_listener.onEqItemPosChanged = listener.onEqItemPosChanged; m_listener.onDblckEqItem = listener.onDblckEqItem; m_listener.onRclickEqItem = listener.onRclickEqItem; } BOOL CEqsGraphWnd::SetCurSel(int nSel) { if (!(nSel == -1 || nSel < m_arItem.GetCount())) { return FALSE; } m_nCurSel = nSel; RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return TRUE; } BOOL CEqsGraphWnd::SetCurSel(CString strItemName) { int nIndex = -1; for (int i = 0; i < m_arItem.GetCount(); i++) { EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i); if (strItemName.Compare(pItem->text) == 0) { nIndex = i; break; } } if (nIndex == -1) { return FALSE; } m_nCurSel = nIndex; RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return TRUE; } BOOL CEqsGraphWnd::SetCurSel(DWORD_PTR pData) { int nIndex = -1; for (int i = 0; i < m_arItem.GetCount(); i++) { EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i); if (pItem->pData == pData) { nIndex = i; break; } } if (nIndex == -1) { return FALSE; } m_nCurSel = nIndex; RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return TRUE; } /* * nType: ITEM_SMALL, ITEM_NORMAL or ITEM_LARGE */ EQITEM* CEqsGraphWnd::AddItem(int id, CString strText, DWORD_PTR dwData, int nType/* = ITEM_NORMAL*/) { // ÐèÒª¼ÆËãÒ»¸öÐÂλÖ㬲»È»È«²¿ÖصþÔÚÒ»Æð int x, y; x = (m_arItem.GetCount() % 4) * 218; y = (m_arItem.GetCount() / 4) * 168; EQITEM* pItem = new EQITEM; memset(pItem, 0, sizeof(EQITEM)); pItem->id = id; pItem->nShowType = nType; pItem->rect.left = x + 20 + m_nOffsetX; pItem->rect.top = y + 50 + m_nOffsetY; if (pItem->nShowType == ITEM_SMALL) { pItem->rect.right = pItem->rect.left + ITEM_CX_SMALL; pItem->rect.bottom = pItem->rect.top + ITEM_CY_SMALL; } else if(pItem->nShowType == ITEM_LARGE){ pItem->rect.right = pItem->rect.left + ITEM_CX_LARGE; pItem->rect.bottom = pItem->rect.top + ITEM_CY_LARGE; } else { pItem->rect.right = pItem->rect.left + ITEM_CX_NORMAL; pItem->rect.bottom = pItem->rect.top + ITEM_CY_NORMAL; } pItem->pData = dwData; pItem->pInPins = (DWORD_PTR)new CPtrArray(); pItem->pOutPins = (DWORD_PTR)new CPtrArray(); int len = min(63, strText.GetLength()); memcpy(pItem->text, (LPTSTR)(LPCTSTR)strText, len); pItem->text[len] = '\0'; m_arItem.Add(pItem); RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return pItem; } void CEqsGraphWnd::RemoveItem(EQITEM* pItem) { BOOL bChanged = FALSE; if (m_listener.onDeleteEqItem != NULL) { if (m_listener.onDeleteEqItem(m_pCurItem)) { bChanged = DeleteItem(m_pCurItem) >= 0; } } if (bChanged) { if (pItem == m_pCurItem) { m_pCurItem = NULL; } RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } } void CEqsGraphWnd::SetItemText(EQITEM* pItem, CString strText) { int len = min(63, strText.GetLength()); memcpy(pItem->text, (LPTSTR)(LPCTSTR)strText, len); pItem->text[len] = '\0'; ::InvalidateRect(m_hWnd, &pItem->rect, TRUE); } void CEqsGraphWnd::SetItemType(EQITEM* pItem, int nType) { pItem->nShowType = nType; if (pItem->nShowType == ITEM_SMALL) { pItem->rect.right = pItem->rect.left + ITEM_CX_SMALL; pItem->rect.bottom = pItem->rect.top + ITEM_CY_SMALL; } else if (pItem->nShowType == ITEM_LARGE) { pItem->rect.right = pItem->rect.left + ITEM_CX_LARGE; pItem->rect.bottom = pItem->rect.top + ITEM_CY_LARGE; } else { pItem->rect.right = pItem->rect.left + ITEM_CX_NORMAL; pItem->rect.bottom = pItem->rect.top + ITEM_CY_NORMAL; } ::InvalidateRect(m_hWnd, &pItem->rect, TRUE); } PIN * CEqsGraphWnd::AddPin(EQITEM* pItem, int nType, CString strName, DWORD_PTR dwData) { ASSERT(pItem); ASSERT(nType == INPIN || nType == OUTPIN); ASSERT(pItem->pInPins); ASSERT(pItem->pOutPins); PIN *pPin = new PIN; memset(pPin, 0, sizeof(PIN)); pPin->pItem = pItem; pPin->nIndex = nType == INPIN ? ((CPtrArray *)pItem->pInPins)->GetSize() : ((CPtrArray *)pItem->pOutPins)->GetSize(); pPin->nType = nType; pPin->pData = dwData; int len = MIN(sizeof(pPin->text), strName.GetLength()); memcpy(pPin->text, (LPTSTR)(LPCTSTR)strName, len); pPin->text[len] = '\0'; CPtrArray *pArray = NULL; if (nType == INPIN) { pArray = (CPtrArray *)pItem->pInPins; } else { pArray = (CPtrArray *)pItem->pOutPins; } ASSERT(pItem->pOutPins); pArray->Add(pPin); return pPin; } EQITEM* CEqsGraphWnd::GetItem(DWORD_PTR dwData) { for (int i = 0; i < m_arItem.GetCount(); i++) { EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i); if (pItem->pData == dwData) { return pItem; } } return NULL; } PIN * CEqsGraphWnd::GetPin(DWORD_PTR dwItemData, DWORD_PTR dwPinData) { EQITEM* pItem = GetItem(dwItemData); if (pItem != NULL) { CPtrArray *pArray = (CPtrArray *)pItem->pInPins; for (int i = 0; i < pArray->GetCount(); i++) { PIN *pPin = (PIN *)pArray->GetAt(i); if (pPin->pData == dwPinData) { return pPin; } } pArray = (CPtrArray *)pItem->pOutPins; for (int i = 0; i < pArray->GetCount(); i++) { PIN *pPin = (PIN *)pArray->GetAt(i); if (pPin->pData == dwPinData) { return pPin; } } } return NULL; } int CEqsGraphWnd::ConnectPin(DWORD_PTR dwItem1Data, DWORD_PTR dwPin1Data, DWORD_PTR dwItem2Data, DWORD_PTR dwPin2Data) { PIN *pPin1, *pPin2; pPin1 = GetPin(dwItem1Data, dwPin1Data); if (pPin1 == NULL) { return -1; } pPin2 = GetPin(dwItem2Data, dwPin2Data); if (pPin2 == NULL) { return -2; } pPin1->pConnectedPin = pPin2; pPin2->pConnectedPin = pPin1; return 0; } // ɾ³ýItem, Èç¹ûpinÓÐÁ¬½Ó£¬×¢ÒâÏȶϿª int CEqsGraphWnd::DeleteItem(EQITEM* pItem) { for (int i = 0; i < m_arItem.GetSize(); i++) { if (pItem == (EQITEM*)m_arItem.GetAt(i)) { m_arItem.RemoveAt(i); ReleaseItem(pItem); return 0; } } return -1; } void CEqsGraphWnd::DeleteAllItems() { ReleaseAllItems(); RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } void CEqsGraphWnd::SetCurrentItem(EQITEM* pItem) { if (m_pCurItem != NULL) { m_pCurItem->bHighlight = FALSE; } m_pCurItem = pItem; if (m_pCurItem != NULL) { m_pCurItem->bHighlight = TRUE; } RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } /* * ÉèÖÃ×ÓÏîµÄÑ¡ÖÐ״̬ */ void CEqsGraphWnd::SetItemSelectState(int nIndex, BOOL bSelect) { if (nIndex >= m_arItem.GetCount()) { return; } EQITEM *pItem = (EQITEM*)m_arItem.GetAt(nIndex); pItem->bHighlight = bSelect; RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } void CEqsGraphWnd::Notify(int nCode, int dwData, int dwData1/* = 0*/, int dwData2/* = 0*/) { HWND hParent; hParent = GetParent(m_hWnd); if (hParent != NULL) { EQSGRAPHWND_NMHDR nmhdr; nmhdr.nmhdr.hwndFrom = m_hWnd; nmhdr.nmhdr.idFrom = GetWindowLong(m_hWnd, GWL_ID); nmhdr.nmhdr.code = nCode; nmhdr.dwData = dwData; nmhdr.dwData1 = dwData1; nmhdr.dwData2 = dwData2; SendMessage(hParent, WM_NOTIFY, (WPARAM)nmhdr.nmhdr.idFrom, (LPARAM)&nmhdr); } } /* * ¼ì²â×ø±êµãËùÔÚµÄÏî * ·µ»ØÏîÀàÐÍ, ÈçHT_ITEM, HT_PIN, HT_LINE * pItem - ËùÔÚµÄEQITEM * pPin --ËùÔÚµÄpin, Èç¹ûÔÚÁ¬ÏßÉÏ£¬±íʾËùÊôpin, out pin£» */ int CEqsGraphWnd::HighTest(POINT pt, OUT EQITEM*& pItem, OUT PIN *& pPin) { // ¼ì²âÊÇ·ñÔÚij¸ö×ÓÏî int nRet = HT_NOWHERE; pItem = NULL; pPin = NULL; RECT rcItem; for (int i = m_arItem.GetSize() - 1; i >= 0 ; i--) { EQITEM *pTempItem = (EQITEM*)m_arItem.GetAt(i); GetItemRect(pTempItem, &rcItem); if (::PtInRect(&rcItem, pt)) { // ÔÚItem pItem = pTempItem; nRet = HT_ITEM; break; } else { RECT rcPin; CPtrArray * pPins = (CPtrArray *)pTempItem->pInPins; for (int j = 0; j < pPins->GetSize(); j++) { if (GetInPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) { // ÔÚin pinÉÏ pPin = (PIN *)pPins->GetAt(j); pItem = pTempItem; nRet = HT_PIN; break; } } if (nRet == HT_NOWHERE) { pPins = (CPtrArray *)pTempItem->pOutPins; for (int j = 0; j < pPins->GetSize(); j++) { if (GetOutPinRect(pTempItem, j, &rcPin) && ::PtInRect(&rcPin, pt)) { // ÔÚout pin pPin = (PIN *)pPins->GetAt(j); pItem = pTempItem; nRet = HT_PIN; break; } else { // ÊÇ·ñÔÚpinÁ¬½ÓÏßÉÏ,¼´ÅжϵãÊÇ·ñÔÚÏßÉÏ // µãµ½Ö±ÏߵľàÀ빫ʽ£¨ÏÈͨ¹ýp1,p2ÓÃÁ½µãʽÇó³öÖ±Ïߵıí´ïʽ£¬ÔÙÌ×¾àÀ빫ʽ£©£»abs()Ϊȡ¾ø¶ÔÖµº¯Êý£¬sqrt()Ϊ¿ª¸ùºÅº¯Êý PIN *pTempPin = (PIN *)pPins->GetAt(j); if (pTempPin->pConnectedPin != NULL && pTempPin->nLinePtCount > 1) { for (int i = 0; i < pTempPin->nLinePtCount - 1; i++) { double distance = PointToSegDist(pt.x + m_nOffsetX, pt.y + m_nOffsetY, pTempPin->ptConnectedLine[i].x, pTempPin->ptConnectedLine[i].y, pTempPin->ptConnectedLine[i+1].x, pTempPin->ptConnectedLine[i+1].y); if (distance < 5.0) { nRet = HT_LINE; pPin = pTempPin; break; } } if (nRet == HT_LINE) { break; } } } } } if (nRet != HT_NOWHERE) { break; } } } return nRet; } /* * »æÖÆÐéÏß¿ò£¬´ú±íÕýÔÚÍ϶¯µÄitem */ void CEqsGraphWnd::DrawDropItemRectangle(LPRECT lpRect1, LPRECT lpRect2) { HDC hDC = GetDC(m_hWnd); HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255)); HPEN hPen = CreatePen(PS_DASH, 1, RGB(0, 0, 0)); int oldRop = SetROP2(hDC, R2_NOTXORPEN); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush); HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen); if (lpRect1 != NULL) { ::Rectangle(hDC, lpRect1->left, lpRect1->top, lpRect1->right, lpRect1->bottom); } if (lpRect2 != NULL) { ::Rectangle(hDC, lpRect2->left, lpRect2->top, lpRect2->right, lpRect2->bottom); } ::SetROP2(hDC, oldRop); ::SelectObject(hDC, hOldBrush); ::SelectObject(hDC, hPen); ::DeleteObject(hBrush); ::DeleteObject(hOldPen); ::ReleaseDC(m_hWnd, hDC); } /* * »æÖÆ´ÅÎüÏß */ void CEqsGraphWnd::DrawMagneticLine(LPRECT lprcClient, int nHozLine1, int nHozLine2, int nVerLine1, int nVerLine2) { HDC hDC = GetDC(m_hWnd); HPEN hPen = CreatePen(PS_DASH, 1, RGB(64, 64, 64)); int oldRop = SetROP2(hDC, R2_NOTXORPEN); HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen); if (nHozLine1) { ::MoveToEx(hDC, 1, nHozLine1, NULL); ::LineTo(hDC, lprcClient->right-1, nHozLine1); } if (nHozLine2) { ::MoveToEx(hDC, 1, nHozLine2, NULL); ::LineTo(hDC, lprcClient->right - 1, nHozLine2); } if (nVerLine1) { ::MoveToEx(hDC, nVerLine1, 1, NULL); ::LineTo(hDC, nVerLine1, lprcClient->bottom - 1); } if (nVerLine2) { ::MoveToEx(hDC, nVerLine2, 1, NULL); ::LineTo(hDC, nVerLine2, lprcClient->bottom - 1); } ::SetROP2(hDC, oldRop); ::SelectObject(hDC, hPen); ::DeleteObject(hOldPen); ::ReleaseDC(m_hWnd, hDC); } /* * »ºÖÆPinÁ¬½ÓÏß * pBrush -- »­Ë¢ * pPen - »­±Ê * lpPt1, lpPt2 -- Pin½ÅµÄλÖà * lpRect1, lpRect2 -- Á½¸öItemµÄRect */ void CEqsGraphWnd::DrawPinConnectedLine(Gdiplus::Graphics *pGraphics, Gdiplus::Brush *pBrush, Gdiplus::Pen *pPen, LPPOINT lpPt1, LPPOINT lpPt2, LPRECT lpRect1, LPRECT lpRect2, PIN *pOwnerPin) { // Èç¹ûûÓлº´æÏßÌõµÄPOINT£¬ÔòÏȼÆËã²¢»º´æ ASSERT(pOwnerPin); int nPinCount = ((CPtrArray*)pOwnerPin->pItem->pOutPins)->GetSize(); int nArrowLen = 8; int nStartMinX = 8; int nMargin = 12; int x1, x2, y1; if (pOwnerPin->nLinePtCount == 0) { // µÚÒ»¸öµãµÄ×îСÕÛÏß³¤ ::OffsetRect(lpRect1, +m_nOffsetX, +m_nOffsetY); ::OffsetRect(lpRect2, +m_nOffsetX, +m_nOffsetY); lpPt1->x += m_nOffsetX; // Ïû³ýÆ«ÒÆ lpPt1->y += m_nOffsetY; lpPt2->x += m_nOffsetX; lpPt2->y += m_nOffsetY; int nMinX = 10 + nMargin * nPinCount + nArrowLen; int xEnd = lpPt2->x - 5; x1 = lpPt1->x + 10 + pOwnerPin->nIndex * nMargin; if (lpPt2->x - lpPt1->x > nMinX) { pOwnerPin->ptConnectedLine[0].x = lpPt1->x; pOwnerPin->ptConnectedLine[0].y = lpPt1->y; pOwnerPin->ptConnectedLine[1].x = x1; pOwnerPin->ptConnectedLine[1].y = lpPt1->y; pOwnerPin->ptConnectedLine[2].x = x1; pOwnerPin->ptConnectedLine[2].y = lpPt2->y; pOwnerPin->ptConnectedLine[3].x = xEnd; pOwnerPin->ptConnectedLine[3].y = lpPt2->y; pOwnerPin->nLinePtCount = 4; } else if (lpRect1 != NULL && lpRect2 != NULL) { if (lpRect2->top - lpRect1->bottom > 20 || lpRect1->top - lpRect2->bottom > 20) { if (lpRect2->top - lpRect1->bottom > 20) { y1 = lpRect1->bottom + 10 + pOwnerPin->nIndex * nMargin; x2 = min(lpPt2->x - nArrowLen, x1) - (nPinCount - pOwnerPin->nIndex) * nMargin; } else { y1 = lpRect1->top - 10 - pOwnerPin->nIndex * nMargin; x2 = min(lpPt2->x - nArrowLen, x1) - (nPinCount - pOwnerPin->nIndex) * nMargin; } pOwnerPin->ptConnectedLine[0].x = lpPt1->x; pOwnerPin->ptConnectedLine[0].y = lpPt1->y; pOwnerPin->ptConnectedLine[1].x = x1; pOwnerPin->ptConnectedLine[1].y = lpPt1->y; pOwnerPin->ptConnectedLine[2].x = x1; pOwnerPin->ptConnectedLine[2].y = y1; pOwnerPin->ptConnectedLine[3].x = x2; pOwnerPin->ptConnectedLine[3].y = y1; pOwnerPin->ptConnectedLine[4].x = x2; pOwnerPin->ptConnectedLine[4].y = lpPt2->y; pOwnerPin->ptConnectedLine[5].x = xEnd; pOwnerPin->ptConnectedLine[5].y = lpPt2->y; pOwnerPin->nLinePtCount = 6; } else { x2 = min(lpRect1->left, lpRect2->left) - 30; y1 = max(lpRect1->bottom, lpRect2->bottom) + 30; pOwnerPin->ptConnectedLine[0].x = lpPt1->x; pOwnerPin->ptConnectedLine[0].y = lpPt1->y; pOwnerPin->ptConnectedLine[1].x = x1; pOwnerPin->ptConnectedLine[1].y = lpPt1->y; pOwnerPin->ptConnectedLine[2].x = x1; pOwnerPin->ptConnectedLine[2].y = y1; pOwnerPin->ptConnectedLine[3].x = x2; pOwnerPin->ptConnectedLine[3].y = y1; pOwnerPin->ptConnectedLine[4].x = x2; pOwnerPin->ptConnectedLine[4].y = lpPt2->y; pOwnerPin->ptConnectedLine[5].x = xEnd; pOwnerPin->ptConnectedLine[5].y = lpPt2->y; pOwnerPin->nLinePtCount = 6; } } } if (pOwnerPin->nLinePtCount >= 2) { for (int i = 0; i < pOwnerPin->nLinePtCount - 1; i++) { pGraphics->DrawLine(pPen, pOwnerPin->ptConnectedLine[i].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i].y - m_nOffsetY, pOwnerPin->ptConnectedLine[i + 1].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i + 1].y - m_nOffsetY); } DrawArrow(pGraphics, pBrush, pPen, pOwnerPin->ptConnectedLine[pOwnerPin->nLinePtCount-1].x - m_nOffsetX, pOwnerPin->ptConnectedLine[pOwnerPin->nLinePtCount-1].y - m_nOffsetY, nArrowLen); } } void CEqsGraphWnd::DrawArrow(Gdiplus::Graphics *pGraphics, Gdiplus::Brush* pBrush, Gdiplus::Pen *pPen, int x, int y, int nArrowLen) { Gdiplus::Point pt[4]; pt[0].X = x; pt[0].Y = y; pt[1].X = x - nArrowLen; pt[1].Y = y - 3; pt[2].X = pt[1].X; pt[2].Y = y + 3; pt[3].X = x; pt[3].Y = y; pGraphics->FillPolygon(pBrush, pt, 4); pGraphics->DrawPolygon(pPen, pt, 4); } void CEqsGraphWnd::DrawPinWillConnectLine(COLORREF color, LPPOINT lpPt1, LPPOINT lpPt2) { HDC hDC = GetDC(m_hWnd); HPEN hPen = CreatePen(PS_SOLID, 2, color); int oldRop = SetROP2(hDC, R2_NOTXORPEN); HBRUSH hOldPen = (HBRUSH)::SelectObject(hDC, hPen); if (lpPt1 != NULL && lpPt2 != NULL) { ::MoveToEx(hDC, lpPt1->x, lpPt1->y, NULL); ::LineTo(hDC, lpPt2->x, lpPt2->y); } ::SetROP2(hDC, oldRop); ::SelectObject(hDC, hPen); ::DeleteObject(hOldPen); ::ReleaseDC(m_hWnd, hDC); } /* * WindowProc£¬´°¿Ú¹ý³Ì */ LRESULT CALLBACK CEqsGraphWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd, EQSGRAPHWND_TAG); if (pEqsGraphWnd == NULL && uMsg != WM_NCCREATE) { return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } // ´¦Àí´°¿ÚÏûÏ¢ ASSERT(hWnd); switch (uMsg) { case WM_NCCREATE: return CEqsGraphWnd::OnNcCreate(hWnd, wParam, lParam); case WM_DESTROY: return pEqsGraphWnd->OnDestroy(wParam, lParam); case WM_NCPAINT: return pEqsGraphWnd->OnNcPaint(wParam, lParam); case WM_PAINT: return pEqsGraphWnd->OnPaint(wParam, lParam); case WM_TIMER: return pEqsGraphWnd->OnTimer(wParam, lParam); case WM_MOUSEMOVE: return pEqsGraphWnd->OnMouseMove(wParam, lParam); case WM_LBUTTONDOWN: return pEqsGraphWnd->OnLButtonDown(wParam, lParam); case WM_RBUTTONDOWN: return pEqsGraphWnd->OnRButtonDown(wParam, lParam); case WM_LBUTTONDBLCLK: return pEqsGraphWnd->OnLButtonDblclk(wParam, lParam); case WM_MOUSEWHEEL: return pEqsGraphWnd->OnMouseWheel(wParam, lParam); case WM_MOUSEHWHEEL: return pEqsGraphWnd->OnMouseHWheel(wParam, lParam); case WM_KEYDOWN: return pEqsGraphWnd->OnKeyDown(wParam, lParam); case WM_SIZE: return pEqsGraphWnd->OnSize(wParam, lParam); case WM_VSCROLL: return pEqsGraphWnd->OnVScroll(wParam, lParam); case WM_HSCROLL: return pEqsGraphWnd->OnHScroll(wParam, lParam); case WM_NOTIFY: return pEqsGraphWnd->OnNitify(wParam, lParam); case WM_GETDLGCODE: return DLGC_WANTALLKEYS; default: break; } return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } /* * WM_NCCREATE * ´°¿Ú´´½¨ */ LRESULT CEqsGraphWnd::OnNcCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) { CEqsGraphWnd* pEqsGraphWnd = (CEqsGraphWnd*)GetProp(hWnd,EQSGRAPHWND_TAG); ASSERT(pEqsGraphWnd == NULL); Hook(hWnd)->Init(); return ::DefWindowProc(hWnd, WM_NCCREATE, wParam, lParam); } /* * WM_DESTROY * ´°¿ÚÏú»Ù */ LRESULT CEqsGraphWnd::OnDestroy(WPARAM wParam, LPARAM lParam) { Release(); return ::DefWindowProc(m_hWnd, WM_DESTROY, wParam, lParam); } /* * WM_TIMER */ LRESULT CEqsGraphWnd::OnTimer(WPARAM wParam, LPARAM lParam) { if (wParam == TIMER_FLASH) { if (m_pFlashItem != NULL && m_nFlashCount > 0) { m_nFlashCount--; m_pFlashItem->nFlashFlag = (m_nFlashCount % 2); RECT rcItem; GetItemWarperRect(m_pFlashItem, &rcItem); InvalidateRect(m_hWnd, &rcItem, TRUE); } else { m_pFlashItem = NULL; m_nFlashCount = 0; } } else if (TIMER_ANIMATION_RECT == wParam) { if (m_pAnimationItem != NULL) { if (m_nAninationStep > 0) { m_nAninationStep--; m_rcAnimation.left += m_rcAninationStep.left; m_rcAnimation.right += m_rcAninationStep.right; m_rcAnimation.top += m_rcAninationStep.top; m_rcAnimation.bottom += m_rcAninationStep.bottom; RECT rcItem; GetItemWarperRect(m_pAnimationItem, &rcItem); InvalidateRect(m_hWnd, &rcItem, TRUE); } else { KillTimer(m_hWnd, TIMER_ANIMATION_RECT); RECT rcItem; GetItemWarperRect(m_pAnimationItem, &rcItem); InvalidateRect(m_hWnd, &rcItem, TRUE); m_pAnimationItem = NULL; } } else { KillTimer(m_hWnd, TIMER_ANIMATION_RECT); RECT rcClient; GetClientRect(m_hWnd, &rcClient); InvalidateRect(m_hWnd, &rcClient, TRUE); } } return ::DefWindowProc(m_hWnd, WM_TIMER, wParam, lParam); } /* * WM_MOUSEMOVE * Êó±ê¹ö¶¯ */ LRESULT CEqsGraphWnd::OnMouseMove(WPARAM wParam, LPARAM lParam) { return ::DefWindowProc(m_hWnd, WM_MOUSEMOVE, wParam, lParam); } /* * WM_LBUTTONDOWN * Êó±ê×ó¼ü°´Ï */ LRESULT CEqsGraphWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam) { POINT pt, ptNew; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); RECT rcClient, rcItem, rcNewItem, rcLast; GetClientRect(m_hWnd, &rcClient); rcLast = {0, 0, 0, 0}; int nMaxOffsetX = m_nStageCx - (rcClient.right - rcClient.left); int nMaxOffsetY = m_nStageCy - (rcClient.bottom - rcClient.top); int nLastHozLine = 0; int nLastVerLine = 0; // ¼ì²âµã»÷×ø±êÊÇ·ñÔÚijһ×ÓÏîÉÏ£¬ÈçÊÇ£¬Ôò¸ßÁÁÏÔʾ EQITEM* pLastItem = m_pCurItem; PIN *pLastPin = m_pCurPin; PIN *pLastSelLineOutPin = m_pSelLineOutPin; BOOL bChanged = FALSE; EQITEM* pHitItem = NULL; PIN *pHitPin = NULL; PIN *pPin2 = NULL; int nRet = HighTest(pt, pHitItem, pHitPin); if (pHitItem != m_pCurItem || nRet != HT_ITEM) { if (m_pCurItem != NULL) { m_pCurItem->bHighlight = FALSE; } m_pCurItem = NULL; } if (pHitPin != m_pCurPin || nRet != HT_PIN) { if (m_pCurPin != NULL) { m_pCurPin->bHighlight = FALSE; } m_pCurPin = NULL; } if (pHitPin != m_pSelLineOutPin || nRet != HT_LINE) { m_pSelLineOutPin = NULL; } if (nRet == HT_ITEM) { m_pCurItem = pHitItem; m_pCurItem->bHighlight = TRUE; } else if (nRet == HT_PIN) { m_pCurPin = pHitPin; m_pCurPin->bHighlight = TRUE; } else if (nRet == HT_LINE) { m_pSelLineOutPin = pHitPin; } bChanged = pLastItem != m_pCurItem || pLastPin != m_pCurPin || pLastSelLineOutPin != m_pSelLineOutPin; // ˢРSetFocus(m_hWnd); if (bChanged) { ::InvalidateRect(m_hWnd, &rcClient, TRUE); } // ²¶×½Êó±êÏûÏ¢£¬¼ì²âÊÇ·ñÍ϶¯ if (nRet == HT_ITEM && m_pCurItem != NULL) { GetItemRect(m_pCurItem, &rcItem); if (::GetCapture() == NULL) { SetCapture(m_hWnd); ASSERT(m_hWnd == GetCapture()); AfxLockTempMaps(); for (;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (GetCapture() != m_hWnd) break; switch (msg.message) { case WM_MOUSEMOVE: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); rcNewItem.left = rcItem.left + (ptNew.x - pt.x); rcNewItem.right = rcItem.right + (ptNew.x - pt.x); rcNewItem.top = rcItem.top + (ptNew.y - pt.y); rcNewItem.bottom = rcItem.bottom + (ptNew.y - pt.y); CalculateMagneticLine(m_pCurItem, &rcNewItem, m_nMagneticLinHoz, m_nMagneticLinVer); DrawDropItemRectangle(&rcNewItem, &rcLast); DrawMagneticLine(&rcClient, m_nMagneticLinHoz, nLastHozLine, m_nMagneticLinVer, nLastVerLine); nLastHozLine = m_nMagneticLinHoz; nLastVerLine = m_nMagneticLinVer; CopyRect(&rcLast, &rcNewItem); break; case WM_LBUTTONUP: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); m_pCurItem->rect.left = m_nMagneticLinVer > 0 ? m_nMagneticLinVer : (rcItem.left + (ptNew.x - pt.x) + m_nOffsetX); m_pCurItem->rect.right = m_pCurItem->rect.left + (rcItem.right - rcItem.left); m_pCurItem->rect.top = m_nMagneticLinHoz > 0 ? m_nMagneticLinHoz : (rcItem.top + (ptNew.y - pt.y) + m_nOffsetY); m_pCurItem->rect.bottom = m_pCurItem->rect.top + (rcItem.bottom - rcItem.top); if (m_pCurItem->rect.left != rcItem.left || m_pCurItem->rect.top != rcItem.top) { if (m_listener.onEqItemPosChanged != nullptr) { m_listener.onEqItemPosChanged(m_pCurItem, m_pCurItem->rect.left, m_pCurItem->rect.top); } } DrawDropItemRectangle(NULL, &rcLast); ReleaseCapture(); ClearConnectedLinePoint(m_pCurItem); ::InvalidateRect(m_hWnd, &rcClient, TRUE); goto ExitLoop; case WM_KEYDOWN: if (msg.wParam != VK_ESCAPE) break; default: DispatchMessage(&msg); break; } } ReleaseCapture(); ExitLoop: AfxUnlockTempMaps(FALSE); } } // ²¶×½Êó±êÏûÏ¢£¬¼ì²âÊÇ·ñÁ¬½ÓÒý½Å else if (nRet == HT_PIN && m_pCurPin != NULL) { if (::GetCapture() == NULL) { BOOL bLast = FALSE; bool bCanConnect; POINT ptPin, ptLast; COLORREF lineColor; GetPinPoint(m_pCurPin, &ptPin); ptLast.x = ptPin.x; ptLast.y = ptPin.y; SetCapture(m_hWnd); ASSERT(m_hWnd == GetCapture()); AfxLockTempMaps(); for (;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (GetCapture() != m_hWnd) break; switch (msg.message) { case WM_MOUSEMOVE: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); // ²Á³ýÉÏÒ»´Î if (bLast) { DrawPinWillConnectLine(lineColor, &ptPin, &ptLast); } // ¼ì²âÊÇ·ñ¿ÉÒÔÁ¬½Ó bCanConnect = false; nRet = HighTest(ptNew, pHitItem, pHitPin); if (nRet == HT_PIN) { if (m_listener.onCheckConnectPin != nullptr) { bCanConnect = m_listener.onCheckConnectPin(m_pCurPin, pHitPin); } } if (bCanConnect) { lineColor = RGB(0, 255, 0); DrawPinWillConnectLine(lineColor, &ptPin, &ptNew); } else { lineColor = RGB(0, 0, 0); DrawPinWillConnectLine(lineColor, &ptPin, &ptNew); } ptLast.x = ptNew.x; ptLast.y = ptNew.y; bLast = TRUE; break; case WM_LBUTTONUP: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); // ²Á³ýÉÏÒ»´Î if (bLast) { DrawPinWillConnectLine(lineColor, &ptPin, &ptLast); } // ¼ì²âÊÇ·ñ¿ÉÒÔÁ¬½Ó bCanConnect = false; nRet = HighTest(ptNew, pHitItem, pHitPin); if (nRet == HT_PIN) { if (m_listener.onConnectPin != nullptr) { bCanConnect = m_listener.onConnectPin(m_pCurPin, pHitPin); } } if (bCanConnect) { m_pCurPin->pConnectedPin = pHitPin; pHitPin->pConnectedPin = m_pCurPin; } bLast = FALSE; ReleaseCapture(); ::InvalidateRect(m_hWnd, &rcClient, TRUE); goto ExitLoop2; case WM_KEYDOWN: if (msg.wParam != VK_ESCAPE) break; default: DispatchMessage(&msg); break; } } ReleaseCapture(); ExitLoop2: AfxUnlockTempMaps(FALSE); } } // ¼ì²âÊó±êÏûÏ¢£¬¼ì²âÊÇ·ñÒÆ¶¯»­²¼ else if (nRet == HT_NOWHERE) { if (::GetCapture() == NULL) { int nLastOffsetX = m_nOffsetX; int nLastOffsetY = m_nOffsetY; POINT ptStart; ptStart.x = pt.x; ptStart.y = pt.y; SetCursor(LoadCursor(NULL, IDC_SIZEALL)); SetCapture(m_hWnd); ASSERT(m_hWnd == GetCapture()); AfxLockTempMaps(); for (;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (GetCapture() != m_hWnd) break; switch (msg.message) { case WM_MOUSEMOVE: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); m_nOffsetX = min(nMaxOffsetX, max(0, nLastOffsetX - (ptNew.x - ptStart.x))); m_nOffsetY = min(nMaxOffsetY, max(0, nLastOffsetY - (ptNew.y - ptStart.y))); CalculateScollbar(); CalculateMapPos(); ::InvalidateRect(m_hWnd, &rcClient, TRUE); break; case WM_LBUTTONUP: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); ReleaseCapture(); CalculateScollbar(); CalculateMapPos(); ::InvalidateRect(m_hWnd, &rcClient, TRUE); goto ExitLoop3; case WM_KEYDOWN: if (msg.wParam != VK_ESCAPE) break; default: DispatchMessage(&msg); break; } } ReleaseCapture(); ExitLoop3: AfxUnlockTempMaps(FALSE); } } return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam); } /* * WM_LBUTTONDBLCLK * Êó±ê×ó¼üË«»÷ */ LRESULT CEqsGraphWnd::OnLButtonDblclk(WPARAM wParam, LPARAM lParam) { POINT pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); RECT rcClient, rcLast; GetClientRect(m_hWnd, &rcClient); rcLast = { 0, 0, 0, 0 }; // ¼ì²âµã»÷×ø±êÊÇ·ñÔÚijһ×ÓÏîÉÏ£¬ÈçÊÇ£¬Ôò¸ßÁÁÏÔʾ EQITEM* pLastItem = m_pCurItem; BOOL bChanged = FALSE; EQITEM* pHitItem = NULL; PIN *pHitPin = NULL; int nRet = HighTest(pt, pHitItem, pHitPin); if ( nRet == HT_ITEM) { m_pCurItem = pHitItem; m_pCurItem->bHighlight = FALSE; if (m_listener.onDblckEqItem != nullptr) { m_listener.onDblckEqItem(pHitItem); } } return ::DefWindowProc(m_hWnd, WM_LBUTTONDBLCLK, wParam, lParam); } /* * WM_MOUSEWHEEL * Êó±ê¹ö¶¯ */ LRESULT CEqsGraphWnd::OnMouseWheel(WPARAM wParam, LPARAM lParam) { short zDelta; UINT nFlags; CPoint pt; nFlags = LOWORD(wParam); zDelta = (short)HIWORD(wParam); pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); CRect rcClient; GetClientRect(m_hWnd, &rcClient); m_nOffsetY -= zDelta; m_nOffsetY = max(0, min(m_nOffsetY, m_nStageCy - rcClient.Height())); CalculateScollbar(); CalculateMapPos(); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return ::DefWindowProc(m_hWnd, WM_MOUSEWHEEL, wParam, lParam); } /* * WM_MOUSEHWHEEL * Êó±ê¹ö¶¯ */ LRESULT CEqsGraphWnd::OnMouseHWheel(WPARAM wParam, LPARAM lParam) { short zDelta; UINT nFlags; CPoint pt; nFlags = LOWORD(wParam); zDelta = (short)HIWORD(wParam); pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); CRect rcClient; GetClientRect(m_hWnd, &rcClient); m_nOffsetX += zDelta; m_nOffsetX = max(0, min(m_nOffsetX, m_nStageCx - rcClient.Width())); CalculateScollbar(); CalculateMapPos(); ::InvalidateRect(m_hWnd, &rcClient, TRUE); return ::DefWindowProc(m_hWnd, WM_MOUSEHWHEEL, wParam, lParam); } /* * WM_RBUTTONDOWN * Êó±ê×ó¼ü°´Ï */ LRESULT CEqsGraphWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam) { POINT pt, ptNew; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); RECT rcClient, rcItem, rcLast; GetClientRect(m_hWnd, &rcClient); rcLast = { 0, 0, 0, 0 }; // ¼ì²âµã»÷×ø±êÊÇ·ñÔÚijһ×ÓÏîÉÏ£¬ÈçÊÇ£¬Ôò¸ßÁÁÏÔʾ EQITEM* pLastItem = m_pCurItem; PIN *pLastPin = m_pCurPin; PIN *pLastSelLineOutPin = m_pSelLineOutPin; BOOL bChanged = FALSE; EQITEM* pHitItem = NULL; PIN *pHitPin = NULL; PIN *pPin2 = NULL; int nRet = HighTest(pt, pHitItem, pHitPin); if (pHitItem != m_pCurItem || nRet != HT_ITEM) { if (m_pCurItem != NULL) { m_pCurItem->bHighlight = FALSE; } m_pCurItem = NULL; } if (pHitPin != m_pCurPin || nRet != HT_PIN) { if (m_pCurPin != NULL) { m_pCurPin->bHighlight = FALSE; } m_pCurPin = NULL; } if (pHitPin != m_pSelLineOutPin || nRet != HT_LINE) { m_pSelLineOutPin = NULL; } if (nRet == HT_ITEM) { m_pCurItem = pHitItem; m_pCurItem->bHighlight = TRUE; } else if (nRet == HT_PIN) { m_pCurPin = pHitPin; m_pCurPin->bHighlight = TRUE; } else if (nRet == HT_LINE) { m_pSelLineOutPin = pHitPin; } bChanged = pLastItem != m_pCurItem || pLastPin != m_pCurPin || pLastSelLineOutPin != m_pSelLineOutPin; // ˢРSetFocus(m_hWnd); if (bChanged) { ::InvalidateRect(m_hWnd, &rcClient, TRUE); } // ²¶×½Êó±êÏûÏ¢£¬¼ì²âÊÇ·ñÍ϶¯ if (nRet == HT_ITEM && m_pCurItem != NULL) { CopyRect(&rcItem, &m_pCurItem->rect); if (::GetCapture() == NULL) { SetCapture(m_hWnd); ASSERT(m_hWnd == GetCapture()); AfxLockTempMaps(); for (;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (GetCapture() != m_hWnd) break; switch (msg.message) { case WM_MOUSEMOVE: break; case WM_RBUTTONUP: ptNew = msg.pt; ::ScreenToClient(m_hWnd, &ptNew); nRet = HighTest(ptNew, pHitItem, pHitPin); ReleaseCapture(); if (m_listener.onRclickEqItem != NULL) { m_listener.onRclickEqItem(pHitItem); } ::InvalidateRect(m_hWnd, &rcClient, TRUE); goto ExitLoop; case WM_KEYDOWN: if (msg.wParam != VK_ESCAPE) break; default: DispatchMessage(&msg); break; } } ReleaseCapture(); ExitLoop: AfxUnlockTempMaps(FALSE); } } return ::DefWindowProc(m_hWnd, WM_LBUTTONDOWN, wParam, lParam); } /* * WM_KEYDOWN * ¼üÅÌÏûÏ¢£¬°´Ï°´¼ü */ LRESULT CEqsGraphWnd::OnKeyDown(WPARAM wParam, LPARAM lParam) { BOOL bChanged = FALSE; if (wParam == VK_DELETE) { // Èç¹ûµ±Ç°Ñ¡ÔñΪÏߣ¬Ôò¶Ï¿ªÁ¬½Ó if (m_pSelLineOutPin != NULL) { if (m_listener.onDisconnectPin != nullptr) { if (m_listener.onDisconnectPin(m_pSelLineOutPin)) { m_pSelLineOutPin->pConnectedPin->pConnectedPin = NULL; m_pSelLineOutPin->pConnectedPin = NULL; m_pSelLineOutPin = NULL; bChanged = TRUE; } } } else if (m_pCurItem != NULL) { if (m_listener.onDeleteEqItem != NULL) { if (m_listener.onDeleteEqItem(m_pCurItem)) { bChanged = DeleteItem(m_pCurItem) >= 0; } } } } if (bChanged) { RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } return ::DefWindowProc(m_hWnd, WM_KEYDOWN, wParam, lParam); } /* * WM_NCPAINT */ LRESULT CEqsGraphWnd::OnNcPaint(WPARAM wParam, LPARAM lParam) { LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NCPAINT, wParam, lParam); long styleEx = GetWindowLong(m_hWnd, GWL_EXSTYLE); if ((styleEx & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) { RECT rect, rcClient; GetClientRect(m_hWnd, &rcClient); ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.left); ::ClientToScreen(m_hWnd, (LPPOINT)&rcClient.right); GetWindowRect(m_hWnd, &rect); rcClient.right = rect.right - 1; rcClient.bottom = rect.bottom - 1; ::OffsetRect(&rcClient, -rect.left, -rect.top); rect.right -= rect.left; rect.bottom -= rect.top; rect.left = 0; rect.top = 0; HRGN hRgnWnd = CreateRectRgnIndirect(&rect); HRGN hRgnClient = CreateRectRgnIndirect(&rcClient); HBRUSH hBrushBK, hBrushFrame; HDC hDC = ::GetWindowDC(m_hWnd); ::SelectClipRgn(hDC, hRgnWnd); ::ExtSelectClipRgn(hDC, hRgnClient, RGN_DIFF); hBrushBK = CreateSolidBrush(m_crBkgnd); ::FillRect(hDC, &rect, hBrushBK); DeleteObject(hBrushBK); hBrushFrame = CreateSolidBrush(m_crFrame); ::FrameRect(hDC, &rect, hBrushFrame); ::DeleteObject(hRgnWnd); ::DeleteObject(hRgnClient); DeleteObject(hBrushFrame); ::ReleaseDC(m_hWnd, hDC); } return lRet; } /* * WM_PAINT */ LRESULT CEqsGraphWnd::OnPaint(WPARAM wParam, LPARAM lParam) { HDC hDC, hMemDC; HBITMAP hBitmap; RECT rcClient; CString strText; HBRUSH hBrushBK; // BeginPaint PAINTSTRUCT ps; hDC = BeginPaint(m_hWnd, &ps); GetClientRect(m_hWnd, &rcClient); hMemDC = ::CreateCompatibleDC(hDC); hBitmap = ::CreateCompatibleBitmap(hDC, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); ::SelectObject(hMemDC, hBitmap); // ±³¾°ÑÕÉ« hBrushBK = CreateSolidBrush(m_crBkgnd); ::FillRect(hMemDC, &rcClient, hBrushBK); DeleteObject(hBrushBK); // ±êÌâ if (m_hFontTitle == nullptr) { LOGFONT lf; HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT); ::GetObject(hFontDefault, sizeof(LOGFONT), &lf); lf.lfHeight -= 6; lf.lfWeight = FW_SEMIBOLD; m_hFontTitle = CreateFontIndirect(&lf); } { char szTitle[256]; GetWindowText(m_hWnd, szTitle, 256); RECT rcTitle; rcTitle.left = rcClient.left + 5; rcTitle.top = rcClient.top + 12; rcTitle.bottom = rcClient.bottom - 5; rcTitle.right = rcClient.right - 5; ::SelectObject(hMemDC, m_hFontTitle); ::DrawText(hMemDC, szTitle, (int)strlen(szTitle), &rcTitle, DT_LEFT | DT_TOP); } // »æÖÆ×ÓÏî HBRUSH hbrItemBackground[2]; HBRUSH hbrItemFrame[2]; HBRUSH hbrPinBackground[3]; hbrItemBackground[0] = CreateSolidBrush(m_crItemBackground[0]); hbrItemBackground[1] = CreateSolidBrush(m_crItemBackground[1]); hbrItemFrame[0] = CreateSolidBrush(m_crItemFrame[0]); hbrItemFrame[1] = CreateSolidBrush(m_crItemFrame[1]); for (int i = 0; i < 3; i++) { hbrPinBackground[i] = CreateSolidBrush(m_crPinBkgnd[i]); } // gdi+ Gdiplus::Graphics graphics(hMemDC); Gdiplus::Pen pen1(Gdiplus::Color(255, 64, 64, 64), 2); Gdiplus::Pen pen2(Gdiplus::Color(255, 255, 127, 39), 2); Gdiplus::SolidBrush brush1(Gdiplus::Color(255, 64, 64, 64)); if (m_bUseGdiPlus) { graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); } SetBkMode(hMemDC, TRANSPARENT); { RECT rcItem; int nPinState; int nItemCount = (int)m_arItem.GetCount(); for (int i = 0; i < nItemCount; i++) { EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i); if (pItem->nFlashFlag == 1) { continue; } GetItemRect(pItem, &rcItem); // ×ÓÏî±³¾°ºÍ±ß¿ò if (m_nItemRound == 0) { ::FillRect(hMemDC, &rcItem, pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]); ::FrameRect(hMemDC, &rcItem, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]); } else { HRGN hRgn = CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right, rcItem.bottom, m_nItemRound, m_nItemRound); ::FillRgn(hMemDC, hRgn, pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]); ::FrameRgn(hMemDC, hRgn, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0], 1, 1); ::DeleteObject(hRgn); } // nameºÍid HFONT hFontOld = (HFONT)::SelectObject(hMemDC, m_hFontName); ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemNameText[1] : m_crItemNameText[0]); ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); if (pItem->nShowType != ITEM_SMALL) { RECT rcId = rcItem; rcId.left += 5; rcId.bottom -= 5; CString strId; strId.Format(_T("ID:%d"), pItem->id); ::SelectObject(hMemDC, m_hFontId); ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]); ::DrawText(hMemDC, strId, (int)strId.GetLength(), &rcId, DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS); } // ¶¯»­Ð§¹û²»»æpin if (m_pAnimationItem == pItem) { continue; } // »æÖÆpin RECT rcPin, rcPin2, rcPinText; CPtrArray *pPins; rcPinText.left = rcItem.left + 8; rcPinText.right = rcItem.right - 8; // in pins PIN *pPin = NULL; pPins = (CPtrArray *)pItem->pInPins; for (int j = 0; j < pPins->GetSize(); j++) { if (GetInPinRect(pItem, j, &rcPin)) { pPin = (PIN *)pPins->GetAt(j); ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]); rcPin2.left = rcPin.left + 1; rcPin2.right = rcPin.right; rcPin2.top = rcPin.top + 1; rcPin2.bottom = rcPin.bottom - 1; nPinState = GetPinState(pPin); ::FillRect(hMemDC, &rcPin2, nPinState == 0 ? (pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]) : hbrPinBackground[nPinState]); if (pItem->nShowType != ITEM_SMALL) { rcPinText.top = rcPin.top - 12; rcPinText.bottom = rcPin.bottom + 12; ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]); ::DrawText(hMemDC, pPin->text, (int)strlen(pPin->text), &rcPinText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); } } } // out pins pPins = (CPtrArray *)pItem->pOutPins; for (int j = 0; j < pPins->GetSize(); j++) { pPin = (PIN *)pPins->GetAt(j); if (GetOutPinRect(pItem, j, &rcPin)) { ::FrameRect(hMemDC, &rcPin, pItem->bHighlight ? hbrItemFrame[1] : hbrItemFrame[0]); rcPin2.left = rcPin.left; rcPin2.right = rcPin.right - 1; rcPin2.top = rcPin.top + 1; rcPin2.bottom = rcPin.bottom - 1; nPinState = GetPinState(pPin); ::FillRect(hMemDC, &rcPin2, nPinState == 0 ? (pItem->bHighlight ? hbrItemBackground[1] : hbrItemBackground[0]) : hbrPinBackground[nPinState]); if (pItem->nShowType != ITEM_SMALL) { rcPinText.top = rcPin.top - 12; rcPinText.bottom = rcPin.bottom + 12; ::SetTextColor(hMemDC, pItem->bHighlight ? m_crItemIdText[1] : m_crItemIdText[0]); ::DrawText(hMemDC, pPin->text, (int)strlen(pPin->text), &rcPinText, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); } } } ::DeleteObject(hbrItemFrame); ::SelectObject(hMemDC, hFontOld); } // »æÖÆÁ¬½ÓÏߣ¬±£´æÏßÌõÔÚ×îºó»æÖÆ for (int i = 0; i < nItemCount; i++) { EQITEM *pItem = (EQITEM*)m_arItem.GetAt(i); if (pItem->nFlashFlag == 1) { continue; } PIN *pPin = NULL; CPtrArray *pPins; // out pins±ßÏß RECT rcItem1, rcItem2; pPins = (CPtrArray *)pItem->pOutPins; for (int j = 0; j < pPins->GetSize(); j++) { pPin = (PIN *)pPins->GetAt(j); if (pPin->pConnectedPin != NULL) { POINT pt1, pt2; if (GetPinPoint(pPin, &pt1) && GetPinPoint(pPin->pConnectedPin, &pt2)) { GetItemRect(pItem, &rcItem1); GetItemRect(pPin->pConnectedPin->pItem, &rcItem2); DrawPinConnectedLine(&graphics, &brush1, pPin == m_pSelLineOutPin ? &pen2 : &pen1, &pt1, &pt2, &rcItem1, &rcItem2, pPin); } } } } for (int i = 0; i < 3; i++) { ::DeleteObject(hbrPinBackground[i]); } ::DeleteObject(hbrItemBackground[0]); ::DeleteObject(hbrItemBackground[1]); ::DeleteObject(hbrItemFrame[0]); ::DeleteObject(hbrItemFrame[1]); } // EndPaint ::BitBlt(hDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hMemDC, 0, 0, SRCCOPY); EndPaint(m_hWnd, &ps); ::DeleteObject(hBitmap); ::DeleteDC(hMemDC); return 1; } /* * WM_SIZE */ LRESULT CEqsGraphWnd::OnSize(WPARAM wParam, LPARAM lParam) { LRESULT lRet = ::DefWindowProc(m_hWnd, WM_SIZE, wParam, lParam); CalculateScollbar(); if (m_hWndMapPos != NULL) { CalculateMapPos(); CRect rcItem, rcClient; GetClientRect(m_hWnd, &rcClient); GetWindowRect(m_hWndMapPos,& rcItem); ::MoveWindow(m_hWndMapPos, rcClient.right- rcItem.Width() - MAPPOSWND_PADDING_RIGHT, MAPPOSWND_PADDING_RIGHT, rcItem.Width(), rcItem.Height(), TRUE); } return lRet; } /* * WM_VSCROLL */ LRESULT CEqsGraphWnd::OnVScroll(WPARAM wParam, LPARAM lParam) { int nSBCode = LOWORD(wParam); int nPos = HIWORD(wParam); SCROLLINFO info = { 0 }; info.cbSize = sizeof(SCROLLINFO); info.fMask = SIF_ALL; GetScrollInfo(m_hWnd, SB_VERT, &info); int nMaxPos = info.nMax - info.nPage; int inc = 10; switch (nSBCode) { case SB_BOTTOM: if (info.nPos < nMaxPos) { // ScrollWindow(m_hWnd, 0, -1 * inc*(iMaxPos - info.nPos), NULL, NULL); info.nPos = nMaxPos; } break; case SB_TOP: if (info.nPos > info.nMin) { // ScrollWindow(m_hWnd, 0, inc*(info.nPos - info.nMin), NULL, NULL); info.nPos = info.nMin; } break; case SB_LINEUP: if (info.nPos > info.nMin) { //ScrollWindow(m_hWnd, 0, inc, NULL, NULL); info.nPos -= 1; } break; case SB_LINEDOWN: if (info.nPos < nMaxPos) { // ScrollWindow(m_hWnd, 0, -1 * inc, NULL, NULL); info.nPos += 1; } break; case SB_PAGEUP: if (info.nPos - 100 >= info.nMin) { //ScrollWindow(m_hWnd, 0, 100 * inc, NULL, NULL); info.nPos -= 100; } else { if (info.nPos <= 0) { // ScrollWindow(m_hWnd, 0, 0, NULL, NULL); } else { // ScrollWindow(m_hWnd, 0, info.nPos, NULL, NULL); } info.nPos = info.nMin; } break; case SB_PAGEDOWN: if (info.nPos + 100 <= nMaxPos) { // ScrollWindow(m_hWnd, 0, -100*inc, NULL, NULL); info.nPos += 100; } else { // ScrollWindow(m_hWnd, 0, (info.nPos - iMaxPos) * inc, NULL, NULL); info.nPos = nMaxPos; } break; case SB_ENDSCROLL: break; case SB_THUMBPOSITION: break; case SB_THUMBTRACK: // ScrollWindow(m_hWnd, 0, inc * (info.nPos - nPos), NULL, NULL); info.nPos = nPos; break; default: break; } m_nOffsetY = info.nPos; SetScrollInfo(m_hWnd, SB_VERT, &info, TRUE); CalculateMapPos(); RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); LRESULT lRet = ::DefWindowProc(m_hWnd, WM_VSCROLL, wParam, lParam); return lRet; } /* * WM_HSCROLL */ LRESULT CEqsGraphWnd::OnHScroll(WPARAM wParam, LPARAM lParam) { int nSBCode = LOWORD(wParam); int nPos = HIWORD(wParam); SCROLLINFO info = { 0 }; info.cbSize = sizeof(SCROLLINFO); info.fMask = SIF_ALL; GetScrollInfo(m_hWnd, SB_HORZ, &info); int nMaxPos = info.nMax - info.nPage; int inc = 10; switch (nSBCode) { case SB_RIGHT: if (info.nPos < nMaxPos) { // ScrollWindow(m_hWnd, 0, -1 * inc*(iMaxPos - info.nPos), NULL, NULL); info.nPos = nMaxPos; } break; case SB_LEFT: if (info.nPos > info.nMin) { // ScrollWindow(m_hWnd, 0, inc*(info.nPos - info.nMin), NULL, NULL); info.nPos = info.nMin; } break; case SB_LINELEFT: if (info.nPos > info.nMin) { //ScrollWindow(m_hWnd, 0, inc, NULL, NULL); info.nPos -= 1; } break; case SB_LINERIGHT: if (info.nPos < nMaxPos) { // ScrollWindow(m_hWnd, 0, -1 * inc, NULL, NULL); info.nPos += 1; } break; case SB_PAGELEFT: if (info.nPos - 100 >= info.nMin) { //ScrollWindow(m_hWnd, 0, 100 * inc, NULL, NULL); info.nPos -= 100; } else { if (info.nPos <= 0) { // ScrollWindow(m_hWnd, 0, 0, NULL, NULL); } else { // ScrollWindow(m_hWnd, 0, info.nPos, NULL, NULL); } info.nPos = info.nMin; } break; case SB_PAGERIGHT: if (info.nPos + 100 <= nMaxPos) { // ScrollWindow(m_hWnd, 0, -100*inc, NULL, NULL); info.nPos += 100; } else { // ScrollWindow(m_hWnd, 0, (info.nPos - iMaxPos) * inc, NULL, NULL); info.nPos = nMaxPos; } break; case SB_ENDSCROLL: break; case SB_THUMBPOSITION: break; case SB_THUMBTRACK: // ScrollWindow(m_hWnd, 0, inc * (info.nPos - nPos), NULL, NULL); info.nPos = nPos; break; default: break; } m_nOffsetX = info.nPos; SetScrollInfo(m_hWnd, SB_HORZ, &info, TRUE); CalculateMapPos(); RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); LRESULT lRet = ::DefWindowProc(m_hWnd, WM_HSCROLL, wParam, lParam); return lRet; } /* * WM_NOTIFY */ LRESULT CEqsGraphWnd::OnNitify(WPARAM wParam, LPARAM lParam) { LRESULT lRet = ::DefWindowProc(m_hWnd, WM_NOTIFY, wParam, lParam); NMHDR *pNmhdr = (NMHDR *)lParam; if (pNmhdr->idFrom == MAPPOSWND_ID) { MAPPOSWND_NMHDR *pNmhdr2 = (MAPPOSWND_NMHDR *)lParam; m_nOffsetX = pNmhdr2->dwData; m_nOffsetY = pNmhdr2->dwData1; CalculateScollbar(); CalculateMapPos(); RECT rcClient; GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, TRUE); } return lRet; } /* * ÉèÖñ³¾°ÑÕÉ« * color -- ±³¾°É« */ void CEqsGraphWnd::SetBkgndColor(COLORREF color) { m_crBkgnd = color; } /* * ±ß¿òÑÕÉ« * color -- ±ß¿òÉ« */ void CEqsGraphWnd::SetFrameColor(COLORREF color) { m_crFrame = color; } void CEqsGraphWnd::FlashItem(EQITEM *pItem) { if (m_pFlashItem != NULL) { KillTimer(m_hWnd, TIMER_FLASH); } m_nFlashCount = 5; m_pFlashItem = pItem; SetTimer(m_hWnd, TIMER_FLASH, 100, NULL); } void CEqsGraphWnd::AnimationItem(EQITEM* pItem) { if (m_pAnimationItem != NULL) { KillTimer(m_hWnd, TIMER_ANIMATION_RECT); } m_pAnimationItem = NULL; KillTimer(m_hWnd, TIMER_ANIMATION_RECT); UINT uElpase = 50; m_nAninationDuration = 200; m_nAninationStep = m_nAninationDuration / uElpase; m_pAnimationItem = pItem; m_rcAnimation.left = pItem->rect.left + (pItem->rect.right - pItem->rect.left) / 2.0f; m_rcAnimation.right = m_rcAnimation.left; m_rcAnimation.top = pItem->rect.top + (pItem->rect.bottom - pItem->rect.top) / 2.0f; m_rcAnimation.bottom = m_rcAnimation.top; m_rcAninationStep.left = (pItem->rect.left - m_rcAnimation.left) / (float)m_nAninationStep; m_rcAninationStep.right = (pItem->rect.right - m_rcAnimation.right) / (float)m_nAninationStep; m_rcAninationStep.top = (pItem->rect.top - m_rcAnimation.top) / (float)m_nAninationStep; m_rcAninationStep.bottom = (pItem->rect.bottom - m_rcAnimation.bottom) / (float)m_nAninationStep; SetTimer(m_hWnd, TIMER_ANIMATION_RECT, uElpase, NULL); } double CEqsGraphWnd::PointToSegDist(double x, double y, double x1, double y1, double x2, double y2) { double cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1); if (cross <= 0) return sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)); double d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); if (cross >= d2) return sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); double r = cross / d2; double px = x1 + (x2 - x1) * r; double py = y1 + (y2 - y1) * r; return sqrt((x - px) * (x - px) + (py - y) * (py - y)); }