void cGUIButton::OnUpdate() { if(einput->isMouseDown(0)) { if(m_mousein) Capture(true); } else if(!einput->mouseValue(0)) { if(IsCaptured()) { Capture(false); if(m_mousein) Action(1); } } if(!IsCaptured() && m_mousein && einput->isMouseDown(1)) Action(2); if( g_gui->m_capture == this ) style |= GUISTYLE_PRESSED; else style &= ~GUISTYLE_PRESSED; }
void nobMilitary::AddActiveSoldier(nofActiveSoldier* soldier) { // aktiver Soldat, eingetroffen werden --> dieser muss erst in einen passiven Soldaten // umoperiert werden (neu erzeugt und alter zerstört) werden nofPassiveSoldier* passive_soldier = new nofPassiveSoldier(*soldier); // neuen Soldaten einhängen AddPassiveSoldier(passive_soldier); // alten Soldaten später vernichten soldier->ResetHome(); GetEvMgr().AddToKillList(soldier); RTTR_Assert(soldier->GetPlayer() == player); // Returned home if(soldier == defender_) NoDefender(); else if(helpers::contains(troops_on_mission, soldier)) { troops_on_mission.remove(soldier); }else if(IsCaptured() || IsFarAwayCapturer(dynamic_cast<nofAttacker*>(soldier))) { RTTR_Assert(dynamic_cast<nofAttacker*>(soldier)); return; } // Do only if not capturing RegulateTroops(); }
bool Button::EventMouse( cevent_mouse* pEvent ) { switch ( pEvent->Type() ) { case EV_MOUSE_MOVE: if ( IsCaptured() ) { crect r = ClientRect(); cpoint p = pEvent->Point(); if ( pressed ) { if ( p.x < 0 || p.y < 0 || p.x >= r.right || p.y >= r.bottom ) { pressed = false; Invalidate(); } } else { if ( p.x >= 0 && p.y >= 0 && p.x < r.right && p.y < r.bottom ) { pressed = true; Invalidate(); } } } break; case EV_MOUSE_PRESS: case EV_MOUSE_DOUBLE: if ( pEvent->Button() != MB_L ) { break; } SetCapture(); pressed = true; Invalidate(); break; case EV_MOUSE_RELEASE: if ( pEvent->Button() != MB_L ) { break; } ReleaseCapture(); if ( pressed ) { SendCommand(); } pressed = false; Invalidate(); break; }; return true; }
/// A far-away capturer arrived at the building/flag and starts the capturing void nobMilitary::FarAwayCapturerReachedGoal(nofAttacker* attacker) { RTTR_Assert(IsFarAwayCapturer(attacker)); if(IsCaptured()) { // If we are still capturing just re-add this soldier to the aggressors // one of the currently capturing soldiers will notify him far_away_capturers.remove(attacker); aggressors.push_back(attacker); }else { // Otherwise we are in a kind of "normal" working state of the building and will just add him when he gets in // Call the next one CallNextFarAwayCapturer(attacker); } }
void nobMilitary::CapturingSoldierArrived() { RTTR_Assert(IsCaptured()); RTTR_Assert(capturing_soldiers > 0); --capturing_soldiers; if(capturing_soldiers == 0) { // Search again NeedOccupyingTroops(); if(capturing_soldiers > 0) return; // Found more // Einnahme beendet capturing = false; // Nun die Besetzung prüfen RegulateTroops(); } }
bool VListWin::EventMouse( cevent_mouse* pEvent ) { if ( !IsEnabled() ) { return false; } int n = ( pEvent->Point().y - listRect.top ) / this->itemHeight + first; if ( pEvent->Type() == EV_MOUSE_PRESS ) { if ( pEvent->Button() == MB_X1 ) { int n = pageSize / 3; if ( n < 1 ) { n = 1; } MoveFirst( first - n ); return true; } if ( pEvent->Button() == MB_X2 ) { int n = pageSize / 3; if ( n < 1 ) { n = 1; } MoveFirst( first + n ); return true; } } if ( pEvent->Type() == EV_MOUSE_PRESS && pEvent->Button() == MB_L && listRect.In( pEvent->Point() ) ) { captureDelta = 0; MoveCurrent( n ); this->SetCapture( &captureSD ); this->SetTimer( 0, 100 ); return true; } if ( pEvent->Type() == EV_MOUSE_DOUBLE ) { MoveCurrent( n ); Command( CMD_ITEM_CLICK, GetCurrent(), this, 0 ); return true; } if ( pEvent->Type() == EV_MOUSE_MOVE && IsCaptured() ) { if ( pEvent->Point().y >= listRect.top && pEvent->Point().y <= listRect.bottom ) { MoveCurrent( n ); captureDelta = 0; } else { captureDelta = ( pEvent->Point().y > listRect.bottom ) ? 1 : ( pEvent->Point().y < listRect.top ) ? -1 : 0; } return true; } if ( pEvent->Type() == EV_MOUSE_RELEASE && pEvent->Button() == MB_L ) { this->ReleaseCapture( &captureSD ); this->DelTimer( 0 ); if ( selectType == SINGLE_SELECT ) { MoveCurrent( n ); Command( CMD_ITEM_CLICK, GetCurrent(), this, 0 ); } return true; } return Win::EventMouse( pEvent ); }
bool ScrollBar::EventMouse( cevent_mouse* pEvent ) { switch ( pEvent->Type() ) { case EV_MOUSE_MOVE: if ( trace ) { int p = vertical ? ( pEvent->Point().y - b1Rect.bottom ) : ( pEvent->Point().x - b1Rect.right ); p -= traceBPoint; int n = len - bsize; if ( n <= 0 ) { break; } //if (p>=n) p = n-1; //if (p<0) p = 0; int n1 = si.size - si.pageSize; int x = ( int64( p ) * n1 ) / n; if ( x >= n1 ) { x = n1; } if ( x < 0 ) { x = 0; } SendManagedCmd( SCMD_SCROLL_TRACK, &x ); //(void*)x); } break; case EV_MOUSE_DOUBLE: case EV_MOUSE_PRESS: if ( pEvent->Button() != MB_L ) { break; } { int subId = 0; if ( b1Rect.In( pEvent->Point() ) ) { b1Pressed = true; subId = ( vertical ) ? SCMD_SCROLL_LINE_UP : SCMD_SCROLL_LINE_LEFT; } else if ( b2Rect.In( pEvent->Point() ) ) { b2Pressed = true; subId = ( vertical ) ? SCMD_SCROLL_LINE_DOWN : SCMD_SCROLL_LINE_RIGHT; } else if ( b3Rect.In( pEvent->Point() ) ) { traceBPoint = ( vertical ) ? ( pEvent->Point().y - b3Rect.top ) : ( pEvent->Point().x - b3Rect.left ); trace = true; SetCapture(); break; } else if ( !b3Rect.IsEmpty() ) { if ( vertical ) { if ( pEvent->Point().y < b3Rect.top ) { subId = SCMD_SCROLL_PAGE_UP; } else { subId = SCMD_SCROLL_PAGE_DOWN; } } else { if ( pEvent->Point().x < b3Rect.left ) { subId = SCMD_SCROLL_PAGE_LEFT; } else { subId = SCMD_SCROLL_PAGE_RIGHT; } } } if ( subId != 0 ) { SetCapture(); SendManagedCmd( subId, 0 ); SetTimer( subId, 100 ); } } this->Invalidate(); break; case EV_MOUSE_RELEASE: if ( pEvent->Button() != MB_L ) { break; } if ( IsCaptured() ) { b1Pressed = false ; b2Pressed = false ; ReleaseCapture(); DelAllTimers(); Invalidate(); trace = false; } break; default: ; } return true; }
LRESULT CSkinScrollBar::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { BOOL bMsgHandled = FALSE; switch (uMsg) { // case WM_PAINT: // OnPaint((HDC)wParam); // break; case WM_LBUTTONDOWN: { CPoint point = _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); if (IsVisible() && IsEnabled() && ::PtInRect(&m_rcScrollBar, point)) { OnLButtonDown((UINT)wParam, point); bMsgHandled = TRUE; } } break; case WM_LBUTTONUP: { if (IsVisible() && IsEnabled() && IsCaptured()) { OnLButtonUp((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); bMsgHandled = TRUE; } } break; case WM_MOUSEMOVE: { CPoint point = _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); if (IsVisible() && IsEnabled() && (IsCaptured() || IsMouseTracking() || ::PtInRect(&m_rcScrollBar, point))) { OnMouseMove((UINT)wParam, point); bMsgHandled = TRUE; } } break; case WM_MOUSELEAVE: { if (IsMouseTracking()) { OnMouseLeave(); bMsgHandled = TRUE; } } break; case WM_TIMER: { UINT_PTR nIDEvent = (UINT_PTR)wParam; if (nIDEvent == m_dwTimerId) { OnTimer(nIDEvent); bMsgHandled = TRUE; } } break; } return bMsgHandled; }
void cGUIEdit::OnUpdate() { iRect rc = scrRect(); int mx = g_gui->m_mouse.x - rc.p1.x; bool shift = einput->shift(); bool ctrl = einput->ctrl(); bool enter = einput->isKeyDown(DIK_RETURN) || einput->isKeyDown(DIK_NUMPADENTER); int width = rect.Width(); int height = rect.Height(); int cursorx = Chr2Pos(m_sel2); int deltax = 0; if(cursorx>width-height/2) deltax = -(cursorx-(width-height/2)); BOOL captured = (g_gui->m_capture == this); BOOL clicked = einput->isMouseDown(0); BOOL clickedin = clicked && m_mousein; if(clicked) { if(clickedin) { if(!m_edit) m_bktxt = txt; Capture(true); m_edit = true; m_sel1 = m_sel2 = Pos2Chr(mx-deltax); // double click static int dblclicktick = 0; int tick = GetTickCount(); if(tick-dblclicktick<500) // select all { m_sel1=0; m_sel2=txt.size(); Capture(false); } dblclicktick = tick; } else { if(m_edit) { Action(0); m_edit = false; m_sel1 = m_sel2 = 0; } } } else if(captured) { m_sel2 = Pos2Chr(mx-deltax); if( !einput->mouseValue(0) ) // for selections { Capture(false); } } int s1 = sel1(), s2 = sel2(); if(m_edit) { if(einput->isKeyDown(DIK_ESCAPE)) { if(!m_bktxt.empty()) txt = m_bktxt; // restore m_edit = false; m_sel1 = m_sel2 = 0; return; } if(enter || einput->isKeyDown(DIK_TAB)) { Action(enter ? 1 : 3); m_edit = false; m_sel1 = m_sel2 = 0; return; } if(einput->isKeyDown(DIK_DELETE)) { if(s1!=s2) ShiftLeft(s2,s2-s1); // selection cut else ShiftLeft(s1+1,1); m_sel2 = m_sel1 = s1; return; } if(einput->isKeyDown(DIK_BACK)) { if(s1!=s2) ShiftLeft(s2,s2-s1); // selection cut else ShiftLeft(s1,1); s1--; if(s1<0) s1 = 0; m_sel2 = m_sel1 = s1; return; } if(einput->isKeyDown(DIK_HOME)) { m_sel2 = 0; if(!shift) m_sel1 = m_sel2; return; } if(einput->isKeyDown(DIK_END)) { m_sel2 = txt.size(); if(!shift) m_sel1 = m_sel2; return; } if(einput->isKeyDown(DIK_LEFT)) { if(m_sel1==m_sel2 || shift) { m_sel2--; if(m_sel2<0) m_sel2 = 0; if(!shift) m_sel1 = m_sel2; } else // break selection { if(m_sel2<m_sel1) m_sel1 = m_sel2; else m_sel2 = m_sel1; } return; } if(einput->isKeyDown(DIK_RIGHT)) { if(m_sel1==m_sel2 || shift) { m_sel2++; if(m_sel2>txt.size()) m_sel2 = txt.size(); if(!shift) m_sel1 = m_sel2; } else // break selection { if(m_sel2<m_sel1) m_sel2 = m_sel1; else m_sel1 = m_sel2; } return; } if(ctrl && einput->isKeyDown(DIK_C)) { ClipboardCopy(); return; } if(ctrl && einput->isKeyDown(DIK_V)) { ClipboardPaste(); return; } if(ctrl && einput->isKeyDown(DIK_X)) { ClipboardCopy(); SelectionCut(); return; } if(!einput->keyQueue.empty()) { for(auto ch: einput->keyQueue) { if(std::isprint(ch)) { if(s1!=s2) ShiftLeft(s2,s2-s1); // selection cut m_sel2 = m_sel1 = s1; txt = txt.substr(0, s1) + ch + txt.substr(s1); m_sel1++; s1 = s2 = m_sel2 = m_sel1; } } einput->keyQueue.clear(); } } // right click action if(!IsCaptured() && m_mousein && einput->isMouseDown(1)) Action(2); }
void nobMilitary::RegulateTroops() { RTTR_Assert(helpers::contains(gwg->GetPlayer(player).GetMilitaryBuildings(), this)); // If this fails, the building is beeing destroyed! // Wenn das Gebäude eingenommen wird, erstmal keine neuen Truppen und warten, wieviele noch reinkommen if(IsCaptured()) return; // Already regulate its troops => Don't call this method again if(is_regulating_troops) return; is_regulating_troops = true; if( mAutoTrain ) { RegulateTrainTroops(); is_regulating_troops = false; return; } // Zu viele oder zu wenig Truppen? int diff = CalcTroopsCount() - static_cast<int>(GetTotalSoldiers()); if(diff < 0) //poc: this should only be >0 if we are being captured. capturing should be true until its the last soldier and this last one would count twice here and result in a returning soldier that shouldnt return. { // Zu viel --> überflüssige Truppen nach Hause schicken // Zuerst die bestellten Soldaten wegschicken // Weak ones first std::vector<nofPassiveSoldier*> notNeededSoldiers; GameClientPlayer& owner = gwg->GetPlayer(player); if (owner.militarySettings_[1] > MILITARY_SETTINGS_SCALE[1] / 2) { for(SortedTroops::iterator it = ordered_troops.begin(); diff && !ordered_troops.empty(); ++diff) { notNeededSoldiers.push_back(*it); it = helpers::erase(ordered_troops, it); } } // Strong ones first else { for(SortedTroops::reverse_iterator it = ordered_troops.rbegin(); diff && !ordered_troops.empty(); ++diff) { notNeededSoldiers.push_back(*it); it = helpers::erase(ordered_troops, it); } } // send the not-needed-soldiers away for (std::vector<nofPassiveSoldier*>::iterator it = notNeededSoldiers.begin(); it != notNeededSoldiers.end(); ++it) { (*it)->NotNeeded(); } // Nur rausschicken, wenn es einen Weg zu einem Lagerhaus gibt! if(owner.FindWarehouse(*this, FW::NoCondition(), true, false)) { // Dann den Rest (einer muss immer noch drinbleiben!) // erst die schwachen Soldaten raus if (owner.militarySettings_[1] > MILITARY_SETTINGS_SCALE[1] / 2) { for(SortedTroops::iterator it = troops.begin(); diff && troops.size() > 1; ++diff) { (*it)->LeaveBuilding(); AddLeavingFigure(*it); it = helpers::erase(troops, it); } } // erst die starken Soldaten raus else { for(SortedTroops::reverse_iterator it = troops.rbegin(); diff && troops.size() > 1; ++diff) { (*it)->LeaveBuilding(); AddLeavingFigure(*it); it = helpers::erase(troops, it); } } } } else if(diff > 0) { // Zu wenig Truppen // Gebäude wird angegriffen und // Addon aktiv, nur soviele Leute zum Nachbesetzen schicken wie Verteidiger eingestellt if (IsUnderAttack() && gwg->GetGGS().getSelection(AddonId::DEFENDER_BEHAVIOR) == 2) { diff = (gwg->GetPlayer(player).militarySettings_[2] * diff) / MILITARY_SETTINGS_SCALE[2]; } //only order new troops if there is a chance that there is a path - pathfinding from each warehouse with soldiers to this mil building will start at the warehouse and cost time bool mightHaveRoad=false; for(unsigned i=2; i<7; i++) //every direction but 1 because 1 is the building connection so it doesnt count for this check { if(GetFlag()->routes[i%6]) { mightHaveRoad=true; break; } } if(mightHaveRoad) gwg->GetPlayer(player).OrderTroops(this, diff); } is_regulating_troops = false; }
void nobMilitary::NeedOccupyingTroops() { RTTR_Assert(IsCaptured()); // Only valid during capturing // Check if we need more soldiers from the attacking soldiers // Choose the closest ones first to avoid having them walk a long way nofAttacker* best_attacker = NULL; unsigned best_radius = std::numeric_limits<unsigned>::max(); unsigned needed_soldiers = unsigned(CalcTroopsCount()); unsigned currentSoldiers = troops.size() + capturing_soldiers + troops_on_mission.size(); if(needed_soldiers > currentSoldiers) { // Soldaten absuchen for(std::list<nofAttacker*>::iterator it = aggressors.begin(); it != aggressors.end(); ++it) { // Is the soldier standing around and owned by the player? if(!(*it)->IsAttackerReady() || (*it)->GetPlayer() != player) continue; // Näher als der bisher beste? if((*it)->GetRadius() >= best_radius) continue; // Und kommt er überhaupt zur Flagge (könnte ja in der 2. Reihe stehen, sodass die vor ihm ihn den Weg versperren)? if(gwg->FindHumanPath((*it)->GetPos(), gwg->GetNeighbour(pos, 4), 10, false) != 0xFF) { // Dann is das der bisher beste best_attacker = *it; best_radius = best_attacker->GetRadius(); } } // Einen gefunden? if(best_attacker) { // Dann soll der hingehen best_attacker->CaptureBuilding(); ++capturing_soldiers; // und raus hier return; } // If necessary look for further soldiers who are not standing around the building for(std::list<nofAttacker*>::iterator it = aggressors.begin(); it != aggressors.end() && needed_soldiers > currentSoldiers + far_away_capturers.size(); ) { nofAttacker* attacker = *it; if(attacker->GetPlayer() == player) { // Ask attacker if this is possible if(attacker->TryToStartFarAwayCapturing(this)) { it = aggressors.erase(it); far_away_capturers.push_back(attacker); continue; } } ++it; } } // At this point agressors contains only soldiers, that cannot capture the building (from other player or without a path to flag), // the one(s) that is currently walking to capture the building and possibly some more from other (non-allied) players // So send those home, who cannot capture the building for(std::list<nofAttacker*>::iterator it = aggressors.begin(); it != aggressors.end();) { nofAttacker* attacker = *it; // Nicht gerade Soldaten löschen, die das Gebäude noch einnehmen! //also: dont remove attackers owned by players not allied with the new owner! if(attacker->GetState() != nofActiveSoldier::STATE_ATTACKING_CAPTURINGNEXT && !gwg->GetPlayer(attacker->GetPlayer()).IsPlayerAttackable(player)) { it = aggressors.erase(it); attacker->CapturedBuildingFull(); }else ++it; } }
void nobMilitary::Capture(const unsigned char new_owner) { RTTR_Assert(IsCaptured()); captured_not_built = true; mAutoTrain = false; mAutoTrainVirtual = false; // Goldmünzen in der Inventur vom alten Spieler abziehen und dem neuen hinzufügen gwg->GetPlayer(player).DecreaseInventoryWare(GD_COINS, coins); gwg->GetPlayer(new_owner).IncreaseInventoryWare(GD_COINS, coins); // Soldaten, die auf Mission sind, Bescheid sagen for(std::list<nofActiveSoldier*>::iterator it = troops_on_mission.begin(); it != troops_on_mission.end(); ++it) (*it)->HomeDestroyed(); // Bestellungen die hierher unterwegs sind canceln CancelOrders(); // Aggressiv-Verteidigenden Soldaten Bescheid sagen, dass sie nach Hause gehen können for(std::list<nofAggressiveDefender*>::iterator it = aggressive_defenders.begin(); it != aggressive_defenders.end(); ++it) (*it)->AttackedGoalDestroyed(); troops_on_mission.clear(); aggressive_defenders.clear(); // In der Wirtschaftsverwaltung dieses Gebäude jetzt zum neuen Spieler zählen und beim alten raushauen gwg->GetPlayer(player).RemoveMilitaryBuilding(this); gwg->GetPlayer(new_owner).AddMilitaryBuilding(this); // Alten Besitzer merken unsigned char old_player = player; // neuer Spieler player = new_owner; // Flagge davor auch übernehmen GetFlag()->Capture(new_owner); // Territorium neu berechnen gwg->RecalcTerritory(*this, false, false); // Sichtbarkeiten berechnen für alten Spieler gwg->RecalcVisibilitiesAroundPoint(pos, GetMilitaryRadius() + VISUALRANGE_MILITARY + 1, old_player, NULL); // Grenzflagge entsprechend neu setzen von den Feinden LookForEnemyBuildings(); // und von den Verbündeten (da ja ein Feindgebäude weg ist)! sortedMilitaryBlds buildings = gwg->LookForMilitaryBuildings(pos, 4); for(sortedMilitaryBlds::iterator it = buildings.begin(); it != buildings.end(); ++it) { // verbündetes Gebäude? if(gwg->GetPlayer((*it)->GetPlayer()).IsPlayerAttackable(old_player) && (*it)->GetBuildingType() >= BLD_BARRACKS && (*it)->GetBuildingType() <= BLD_FORTRESS) // Grenzflaggen von dem neu berechnen static_cast<nobMilitary*>(*it)->LookForEnemyBuildings(); } // ehemalige Leute dieses Gebäudes nach Hause schicken, die ggf. grad auf dem Weg rein/raus waren MapPoint coords[2] = {pos, MapPoint(gwg->GetNeighbour(pos, 4))}; for(unsigned short i = 0; i < 2; ++i) { const std::list<noBase*>& figures = gwg->GetFigures(coords[i]); for(std::list<noBase*>::const_iterator it = figures.begin(); it != figures.end(); ++it) { if((*it)->GetType() == NOP_FIGURE) { if(static_cast<noFigure*>(*it)->GetCurrentRoad() == routes[4] && static_cast<noFigure*>(*it)->GetPlayer() != new_owner) { static_cast<noFigure*>(*it)->Abrogate(); static_cast<noFigure*>(*it)->StartWandering(); } } } } // Send all allied aggressors home (we own the building now!) for(std::list<nofAttacker*>::iterator it = aggressors.begin(); it != aggressors.end();) { nofAttacker* attacker = *it; // dont remove attackers owned by players not allied with the new owner! unsigned char attPlayer = attacker->GetPlayer(); if(attPlayer != player && !gwg->GetPlayer(attPlayer).IsPlayerAttackable(player)) { it = aggressors.erase(it); attacker->CapturedBuildingFull(); }else ++it; } // Fanfarensound abspieln, falls das Militärgebäude im Sichtbereich ist und unseres ist gwg->MilitaryBuildingCaptured(pos, player); // Post verschicken, an den alten Besitzer und an den neuen Besitzer SendPostMessage(old_player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("Military building lost"), PMC_MILITARY, *this)); SendPostMessage(player, new PostMsgWithBuilding(GetEvMgr().GetCurrentGF(), _("Military building captured"), PMC_MILITARY, *this)); // ggf. Fenster schließen vom alten Spieler gwg->ImportantObjectDestroyed(pos); gwg->GetNotifications().publish(BuildingNote(BuildingNote::Captured, player, pos, type_)); gwg->GetNotifications().publish(BuildingNote(BuildingNote::Lost, old_player, pos, type_)); }
////////////////// // Handle mousemove: enter DRAGGING state. // BOOL CDragDropMgr::OnMouseMove(const MSG& msg) { if (!IsCaptured()) return FALSE; BOOL bLButtonDown = (GetKeyState(VK_LBUTTON) & 0x8000); BOOL bRButtonDown = (GetKeyState(VK_RBUTTON) & 0x8000); // check mouse button is still down if (!bLButtonDown && !bRButtonDown) { SetState(NONE); return FALSE; } CWnd* pWnd = CWnd::FromHandle(m_hwndTracking); CPoint pt = GETPOINT(msg.lParam); if (IsDragging()) { // already dragging: move drag image pWnd->ClientToScreen(&pt); // convert to screen coords // get new target window if any m_ddi.pt = pt; m_pMainWnd->ScreenToClient(&m_ddi.pt); // convert to main window coords HWND hwndTarget = ::ChildWindowFromPoint(*m_pMainWnd, m_ddi.pt); if (hwndTarget) { m_pMainWnd->ClientToScreen(&m_ddi.pt); // back to screen ScreenToClient(hwndTarget, &m_ddi.pt); // then to target client coords } else m_ddi.pt.x = m_ddi.pt.y = -10000; m_ddi.hwndTarget = hwndTarget; // m_ddi.pt is current pos in client coords of current target window SendDragMessage(WM_DD_PREDRAGMOVE); // now move drag image m_pDragImage->DragMove(pt); // update ui UINT nDropEffect = SendDragMessage(WM_DD_DRAGOVER); // set the cursor if (!(m_ddi.hwndTarget && IsTargetWnd(m_ddi.hwndTarget))) nDropEffect = DROPEFFECT_NONE; HCURSOR hCur = NULL; if (!m_hInstOle32) m_hInstOle32 = LoadLibrary(_T("Ole32.dll")); switch (nDropEffect) { case DD_DROPEFFECT_COPY: hCur = LoadCursor(m_hInstOle32, MAKEINTRESOURCE(3)); break; case DD_DROPEFFECT_MOVE: hCur = LoadCursor(m_hInstOle32, MAKEINTRESOURCE(2)); break; case DD_DROPEFFECT_LINK: hCur = LoadCursor(m_hInstOle32, MAKEINTRESOURCE(4)); break; case DD_DROPEFFECT_NONE: default: hCur = LoadCursor(m_hInstOle32, MAKEINTRESOURCE(1)); break; } if (hCur) SetCursor(hCur); } else // if (IsCaptured()) { // Not dragging yet: enter drag mode if mouse moves beyond threshhold. CPoint delta = pt - m_ptOrg; static CPoint jog(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG)); if (abs(delta.x) > jog.x || abs(delta.y) > jog.y) { m_ddi.hwndSource = m_hwndTracking; m_ddi.pt = m_ptOrg; // start from ORIGINAL point, not where now m_ddi.hwndTarget = m_hwndTracking; m_ddi.pData = NULL; m_ddi.bLeftDrag = bLButtonDown; // Send main window a message: enter drag mode. BOOL bDrag = SendDragMessage(WM_DD_DRAGENTER); if (bDrag && m_ddi.pData) { SetState(bLButtonDown ? LDRAGGING : RDRAGGING); // I am now dragging OnMouseMove(msg); CRect rc; m_pDragImage = m_ddi.pData->CreateDragImage(pWnd, rc); m_pDragImage->BeginDrag(0, rc.BottomRight()); pWnd->ClientToScreen(&pt); m_pDragImage->DragEnter(NULL, pt); } else SetState(NONE); } } return TRUE; }