447 lines
12 KiB
C++
447 lines
12 KiB
C++
#include "stdafx.h"
|
|
#ifdef ACTIVE_EDITOR
|
|
|
|
#include "acp_base.h"
|
|
#include <sys/timeb.h>
|
|
#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
|