#include "stdafx.h" #ifdef ACTIVE_EDITOR #include "acp_base.h" #include #include "itf/CPAProj.hpp" #include "itf/DEVMul3D.hpp" #include "itf/CPADD.hpp" #include "itf/CPARes.h" // For rectangles static int gs_iNumOfRects = 0; typedef struct DD_tdstRect_ { RECT stRect; HWND hWnd; } DD_tdstRect; #define DD_C_MaxRects 50 static DD_tdstRect gs_a_stRects[DD_C_MaxRects]; // for timer UINT gs_uiTimer; UINT gs_uiElapseScroll = 500; int gs_iRect = -1; //================================================================== // REFERENCES //================================================================== // Search a reference to a window in array of all references BOOL DD_bSearchReference(HWND hWnd, char *p_szName, UINT uiDataType, BOOL *p_bCopy) { int iIndex; for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++) { if ( (M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd) && (!strcmpi(p_szName, M_GetMainApp()->m_a_WndRef[iIndex].p_szEditorName)) && (M_GetMainApp()->m_a_WndRef[iIndex].uiDataType == uiDataType) ) { *p_bCopy = M_GetMainApp()->m_a_WndRef[iIndex].bCopyOnly; return TRUE; } } return FALSE; } // Add a reference to a window that can receive a dragdrop object tdeDDError DD_eAddReference(HWND hWnd, char *p_szName, UINT uiDataType, BOOL bCopy) { BOOL bTemp; // Too much references already define if(M_GetMainApp()->m_iNumRef == C_ucMaxCWndRef) return E_DDERR_TooMuchRef; // Reference always exists if(DD_bSearchReference(hWnd, p_szName, uiDataType, &bTemp)) return E_DDERR_None; // Add reference M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].hWnd = hWnd; M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].p_szEditorName = p_szName; M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef].uiDataType = uiDataType; M_GetMainApp()->m_a_WndRef[M_GetMainApp()->m_iNumRef++].bCopyOnly = bCopy; return E_DDERR_None; } // Delete a reference to a window (all types) tdeDDError DD_eDelReference(HWND hWnd) { int iIndex; BOOL bOk = FALSE; for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++) { if(M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd) { memmove(&M_GetMainApp()->m_a_WndRef[iIndex], &M_GetMainApp()->m_a_WndRef[iIndex+1], M_GetMainApp()->m_iNumRef - iIndex); M_GetMainApp()->m_iNumRef--; bOk = TRUE; } } if(bOk) return E_DDERR_None; else return E_DDERR_UnknownRef; } // Delete a reference to a window with a special type tdeDDError DD_eDelReferenceType(HWND hWnd, char *p_szName, UINT uiDataType) { int iIndex; for(iIndex = 0; iIndex < M_GetMainApp()->m_iNumRef; iIndex++) { if ( (M_GetMainApp()->m_a_WndRef[iIndex].hWnd == hWnd) && (!strcmpi(p_szName, M_GetMainApp()->m_a_WndRef[iIndex].p_szEditorName)) && (M_GetMainApp()->m_a_WndRef[iIndex].uiDataType == uiDataType) ) { memmove(&M_GetMainApp()->m_a_WndRef[iIndex], &M_GetMainApp()->m_a_WndRef[iIndex+1], M_GetMainApp()->m_iNumRef - iIndex); M_GetMainApp()->m_iNumRef--; return E_DDERR_None; } } return E_DDERR_UnknownRef; } // Delete all references void DD_vDelAllReferences(void) { M_GetMainApp()->m_iNumRef = 0; } //================================================================== // Drag & Drop //================================================================== // Determins what type of mouse pointer must be drawn regardless to window // under mouse. // Set M_GetMainApp()->m_bCanDrop global variable. void DD_vCanDrop(HWND hWnd, char *p_szEditorName, UINT uiDataType) { HCURSOR hcursor; BOOL bCopy; // Is Window reference ? if(hWnd && (DD_bSearchReference(hWnd, p_szEditorName, uiDataType, &bCopy))) { M_GetMainApp()->m_bCanDrop = TRUE; // Copy if CONTROL key is pressed or if window only accept copy objects if(M_GetMainApp()->m_bControl || bCopy) { hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGCOPY); M_GetMainApp()->m_bCopy = TRUE; } else { hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGMOVE); M_GetMainApp()->m_bCopy = FALSE; } } else { M_GetMainApp()->m_bCanDrop = FALSE; M_GetMainApp()->m_bCopy = FALSE; hcursor = AfxGetApp()->LoadCursor(CPA_IDC_DRAGNONE); } ::SetCursor(hcursor); } // Test if p_Wnd is loosing or gaining the focus of drag & drop // That function is call only if cursor pos has changed void DD_vDeterminsFocus(HWND hWnd, DD_Object *p_stDDObject) { if (hWnd != M_GetMainApp()->m_LastFocusWnd) { // Send a loosing focus message to last window if(M_GetMainApp()->m_LastFocusWnd) ::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_LOOSEFOCUS, 0, (LPARAM) p_stDDObject); // If there's a new window that accept drop, we send a message to it if(hWnd && M_GetMainApp()->m_bCanDrop) ::SendMessage(hWnd, WM_DRAGDROP_GAINFOCUS, 0, (LPARAM) p_stDDObject); } else if (hWnd) { // Mouse move in the same window than last one ::SendMessage(hWnd, WM_DRAGDROP_MOVE, 0, (LPARAM) p_stDDObject); } // Last focus window is now new one M_GetMainApp()->m_LastFocusWnd = hWnd; } // Get mouse position with a LPARAM parameter // Set m_stMousePos with current value of mouse position void DD_vGetMousePos(LPARAM lParam, DD_Object *p_stDDObject) { GetCursorPos(&M_GetMainApp()->m_stMousePos); /* M_GetMainApp()->m_stMousePos.x = LOWORD(lParam); M_GetMainApp()->m_stMousePos.y = HIWORD(lParam); p_stDDObject->fn_p_stGetOwner()->ClientToScreen(&M_GetMainApp()->m_stMousePos);*/ p_stDDObject->m_stMousePos.x = M_GetMainApp()->m_stMousePos.x; p_stDDObject->m_stMousePos.y = M_GetMainApp()->m_stMousePos.y; } // Finish a drag & drop operation // Send a message to current window if it accepts drag & drop // Restore mouse cursor void DD_vFinish(DD_Object *p_stDDObject) { // Send a end of drag & drop message to current window if it's possible, else // send a loose focus if(M_GetMainApp()->m_bCanDrop) ::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_END, (WPARAM) M_GetMainApp()->m_bCopy, (LPARAM) p_stDDObject); else ::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_LOOSEFOCUS, 0, (LPARAM) p_stDDObject); // Restore initial mouse cursor ::SetCursor(M_GetMainApp()->m_hFirstCursor); } // Register a special rectangle void DD_vRegisterRect(RECT *p_stRect, HWND hWnd) { if(gs_iNumOfRects == DD_C_MaxRects) return; memcpy(&gs_a_stRects[gs_iNumOfRects].stRect, p_stRect, sizeof(RECT)); gs_a_stRects[gs_iNumOfRects++].hWnd = hWnd; } // change timer elapse time void DD_vSetScrollTime( UINT uiTime ) { gs_uiElapseScroll = uiTime; } // Determins if mouse is in a rect int fn_iIsInRect(void) { int i; for(i = 0; i < gs_iNumOfRects; i++) { if(gs_a_stRects[i].hWnd == M_GetMainApp()->m_LastFocusWnd) { POINT pt; RECT *r = &gs_a_stRects[i].stRect; GetCursorPos(&pt); if((pt.x >= r->left ) && (pt.x <= r->right) && (pt.y >= r->top) && (pt.y <= r->bottom)) return i; } } return gs_iNumOfRects; } // Treat registered rectangles void fn_vTreatRects(DD_Object *p_stDDObject) { int iRes; iRes = fn_iIsInRect(); if(iRes < gs_iNumOfRects) { if (gs_iRect == -1) { gs_uiTimer = SetTimer(NULL, 1, gs_uiElapseScroll, NULL ); gs_iRect = iRes; } } else { if (gs_iRect != -1) { KillTimer( NULL, gs_uiTimer ); gs_iRect = -1; } } } // Begin a drag & drop operation // p_Rect : Rect to begin drag & drop // p_stObject : Object to transmit HWND DD_hBeginDragDrop(RECT *p_Rect, DD_Object *p_stDDObject) { BOOL bOutOfRect = FALSE; BOOL bEndOfLoop = FALSE; BOOL bCanDispatch; MSG stMsg; // Inits //------ M_GetMainApp()->m_bCanDrop = FALSE; M_GetMainApp()->m_bCopy = FALSE; M_GetMainApp()->m_bControl = FALSE; M_GetMainApp()->m_hFirstCursor = ::GetCursor(); // Wait mouse to go out of first rect area //---------------------------------------- while (bEndOfLoop == FALSE) { ::GetMessage(&stMsg, NULL, 0, 0); switch(stMsg.message) { case WM_MOUSEMOVE: DD_vGetMousePos(stMsg.lParam, p_stDDObject); if (!::PtInRect(p_Rect, M_GetMainApp()->m_stMousePos)) { bOutOfRect = TRUE; bEndOfLoop = TRUE; break; } break; case WM_LBUTTONUP: bEndOfLoop = TRUE; break; } ::TranslateMessage(&stMsg); ::DispatchMessage(&stMsg); } // A drag & drop is beginnig if bOutOfRect is set to TRUE //------------------------------------------------------- if (bOutOfRect) { // Source window capture mouse //---------------------------- ASSERT(p_stDDObject->fn_p_stGetOwner() != NULL); p_stDDObject->m_p_oGrabCaptureFor(p_stDDObject->fn_p_stGetOwner()); bEndOfLoop = FALSE; // The last wnd under mouse is window that owns object M_GetMainApp()->m_LastFocusWnd = p_stDDObject->fn_p_stGetOwner()->GetSafeHwnd(); while(bEndOfLoop == FALSE) { HWND hWndUnder; // Current window under mouse ::GetMessage(&stMsg, NULL, 0, 0); bCanDispatch = TRUE; // Can dispatch messages ? switch(stMsg.message) { case WM_TIMER: if (stMsg.wParam == gs_uiTimer) { // we are in a scroll rect, send DRAGDROP_SCROLL message ::SendMessage(M_GetMainApp()->m_LastFocusWnd, WM_DRAGDROP_SCROLL, 0, (LPARAM) &gs_a_stRects[gs_iRect].stRect); // Don't dispatch the message bCanDispatch = FALSE; } break; case WM_MOUSEMOVE: // Coords of mouse DD_vGetMousePos(stMsg.lParam, p_stDDObject); // Get window under mouse hWndUnder = WindowFromPoint(M_GetMainApp()->m_stMousePos); // specific for 2nd screen if (M_GetMainApp()->GetInterface()->fn_bGetAutomaticSwap()) { // get active device & viewport DEV_MultiDevice3D * pMulti = (DEV_MultiDevice3D *) M_GetMainDevice2(); DEV_ViewPort3D * pViewport = (DEV_ViewPort3D *) M_GetActiveViewport(pMulti); // call this function to detect swap pViewport->DetectMouseSwap(); // update active window if (!M_GetMainApp()->m_bCursorInFirstScreen) hWndUnder = pViewport->GetSafeHwnd(); else if (hWndUnder == pViewport->GetSafeHwnd()) hWndUnder = NULL; } // Window under mouse accept drag & drop ? DD_vCanDrop(hWndUnder, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType()); // Treat focus messages DD_vDeterminsFocus(hWndUnder, p_stDDObject); // Don't dispatch message bCanDispatch = FALSE; break; case WM_RBUTTONDOWN: M_GetMainApp()->m_bCanDrop = FALSE; DD_vFinish(p_stDDObject); bEndOfLoop = TRUE; // Don't dispatch message bCanDispatch = FALSE; break; case WM_LBUTTONUP: DD_vFinish(p_stDDObject); bEndOfLoop = TRUE; // Don't dispatch message bCanDispatch = FALSE; break; // For copying object instead of moving it case WM_KEYDOWN: if(stMsg.wParam == VK_CONTROL) { M_GetMainApp()->m_bControl = TRUE; // To redraw mouse cursor DD_vCanDrop(M_GetMainApp()->m_LastFocusWnd, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType()); // Don't dispatch message bCanDispatch = FALSE; } break; case WM_KEYUP: if(stMsg.wParam == VK_CONTROL) { M_GetMainApp()->m_bControl = FALSE; DD_vCanDrop(M_GetMainApp()->m_LastFocusWnd, p_stDDObject->fn_p_szGetEditorName(), p_stDDObject->fn_uiGetDataType()); // Don't dispatch message bCanDispatch = FALSE; } break; } // Can we dispatch message ? if(bCanDispatch) { ::TranslateMessage(&stMsg); ::DispatchMessage(&stMsg); } // Treat registered rectangles if(bEndOfLoop == FALSE) fn_vTreatRects(p_stDDObject); } // We restore mouse capture //------------------------- p_stDDObject->m_p_oSurrenderCapture(); } // No rects gs_iNumOfRects = 0; // set elapse time to default value gs_uiElapseScroll = 500; // kill timer if still in a rectangle if (gs_iRect != -1) { KillTimer( NULL, gs_uiTimer ); gs_iRect = -1; } // Return handle of window that accepted Drag & Drop if(M_GetMainApp()->m_bCanDrop) return M_GetMainApp()->m_LastFocusWnd; else return NULL; } #endif // ACTIVE_EDITOR