/* Cards dragged from a stack */ bool CARDLIBPROC StackDragProc(CardRegion &stackobj, int numDragCards) { int numfacedown, numcards; stackobj.GetFaceDirection(&numfacedown); numcards = stackobj.NumCards(); /* Only cards facing up */ if (numDragCards <= numcards - numfacedown) { const CardStack &mystack = stackobj.GetCardStack(); /* Don't allow to drag unsuited cards */ if (!stackLookingGood(mystack, numDragCards - 1)) { return false; } /* Remember where the cards come from */ from = &stackobj; return true; } else { return false; } }
// // Double-click on one of the row stacks // The aim is to find a suit-stack to move the // double-clicked card to. // void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked) { TRACE("ENTER RowStackDblClickProc()\n"); //can only move 1 card at a time if(iNumClicked != 1) { TRACE("EXIT RowStackDblClickProc()\n"); return; } //find a suit-stack to move the card to... const CardStack &cardstack = stackobj.GetCardStack(); CardRegion *pDest = FindSuitStackFromCard(cardstack[0]); if(pDest != 0) { fGameStarted = true; //stackobj.MoveCards(pDest, 1, true); //use the SimulateDrag funcion, because we get the //AddProc callbacks called for us on the destination stacks... stackobj.SimulateDrag(pDest, 1, true); } TRACE("EXIT RowStackDblClickProc()\n"); }
/* Card to be turned from a stack */ void TurnStackCard(CardRegion &stackobj) { int numfacedown; stackobj.GetFaceDirection(&numfacedown); if (stackobj.NumCards() <= numfacedown) { if (numfacedown > 0) numfacedown--; stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown); stackobj.Redraw(); } }
CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset) { CardRegion *cr; if(nNumCardRegions == MAXCARDSTACKS) return FALSE; cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset); cr->SetBackColor(crBackgnd); cr->SetBackCardIdx(nBackCardIdx); Regions[nNumCardRegions++] = cr; return cr; }
// // Single-click on one of the row-stacks // Turn the top-card over if they are all face-down // void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked) { TRACE("ENTER RowStackClickProc()\n"); int numfacedown; stackobj.GetFaceDirection(&numfacedown); //if all face-down, then make top card face-up if(stackobj.NumCards() == numfacedown) { if(numfacedown > 0) numfacedown--; stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown); stackobj.Redraw(); } TRACE("EXIT RowStackClickProc()\n"); }
// // Can only drop a card onto a suit-stack if the // card is 1 higher, and is the same suit // bool CanDrop(CardRegion &stackobj, Card card) { TRACE("ENTER CanDrop()\n"); int topval; const CardStack &cardstack = stackobj.GetCardStack(); if(cardstack.NumCards() > 0) { if(card.Suit() != cardstack[0].Suit()) { TRACE("EXIT CanDrop()\n"); return false; } topval = cardstack[0].LoVal(); } else { topval = 0; } //make sure 1 higher if(card.LoVal() != (topval + 1)) { TRACE("EXIT CanDrop()\n"); return false; } TRACE("EXIT CanDrop()\n"); return true; }
// // Can only drag face-up cards // bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards) { TRACE("ENTER RowStackDragProc()\n"); int numfacedown; int numcards; stackobj.GetFaceDirection(&numfacedown); numcards = stackobj.NumCards(); TRACE("EXIT RowStackDragProc()\n"); if(iNumDragCards <= numcards-numfacedown) return true; else return false; }
// // What happens when a card is removed from face-up pile? // void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems) { TRACE("ENTER PileRemoveProc()\n"); //modify our "virtual" pile by removing the same card //that was removed from the physical card stack activepile.Pop(iItems); //if there is just 1 card left, then modify the //stack to contain ALL the face-up cards..the effect //will be, the next time a card is dragged, all the //previous card-triplets will be available underneath if(stackobj.NumCards() == 1) { stackobj.SetOffsets(0,0); stackobj.SetCardStack(activepile); } TRACE("EXIT PileRemoveProc()\n"); }
/* Cards dropped to a stack */ bool CARDLIBPROC StackDropProc(CardRegion &stackobj, CardStack &dragcards) { Card dragcard = dragcards[dragcards.NumCards() - 1]; int faceup, facedown; /* Only drop our cards on other stacks */ if (stackobj.Id() == from->Id()) { return false; } /* If stack is empty, everything can be dropped */ if (stackobj.NumCards() != 0) { const CardStack &mystack = stackobj.GetCardStack(); /* Can only drop if card is 1 less */ if (mystack[0].LoVal() != dragcard.LoVal() + 1) { return false; } /* Check if stack complete */ stackobj.GetFaceDirection(&facedown); faceup = stackobj.NumCards() - facedown; if (faceup + dragcards.NumCards() >= NUM_ONECOLOR_CARDS) { int i, max = NUM_ONECOLOR_CARDS - dragcards.NumCards() - 1; /* Dragged cards have been checked to be in order, check stack cards */ if (mystack[0].Suit() == dragcard.Suit() && stackLookingGood(mystack, max)) { CardStack s = stackobj.GetCardStack(); CardStack f; /* Remove from card stack */ for (i = 0; i < max + 1; i++) { s.RemoveCard(0); } /* Remove dragged cards */ dragcards = f; stackobj.SetCardStack(s); cardsFinished += NUM_ONECOLOR_CARDS; /* Flip top card of the dest stack */ TurnStackCard(stackobj); } } } /* Flip the top card of the source stack */ TurnStackCard(*from); fGameStarted = true; return true; }
// // Row a row-stack, we can only drop cards // that are lower / different colour // bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, CardStack &dragcards) { TRACE("ENTER RowStackDropProc()\n"); Card dragcard = dragcards[dragcards.NumCards() - 1]; //if we are empty, can only drop a stack with a King at bottom if(stackobj.NumCards() == 0) { if(dragcard.LoVal() != 13) { TRACE("EXIT RowStackDropProc(false)\n"); return false; } } else { const CardStack &mystack = stackobj.GetCardStack(); //can only drop if card is 1 less if(mystack[0].LoVal() != dragcard.LoVal() + 1) { TRACE("EXIT RowStackDropProc(false)\n"); return false; } //can only drop if card is different colour if( (mystack[0].IsBlack() && !dragcard.IsRed()) || (!mystack[0].IsBlack() && dragcard.IsRed()) ) { TRACE("EXIT RowStackDropProc(false)\n"); return false; } } fGameStarted = true; TRACE("EXIT RowStackDropProc(true)\n"); return true; }
// // Double-click on the deck // Move 3 cards to the face-up pile // void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked) { TRACE("ENTER DeckClickProc()\n"); CardStack cardstack = stackobj.GetCardStack(); CardStack pile = pPile->GetCardStack(); fGameStarted = true; //reset the face-up pile to represent 3 cards if(dwOptions & OPTION_THREE_CARDS) pPile->SetOffsets(CS_DEFXOFF, 1); if(cardstack.NumCards() == 0) { pile.Clear(); activepile.Reverse(); cardstack.Push(activepile); activepile.Clear(); } else { int numcards = min((dwOptions & OPTION_THREE_CARDS) ? 3 : 1, cardstack.NumCards()); //make a "visible" copy of these cards CardStack temp; temp = cardstack.Pop(numcards); temp.Reverse(); if(dwOptions & OPTION_THREE_CARDS) pile.Clear(); pile.Push(temp); //remove the top 3 from deck activepile.Push(temp); } activepile.Print(); pDeck->SetCardStack(cardstack); pPile->SetCardStack(pile); SolWnd.Redraw(); TRACE("EXIT DeckClickProc()\n"); }
LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; CREATESTRUCT *cs; static CardButton *buttonptr = 0; static CardRegion *stackptr = 0; int x, y, i; switch(iMsg) { case WM_NCCREATE: // When we created this window, we passed in the // pointer to the class object (CardWindow *) in the // call to CreateWindow. cs = (CREATESTRUCT *)lParam; // // associate this class with the window // SetWindowLongPtr(hwnd, 0, (LONG_PTR)cs->lpCreateParams); return 1; case WM_NCDESTROY: // Don't delete anything here.. break; case WM_SIZE: nWidth = LOWORD(lParam); nHeight = HIWORD(lParam); // // reposition all the stacks and buttons // in case any of them are centered, right-justified etc // for(i = 0; i < nNumCardRegions; i++) { Regions[i]->AdjustPosition(nWidth, nHeight); } for(i = 0; i < nNumButtons; i++) { Buttons[i]->AdjustPosition(nWidth, nHeight); } // // Call the user-defined resize proc AFTER all the stacks // have been positioned // if(ResizeWndCallback) ResizeWndCallback(nWidth, nHeight); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); Paint(hdc); EndPaint(hwnd, &ps); return 0; case WM_TIMER: //find the timer object in the registered funcs /*if(wParam >= 0x10000) { for(i = 0; i < nRegFuncs; i++) { if(RegFuncs[i].id == wParam) { KillTimer(hwnd, wParam); //call the registered function!! RegFuncs[i].func(RegFuncs[i].dwParam); RegFuncs[i] = RegFuncs[nRegFuncs-1]; nRegFuncs--; } } } else*/ { //find the cardstack CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam); stackobj->DoFlash(); } return 0; case WM_LBUTTONDBLCLK: x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); if((buttonptr = CardButtonFromPoint(x, y)) != 0) { buttonptr->OnLButtonDown(hwnd, x, y); return 0; } if((stackptr = CardRegionFromPoint(x, y)) != 0) { stackptr->OnLButtonDblClk(x, y); stackptr = 0; } return 0; case WM_LBUTTONDOWN: x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); //if clicked on a button if((buttonptr = CardButtonFromPoint(x, y)) != 0) { if(buttonptr->OnLButtonDown(hwnd, x, y) == 0) buttonptr = 0; return 0; } if((stackptr = CardRegionFromPoint(x, y)) != 0) { if(!stackptr->OnLButtonDown(x, y)) stackptr = 0; } return 0; case WM_LBUTTONUP: x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); // // if we were clicking a button // if(buttonptr != 0) { buttonptr->OnLButtonUp(hwnd, x, y); buttonptr = 0; return 0; } if(stackptr != 0) { stackptr->OnLButtonUp(x, y); stackptr = 0; return 0; } if ((stackptr = CardRegionFromPoint(x, y)) != 0) { stackptr->ClickRelease(x, y); stackptr = 0; } return 0; case WM_MOUSEMOVE: x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); // if we were clicking a button if(buttonptr != 0) { buttonptr->OnMouseMove(hwnd, x, y); return 0; } if(stackptr != 0) { return stackptr->OnMouseMove(x, y); } return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); }
bool CardRegion::OnLButtonUp(int x, int y) { CardRegion *pDestStack = 0; HDC hdc; int dropstackid = CS_DROPZONE_NODROP; RECT dragrect; DropZone *dropzone; fMouseDragging = false; //first of all, see if any drop zones have been registered SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight); dropzone = parentWnd.GetDropZoneFromRect(&dragrect); if(dropzone) { dropstackid = dropzone->DropCards(dragstack); if(dropstackid != CS_DROPZONE_NODROP) pDestStack = parentWnd.CardRegionFromId(dropstackid); else pDestStack = 0; } else { pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight); } // If have found a stack to drop onto // TRACE ( "can I drop card?\n" ); if(pDestStack && pDestStack->CanDropCards(dragstack)) { TRACE ( "yes, dropping card\n" ); hdc = GetDC((HWND)parentWnd); // UseNicePalette(hdc); ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack); ReleaseDC((HWND)parentWnd, hdc); // //add the cards to the destination stack // CardStack temp = pDestStack->GetCardStack(); temp.Push(dragstack); pDestStack->SetCardStack(temp); // pDestStack->Update(); //Update this stack's card count + size // pDestStack->UpdateFaceDir(temp); // Call the remove callback on THIS stack, if one is specified // if(RemoveCallback) RemoveCallback(*this, iNumDragCards); // Call the add callback, if one is specified // if(pDestStack->AddCallback) pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards); RedrawIfNotDim(pDestStack, true); TRACE ( "done dropping card\n" ); } // // Otherwise, let the cards snap back onto this stack // else { TRACE ( "no, putting card back\n" ); hdc = GetDC((HWND)parentWnd); TRACE ( "calling ZoomCard()\n" ); ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this); TRACE ( "cardstack += dragstack\n" ); cardstack += dragstack; TRACE ( "calling ReleaseDC()\n" ); ReleaseDC((HWND)parentWnd, hdc); TRACE ( "calling Update()\n" ); Update(); //Update this stack's card count + size TRACE ( "done putting card back\n" ); } ReleaseDragBitmaps(); ReleaseCapture(); TRACE ( "OnLButtonUp() done\n" ); return true; }