Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencardregion.cppGo to the documentation of this file.00001 // 00002 // CardLib - CardRegion class 00003 // 00004 // Freeware 00005 // Copyright J Brown 2001 00006 // 00007 #include <windows.h> 00008 00009 #include "cardlib.h" 00010 #include "cardregion.h" 00011 #include "cardwindow.h" 00012 #include "cardcolor.h" 00013 00014 HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height); 00015 00016 void PaintRect(HDC hdc, RECT *rect, COLORREF colour); 00017 00018 CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset) 00019 : id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible) 00020 { 00021 width = __cardwidth; 00022 height = __cardheight; 00023 00024 crBackgnd = RGB(0, 64, 100); 00025 00026 uFaceDirType = CS_FACE_UP; 00027 nFaceDirOption = 0; 00028 uEmptyImage = CS_EI_SUNK; 00029 00030 fVisible = visible; 00031 00032 nThreedCount = 1; 00033 00034 Update(); //Update this stack's size+card count 00035 00036 hdcBackGnd = 0; 00037 hbmBackGnd = 0; 00038 hdcDragCard = 0; 00039 hbmDragCard = 0; 00040 00041 nDragCardWidth = 0; 00042 nDragCardHeight = 0; 00043 00044 CanDragCallback = 0; 00045 CanDropCallback = 0; 00046 AddCallback = 0; 00047 RemoveCallback = 0; 00048 ClickCallback = 0; 00049 ClickReleaseCallback = 0; 00050 DblClickCallback = 0; 00051 00052 uDragRule = CS_DRAG_ALL; 00053 uDropRule = CS_DROP_ALL; 00054 00055 xjustify = yjustify = xadjust = yadjust = 0; 00056 00057 nFlashCount = 0; 00058 fFlashVisible = false; 00059 uFlashTimer = (UINT)-1; 00060 00061 fMouseDragging = false; 00062 00063 mxlock = CreateMutex(0, FALSE, 0); 00064 } 00065 00066 CardRegion::~CardRegion() 00067 { 00068 CloseHandle(mxlock); 00069 } 00070 00071 void CardRegion::SetBackColor(COLORREF cr) 00072 { 00073 crBackgnd = cr; 00074 } 00075 00076 int CardRegion::CalcApparentCards(int realnum) 00077 { 00078 return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount; 00079 } 00080 00081 void CardRegion::CalcApparentCards() 00082 { 00083 nNumApparentCards = CalcApparentCards(cardstack.NumCards()); 00084 } 00085 00086 00087 void CardRegion::UpdateSize(void) 00088 { 00089 if(cardstack.NumCards() > 0) 00090 { 00091 if(xoffset > 0) 00092 width = (nNumApparentCards - 1) * xoffset + __cardwidth; 00093 else 00094 width = (nNumApparentCards - 1) * -xoffset + __cardwidth; 00095 00096 if(yoffset > 0) 00097 height = (nNumApparentCards - 1) * yoffset + __cardheight; 00098 else 00099 height = (nNumApparentCards - 1) * -yoffset + __cardheight; 00100 } 00101 else 00102 { 00103 width = __cardwidth; 00104 height = __cardheight; 00105 } 00106 } 00107 00108 CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset) 00109 { 00110 CardRegion *cr; 00111 00112 if(nNumCardRegions == MAXCARDSTACKS) 00113 return FALSE; 00114 00115 cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset); 00116 cr->SetBackColor(crBackgnd); 00117 cr->SetBackCardIdx(nBackCardIdx); 00118 00119 Regions[nNumCardRegions++] = cr; 00120 00121 return cr; 00122 } 00123 00124 int CardRegion::GetOverlapRatio(int x, int y, int w, int h) 00125 { 00126 RECT me, him; 00127 RECT inter; 00128 SetRect(&him, x, y, x+w, y+h); 00129 SetRect(&me, xpos, ypos, xpos+width, ypos+height); 00130 00131 //see if the specified rectangle overlaps us 00132 if(IntersectRect(&inter, &me, &him)) 00133 { 00134 int wi = inter.right - inter.left; 00135 int hi = inter.bottom - inter.top; 00136 00137 int overlap = wi * hi; 00138 int total = width * height; 00139 00140 int percent = (overlap << 16) / total; 00141 return (percent * 100) >> 16; 00142 } 00143 //do not overlap 00144 else 00145 { 00146 return 0; 00147 } 00148 } 00149 00150 bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc) 00151 { 00152 switch(uDragType) 00153 { 00154 case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP: 00155 uDragRule = uDragType; 00156 return true; 00157 00158 case CS_DRAG_CALLBACK: 00159 uDragRule = uDragType; 00160 CanDragCallback = proc; 00161 return true; 00162 00163 default: 00164 return false; 00165 } 00166 } 00167 00168 bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc) 00169 { 00170 switch(uDropType) 00171 { 00172 case CS_DROP_NONE: case CS_DROP_ALL: 00173 uDropRule = uDropType; 00174 return true; 00175 00176 case CS_DROP_CALLBACK: 00177 uDropRule = uDropType; 00178 CanDropCallback = proc; 00179 return true; 00180 00181 default: 00182 return false; 00183 } 00184 } 00185 00186 void CardRegion::SetClickProc(pClickProc proc) 00187 { 00188 ClickCallback = proc; 00189 } 00190 00191 void CardRegion::SetClickReleaseProc(pClickProc proc) 00192 { 00193 ClickReleaseCallback = proc; 00194 } 00195 00196 void CardRegion::SetDblClickProc(pClickProc proc) 00197 { 00198 DblClickCallback = proc; 00199 } 00200 00201 void CardRegion::SetAddCardProc(pAddProc proc) 00202 { 00203 AddCallback = proc; 00204 } 00205 00206 void CardRegion::SetRemoveCardProc(pRemoveProc proc) 00207 { 00208 RemoveCallback = proc; 00209 } 00210 00211 void CardRegion::Update() 00212 { 00213 CalcApparentCards(); 00214 UpdateSize(); 00215 UpdateFaceDir(cardstack); 00216 } 00217 00218 00219 bool CardRegion::SetThreedCount(int count) 00220 { 00221 if(count < 1) 00222 { 00223 return false; 00224 } 00225 else 00226 { 00227 nThreedCount = count; 00228 return true; 00229 } 00230 } 00231 00232 void CardRegion::SetOffsets(int x, int y) 00233 { 00234 xoffset = x; 00235 yoffset = y; 00236 } 00237 00238 void CardRegion::SetPos(int x, int y) 00239 { 00240 xpos = x; 00241 ypos = y; 00242 } 00243 00244 void CardRegion::Show(bool fShow) 00245 { 00246 fVisible = fShow; 00247 } 00248 00249 bool CardRegion::IsVisible() 00250 { 00251 return fVisible; 00252 } 00253 00254 void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust) 00255 { 00256 xjustify = xJustify; 00257 yjustify = yJustify; 00258 xadjust = xAdjust; 00259 yadjust = yAdjust; 00260 } 00261 00262 void CardRegion::SetFaceDirection(UINT uDirType, int nOption) 00263 { 00264 switch(uDirType) 00265 { 00266 case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP: 00267 case CS_FACE_UPDOWN: case CS_FACE_ANY: 00268 uFaceDirType = uDirType; 00269 nFaceDirOption = nOption; 00270 00271 UpdateFaceDir(cardstack); 00272 00273 break; 00274 } 00275 } 00276 00277 UINT CardRegion::GetFaceDirection(int *pnOption) 00278 { 00279 if(pnOption) 00280 *pnOption = nFaceDirOption; 00281 00282 return uFaceDirType; 00283 } 00284 00285 void CardRegion::AdjustPosition(int winwidth, int winheight) 00286 { 00287 Update(); //Update this stack's card count + size 00288 00289 switch(xjustify) 00290 { 00291 default: case CS_XJUST_NONE: break; 00292 00293 case CS_XJUST_CENTER: //centered 00294 xpos = (winwidth - (width & ~0x1)) / 2; 00295 xpos += xadjust; 00296 00297 if(xoffset < 0) xpos += (width - __cardwidth); 00298 00299 break; 00300 00301 case CS_XJUST_RIGHT: //right-aligned 00302 xpos = winwidth - __cardwidth;//width - 20; 00303 xpos += xadjust; 00304 break; 00305 } 00306 00307 switch(yjustify) 00308 { 00309 default: case CS_YJUST_NONE: break; 00310 00311 case CS_YJUST_CENTER: //centered 00312 ypos = (winheight - height) / 2; 00313 ypos += yadjust; 00314 if(yoffset < 0) ypos += (height - __cardheight); 00315 break; 00316 00317 case CS_YJUST_BOTTOM: //bottom-aligned 00318 ypos = winheight - __cardheight;//height - 20; 00319 ypos += yadjust; 00320 break; 00321 } 00322 00323 } 00324 00325 00326 void CardRegion::Flash(int count, int milliseconds) 00327 { 00328 if(count <= 0) return; 00329 00330 nFlashCount = count; 00331 fFlashVisible = false; 00332 uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0); 00333 00334 parentWnd.Redraw(); 00335 } 00336 00337 void CardRegion::StopFlash() 00338 { 00339 if(uFlashTimer != (UINT)-1) 00340 { 00341 KillTimer((HWND)parentWnd, uFlashTimer); 00342 nFlashCount = 0; 00343 uFlashTimer = (UINT)-1; 00344 fFlashVisible = true; 00345 } 00346 } 00347 00348 void CardRegion::DoFlash() 00349 { 00350 if(uFlashTimer != (UINT)-1) 00351 { 00352 fFlashVisible = !fFlashVisible; 00353 00354 if(--nFlashCount == 0) 00355 { 00356 KillTimer((HWND)parentWnd, uFlashTimer); 00357 uFlashTimer = (UINT)-1; 00358 fFlashVisible = true; 00359 } 00360 00361 parentWnd.Redraw(); 00362 } 00363 } 00364 00365 int CardRegion::Id() 00366 { 00367 return id; 00368 } 00369 00370 void CardRegion::SetEmptyImage(UINT uImage) 00371 { 00372 switch(uImage) 00373 { 00374 case CS_EI_NONE: 00375 case CS_EI_SUNK: 00376 case CS_EI_CIRC: 00377 case CS_EI_X: 00378 uEmptyImage = uImage; 00379 break; 00380 00381 default: 00382 uEmptyImage = CS_EI_NONE; 00383 break; 00384 } 00385 00386 } 00387 00388 void CardRegion::SetBackCardIdx(UINT uBackIdx) 00389 { 00390 if(uBackIdx >= 52 && uBackIdx <= 68) 00391 nBackCardIdx = uBackIdx; 00392 } 00393 00394 void CardRegion::SetCardStack(const CardStack &cs) 00395 { 00396 //make a complete copy of the specified stack.. 00397 cardstack = cs; 00398 00399 // Update the face-direction and stack-size 00400 Update(); 00401 } 00402 00403 const CardStack & CardRegion::GetCardStack() 00404 { 00405 //return reference to our internal stack 00406 return cardstack; 00407 } 00408 00409 // 00410 // Update specified card-stack using THIS stack's 00411 // face direction rules! 00412 // 00413 void CardRegion::UpdateFaceDir(CardStack &cards) 00414 { 00415 int i, n, num; 00416 00417 num = cards.NumCards(); 00418 00419 //Now apply the face direction rules.. 00420 switch(uFaceDirType) 00421 { 00422 case CS_FACE_UP: 00423 00424 for(i = 0; i < num; i++) 00425 { 00426 cards[i].SetFaceUp(true); 00427 } 00428 00429 break; 00430 00431 case CS_FACE_DOWN: 00432 00433 for(i = 0; i < num; i++) 00434 { 00435 cards[i].SetFaceUp(false); 00436 } 00437 00438 break; 00439 00440 case CS_FACE_DOWNUP: 00441 00442 num = cardstack.NumCards(); 00443 n = min(nFaceDirOption, num); 00444 00445 //bottom n cards.. 00446 for(i = 0; i < n; i++) 00447 { 00448 cards[num - i - 1].SetFaceUp(false); 00449 } 00450 00451 for(i = n; i < num; i++) 00452 { 00453 cards[num - i - 1].SetFaceUp(true); 00454 } 00455 00456 break; 00457 00458 case CS_FACE_UPDOWN: 00459 00460 num = cardstack.NumCards(); 00461 n = min(nFaceDirOption, num); 00462 00463 for(i = 0; i < n; i++) 00464 { 00465 cards[num - i - 1].SetFaceUp(true); 00466 } 00467 00468 for(i = n; i < num; i++) 00469 { 00470 cards[num - i - 1].SetFaceUp(false); 00471 } 00472 00473 break; 00474 00475 case CS_FACE_ANY: //cards can be any orientation 00476 default: 00477 break; 00478 } 00479 } 00480 00481 bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate) 00482 { 00483 HDC hdc; 00484 00485 int x, y; 00486 00487 if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; } 00488 00489 if(nNumCards < 0 || nNumCards > cardstack.NumCards()) 00490 return false; 00491 00492 x = xpos + xoffset * (nNumApparentCards - nNumCards); 00493 y = ypos + yoffset * (nNumApparentCards - nNumCards); 00494 00495 oldx = x; 00496 oldy = y; 00497 00498 dragstack = cardstack.Pop(nNumCards); 00499 00500 //Alter the drag-stack so that it's cards are the same way up 00501 //as the destination. Use the destination's drag-rules 00502 //instead of this ones!! 00503 CardStack temp; 00504 temp.Push(pDestStack->GetCardStack()); 00505 temp.Push(dragstack); 00506 00507 pDestStack->UpdateFaceDir(temp); 00508 00509 dragstack = temp.Pop(nNumCards); 00510 00511 if(fAnimate) 00512 { 00513 iNumDragCards = nNumCards; 00514 PrepareDragBitmaps(nNumCards); 00515 } 00516 00517 Update(); //Update this stack's size+card count 00518 00519 if(fAnimate) 00520 { 00521 hdc = GetDC((HWND)parentWnd); 00522 00523 ZoomCard(hdc, x, y, pDestStack); 00524 00525 ReleaseDC((HWND)parentWnd, hdc); 00526 ReleaseDragBitmaps(); 00527 } 00528 00529 // Get a copy of the cardstack 00530 CardStack cs = pDestStack->GetCardStack(); 00531 cs.Push(dragstack); 00532 00533 pDestStack->SetCardStack(cs); 00534 00535 //cs = pDestStack->GetCardStack(); 00536 //pDestStack->Update(); 00537 //pDestStack->UpdateFaceDir(cs); 00538 00539 RedrawIfNotDim(pDestStack, false); 00540 00541 //forcedfacedir = -1; 00542 return true; 00543 } 00544 00545 // 00546 // Simple wrappers 00547 // 00548 int CardRegion::NumCards() const 00549 { 00550 if(fMouseDragging) 00551 return cardstack.NumCards() + dragstack.NumCards(); 00552 else 00553 return cardstack.NumCards(); 00554 } 00555 00556 bool CardRegion::Lock() 00557 { 00558 DWORD dw = WaitForSingleObject(mxlock, 0); 00559 00560 if(dw == WAIT_OBJECT_0) 00561 { 00562 //TRACE("LockStack succeeded\n"); 00563 return true; 00564 } 00565 else 00566 { 00567 //TRACE("LockStack failed\n"); 00568 return false; 00569 } 00570 return false; 00571 } 00572 00573 bool CardRegion::UnLock() 00574 { 00575 if(ReleaseMutex(mxlock)) 00576 { 00577 //TRACE("Unlocking stack\n"); 00578 return true; 00579 } 00580 else 00581 { 00582 //TRACE("Unlocking stack failed\n"); 00583 return false; 00584 } 00585 } 00586 00587 bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num) 00588 { 00589 //search the stack for the specified card value... 00590 while(num--) 00591 { 00592 for(int i = 0; i < cardstack.NumCards(); i++) 00593 { 00594 if(cardstack[i].HiVal() == value) 00595 { 00596 //swap the card with one at top pos... 00597 Card card = cardstack.RemoveCard(i); 00598 cardstack.Push(card); 00599 00600 Redraw(); 00601 00602 MoveCard(pDestStack, 1, true); 00603 break; 00604 } 00605 } 00606 } 00607 00608 return true; 00609 } 00610 00611 // 00612 // Redraw the current stack if it has a different 00613 // layout than the comparison stack. 00614 // 00615 void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw) 00616 { 00617 // 00618 // 00619 // 00620 if( pCompare->xoffset != xoffset || 00621 pCompare->yoffset != yoffset || 00622 pCompare->nThreedCount != nThreedCount || 00623 pCompare->uFaceDirType != uFaceDirType || 00624 pCompare->uFaceDirType != CS_FACE_ANY 00625 ) 00626 { 00627 if(fFullRedraw) 00628 parentWnd.Redraw(); 00629 else 00630 pCompare->Redraw(); 00631 } 00632 00633 } 00634 00635 // 00636 // SimulateDrag mimicks the complete drag+drop process. 00637 // It basically just a MoveCard(..), but it calls the 00638 // event callbacks as well. 00639 // 00640 bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate) 00641 { 00642 if(pDestStack == 0) 00643 return false; 00644 00645 if(CanDragCards(iNumDragCards) != false) 00646 { 00647 if(pDestStack->CanDropCards(cardstack)) 00648 { 00649 MoveCard(pDestStack, iNumDragCards, fAnimate); 00650 00651 if(RemoveCallback) 00652 RemoveCallback(*this, iNumDragCards); 00653 00654 if(pDestStack->AddCallback) 00655 pDestStack->AddCallback(*pDestStack, pDestStack->cardstack); 00656 00657 RedrawIfNotDim(pDestStack, true); 00658 } 00659 00660 } 00661 00662 return true; 00663 } Generated on Thu Feb 9 04:59:25 2012 for ReactOS by
1.6.3
|