#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_listener.onSelectEqItem = 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; i<pPins->GetCount(); 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; i<pPins->GetCount(); 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;
|
m_listener.onSelectEqItem = listener.onSelectEqItem;
|
}
|
|
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);
|
}
|
|
void CEqsGraphWnd::SetItemPos(EQITEM* pItem, int x, int y)
|
{
|
ASSERT(pItem);
|
pItem->rect.left = x;
|
pItem->rect.top = y;
|
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;
|
BOOL bSelectChanged = 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) {
|
if (m_pCurItem != pHitItem) {
|
m_pCurItem = pHitItem;
|
m_pCurItem->bHighlight = TRUE;
|
bSelectChanged = 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:
|
m_nMagneticLinHoz = 0;
|
m_nMagneticLinVer = 0;
|
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);
|
}
|
}
|
|
|
if (bSelectChanged) {
|
if (m_listener.onSelectEqItem != nullptr) {
|
m_listener.onSelectEqItem(m_pCurItem);
|
}
|
}
|
|
|
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));
|
}
|