mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 00:54:40 +00:00
imported catch-22 sol clone with authors permission
svn path=/trunk/; revision=13904
This commit is contained in:
parent
59b8be68dc
commit
e415037205
32 changed files with 7127 additions and 0 deletions
22
rosapps/games/solitaire/ReadMe.txt
Normal file
22
rosapps/games/solitaire/ReadMe.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
Solitaire for ReactOS
|
||||
|
||||
/*****************************************
|
||||
A complete working example of the CardLib
|
||||
card-game library.
|
||||
|
||||
Freeware
|
||||
Copyright J Brown 2001
|
||||
|
||||
Updates at http://www.catch22.net
|
||||
|
||||
******************************************/
|
||||
|
||||
The author has given permission to use these sources
|
||||
under Public Domain. Do what thou will but please give
|
||||
credit where credit is due.
|
||||
|
||||
If you wish to use cardlib to write another card game
|
||||
for ReactOS please make cardlib a static lib.
|
||||
|
||||
-sedwards
|
||||
|
105
rosapps/games/solitaire/cardlib/card.h
Normal file
105
rosapps/games/solitaire/cardlib/card.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// CardLib - Card class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
|
||||
#ifndef _CARD_INCLUDED
|
||||
#define _CARD_INCLUDED
|
||||
|
||||
enum eSuit { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 };
|
||||
enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7,
|
||||
Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 };
|
||||
|
||||
inline int MAKE_CARD(int Value, int Suit)
|
||||
{
|
||||
if(Value < 1) Value = 1;
|
||||
if(Value == 14) Value = 1;
|
||||
if(Value > 13) Value = 13;
|
||||
|
||||
if(Suit < 0) Suit = 0;
|
||||
if(Suit > 3) Suit = 3;
|
||||
|
||||
return ((Value - 1) * 4 + Suit);
|
||||
}
|
||||
|
||||
class Card
|
||||
{
|
||||
friend class CardStack;
|
||||
|
||||
public:
|
||||
|
||||
Card()
|
||||
{
|
||||
nValue = 0; //ace of spades by default
|
||||
fFaceUp = true;
|
||||
}
|
||||
|
||||
Card(int value, int suit) //specify a face value [1-13] and suit [0-3]
|
||||
{
|
||||
nValue = MAKE_CARD(value, suit);
|
||||
fFaceUp = true;
|
||||
}
|
||||
|
||||
Card(int index) //specify a 0-51 index
|
||||
{
|
||||
if(index < 0) index = 0;
|
||||
if(index > 51) index = 51;
|
||||
|
||||
nValue = index;
|
||||
fFaceUp = true;
|
||||
}
|
||||
|
||||
int Suit() const
|
||||
{
|
||||
return (nValue % 4);
|
||||
}
|
||||
|
||||
int LoVal() const
|
||||
{
|
||||
return (nValue / 4) + 1;
|
||||
}
|
||||
|
||||
int HiVal() const
|
||||
{
|
||||
return ((nValue < 4) ? 14 : (nValue / 4) + 1);
|
||||
}
|
||||
|
||||
int Idx() const //unique value (0-51 etc)
|
||||
{
|
||||
return nValue;
|
||||
}
|
||||
|
||||
bool FaceUp() const
|
||||
{
|
||||
return fFaceUp;
|
||||
}
|
||||
|
||||
bool FaceDown() const
|
||||
{
|
||||
return !fFaceUp;
|
||||
}
|
||||
|
||||
void SetFaceUp(bool fTrue)
|
||||
{
|
||||
fFaceUp = fTrue;
|
||||
}
|
||||
|
||||
bool IsBlack() const
|
||||
{
|
||||
return Suit() == 0 || Suit() == 3;
|
||||
}
|
||||
|
||||
bool IsRed() const
|
||||
{
|
||||
return !IsBlack();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int nValue;
|
||||
bool fFaceUp;
|
||||
};
|
||||
|
||||
#endif
|
281
rosapps/games/solitaire/cardlib/cardbitmaps.cpp
Normal file
281
rosapps/games/solitaire/cardlib/cardbitmaps.cpp
Normal file
|
@ -0,0 +1,281 @@
|
|||
//
|
||||
// CardLib - Card bitmap support
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "globals.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
#ifndef __REACTOS__
|
||||
#pragma comment( lib, "..\\CardLib\\cards16.lib" )
|
||||
|
||||
extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR );
|
||||
extern "C" void WINAPI FreeLibrary16( HINSTANCE );
|
||||
#endif
|
||||
|
||||
#define NUMCARDBITMAPS (52+16)
|
||||
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF col);
|
||||
|
||||
void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight)
|
||||
{
|
||||
HBITMAP hBitmap;
|
||||
HDC hdcCard;
|
||||
HANDLE hOld;
|
||||
int i, xpos;
|
||||
int width, height;
|
||||
BITMAP bmp;
|
||||
|
||||
for(i = 0; i < NUMCARDBITMAPS; i++)
|
||||
{
|
||||
//convert into the range used by the cdt_xxx functions
|
||||
int val;
|
||||
|
||||
if(i < 52) val = (i % 4) * 13 + (i/4);
|
||||
else val = i;
|
||||
|
||||
hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1));
|
||||
GetObject(hBitmap, sizeof(bmp), &bmp);
|
||||
|
||||
width = bmp.bmWidth;
|
||||
height = bmp.bmHeight;
|
||||
|
||||
if(i == 0) //if first time through, create BIG bitmap..
|
||||
{
|
||||
HDC hdc = GetDC(0);
|
||||
__hdcCardBitmaps = CreateCompatibleDC(hdc);
|
||||
__hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height);
|
||||
SelectObject(__hdcCardBitmaps, __hbmCardBitmaps);
|
||||
|
||||
hdcCard = CreateCompatibleDC(0);
|
||||
|
||||
ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
hOld = SelectObject(hdcCard, hBitmap);
|
||||
BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY);
|
||||
SelectObject(hdcCard, hOld);
|
||||
|
||||
//Now draw a black border around each card...
|
||||
xpos = i*width;
|
||||
MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0);
|
||||
LineTo(__hdcCardBitmaps, xpos+width - 3, 0);
|
||||
LineTo(__hdcCardBitmaps, xpos+width - 1, 2);
|
||||
LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3); //vertical
|
||||
LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1);
|
||||
LineTo(__hdcCardBitmaps, xpos+2, height - 1);
|
||||
LineTo(__hdcCardBitmaps, xpos+0, height - 3);
|
||||
LineTo(__hdcCardBitmaps, xpos+0, 2);
|
||||
LineTo(__hdcCardBitmaps, xpos+2, 0);
|
||||
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
|
||||
DeleteDC(hdcCard);
|
||||
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
|
||||
}
|
||||
|
||||
void LoadCardBitmaps(void)
|
||||
{
|
||||
HINSTANCE hCardDll;
|
||||
|
||||
|
||||
//If Windows NT/2000/XP
|
||||
if(GetVersion() < 0x80000000)
|
||||
{
|
||||
hCardDll = LoadLibrary("cards.dll");
|
||||
|
||||
if(hCardDll == 0)
|
||||
{
|
||||
MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);
|
||||
PostQuitMessage(0);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);
|
||||
|
||||
FreeLibrary(hCardDll);
|
||||
}
|
||||
#ifndef __REACTOS__
|
||||
//Else, Win9X
|
||||
else
|
||||
{
|
||||
hCardDll = LoadLibrary16("cards.dll");
|
||||
|
||||
if(hCardDll == 0)
|
||||
{
|
||||
MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);
|
||||
PostQuitMessage(0);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);
|
||||
|
||||
FreeLibrary16(hCardDll);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FreeCardBitmaps()
|
||||
{
|
||||
DeleteObject (__hbmCardBitmaps);
|
||||
DeleteDC (__hdcCardBitmaps);
|
||||
}
|
||||
//
|
||||
// Paint a checkered rectangle, with each alternate
|
||||
// pixel being assigned a different colour
|
||||
//
|
||||
static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
|
||||
{
|
||||
static WORD wCheckPat[8] =
|
||||
{
|
||||
0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
|
||||
};
|
||||
|
||||
HBITMAP hbmp;
|
||||
HBRUSH hbr, hbrold;
|
||||
COLORREF fgold, bgold;
|
||||
|
||||
hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
|
||||
hbr = CreatePatternBrush(hbmp);
|
||||
|
||||
//UnrealizeObject(hbr);
|
||||
|
||||
SetBrushOrgEx(hdc, rect->left, rect->top, 0);
|
||||
|
||||
hbrold = (HBRUSH)SelectObject(hdc, hbr);
|
||||
|
||||
fgold = SetTextColor(hdc, fg);
|
||||
bgold = SetBkColor(hdc, bg);
|
||||
|
||||
PatBlt(hdc, rect->left, rect->top,
|
||||
rect->right - rect->left,
|
||||
rect->bottom - rect->top,
|
||||
PATCOPY);
|
||||
|
||||
SetBkColor(hdc, bgold);
|
||||
SetTextColor(hdc, fgold);
|
||||
|
||||
SelectObject(hdc, hbrold);
|
||||
DeleteObject(hbr);
|
||||
DeleteObject(hbmp);
|
||||
}
|
||||
|
||||
void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2)
|
||||
{
|
||||
if(bg) *bg = crBase;
|
||||
if(fg) *fg = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140);
|
||||
if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4);
|
||||
if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2);
|
||||
}
|
||||
|
||||
HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height)
|
||||
{
|
||||
HANDLE hold, hpold;
|
||||
HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height);
|
||||
|
||||
HPEN hpfg, hpbg, hpsh, hpsh2;
|
||||
|
||||
RECT rect;
|
||||
COLORREF fg, bg, shadow, shadow2;
|
||||
|
||||
GetSinkCols(col, &fg, &bg, &shadow, &shadow2);
|
||||
|
||||
hold = SelectObject(hdc, hbm);
|
||||
|
||||
//fill with a solid base colour
|
||||
SetRect(&rect, 0,0,width,height);
|
||||
PaintRect(hdc, &rect, MAKE_PALETTERGB(bg));
|
||||
|
||||
//draw the outline
|
||||
hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg));
|
||||
hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg));
|
||||
hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow));
|
||||
hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2));
|
||||
|
||||
hpold = SelectObject(hdc, hpsh);
|
||||
MoveToEx(hdc, 2, 0, NULL);
|
||||
LineTo (hdc, width-3,0);
|
||||
LineTo (hdc, width-1, 2);
|
||||
|
||||
SelectObject(hdc, hpold);
|
||||
hpold = SelectObject(hdc, hpsh2);
|
||||
LineTo (hdc, width-1, height-3); //vertical
|
||||
LineTo (hdc, width-3, height-1);
|
||||
LineTo (hdc, 2, height-1);
|
||||
LineTo (hdc, 0, height-3);
|
||||
SelectObject(hdc, hpold);
|
||||
hpold = SelectObject(hdc, hpsh);
|
||||
|
||||
//MoveToEx( hdc, 0, height-3,0);
|
||||
LineTo (hdc, 0, 2);
|
||||
LineTo (hdc, 2, 0);
|
||||
|
||||
SelectObject(hdc, hpold);
|
||||
|
||||
//draw the highlight (vertical)
|
||||
hpold = SelectObject(hdc, hpfg);
|
||||
MoveToEx(hdc, width - 2, 3, NULL);
|
||||
LineTo (hdc, width - 2, height - 2);
|
||||
|
||||
//(horz)
|
||||
MoveToEx(hdc, width - 3, height-2, NULL);
|
||||
LineTo (hdc, 3, height-2);
|
||||
SelectObject(hdc, hpold);
|
||||
|
||||
//draw the background
|
||||
InflateRect(&rect, -2, -2);
|
||||
DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg));
|
||||
|
||||
//overwrite the top-left background pixel
|
||||
SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg));
|
||||
|
||||
DeleteObject(hpsh);
|
||||
DeleteObject(hpsh2);
|
||||
DeleteObject(hpfg);
|
||||
DeleteObject(hpbg);
|
||||
|
||||
|
||||
return hbm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CopyColor(PALETTEENTRY *pe, COLORREF col)
|
||||
{
|
||||
pe->peBlue = GetBValue(col);
|
||||
pe->peGreen = GetGValue(col);
|
||||
pe->peRed = GetRValue(col);
|
||||
pe->peFlags = 0;
|
||||
}
|
||||
|
||||
HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours)
|
||||
{
|
||||
LOGPALETTE *lp;
|
||||
HPALETTE hPalette;
|
||||
|
||||
// Allocate memory for the logical palette
|
||||
lp = (LOGPALETTE *)HeapAlloc(
|
||||
GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours);
|
||||
|
||||
lp->palNumEntries = nNumColours;
|
||||
lp->palVersion = 0x300;
|
||||
|
||||
//copy the colours into the logical palette format
|
||||
for(int i = 0; i < nNumColours; i++)
|
||||
{
|
||||
CopyColor(&lp->palPalEntry[i], cols[i]);
|
||||
}
|
||||
|
||||
// create palette!
|
||||
hPalette = CreatePalette(lp);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, lp);
|
||||
|
||||
return hPalette;
|
||||
}
|
489
rosapps/games/solitaire/cardlib/cardbutton.cpp
Normal file
489
rosapps/games/solitaire/cardlib/cardbutton.cpp
Normal file
|
@ -0,0 +1,489 @@
|
|||
//
|
||||
// CardLib - CardButton class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardbutton.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
HPALETTE UseNicePalette(HDC, HPALETTE);
|
||||
void RestorePalette(HDC, HPALETTE);
|
||||
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
|
||||
|
||||
CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,
|
||||
int x, int y, int width, int height)
|
||||
|
||||
: parentWnd(parent), id(Id), fVisible(visible), uStyle(Style), ButtonCallback(0)
|
||||
{
|
||||
crText = RGB(255,255,255);
|
||||
crBack = RGB(0, 128, 0);
|
||||
|
||||
xadjust = 0;
|
||||
yadjust = 0;
|
||||
xjustify = 0;
|
||||
yjustify = 0;
|
||||
|
||||
fMouseDown = false;
|
||||
fButtonDown = false;
|
||||
|
||||
hIcon = 0;
|
||||
|
||||
SetText(szText);
|
||||
Move(x, y, width, height);
|
||||
|
||||
mxlock = CreateMutex(0, FALSE, 0);
|
||||
|
||||
hFont = 0;
|
||||
}
|
||||
|
||||
CardButton::~CardButton()
|
||||
{
|
||||
CloseHandle(mxlock);
|
||||
}
|
||||
|
||||
void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)
|
||||
{
|
||||
RECT fill;
|
||||
|
||||
HANDLE hOld;
|
||||
|
||||
HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));
|
||||
HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));
|
||||
HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);
|
||||
|
||||
int x = rect->left;
|
||||
int y = rect->top;
|
||||
int width = rect->right-rect->left - 1;
|
||||
int height = rect->bottom-rect->top - 1;
|
||||
|
||||
SetRect(&fill, x+1, y+1, x+width-1, y+height-1);
|
||||
|
||||
int one = 1;
|
||||
|
||||
if(!fNormal)
|
||||
{
|
||||
x += width;
|
||||
y += height;
|
||||
width = -width;
|
||||
height = -height;
|
||||
one = -1;
|
||||
OffsetRect(&fill, 1, 1);
|
||||
}
|
||||
|
||||
if(fNormal)
|
||||
hOld = SelectObject(hdc, hhi);
|
||||
else
|
||||
hOld = SelectObject(hdc, hhi);
|
||||
|
||||
MoveToEx(hdc, x, y+height, 0);
|
||||
LineTo(hdc, x, y);
|
||||
LineTo(hdc, x+width, y);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
hOld = SelectObject(hdc, hbl);
|
||||
LineTo(hdc, x+width, y+height);
|
||||
LineTo(hdc, x-one, y+height);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
hOld = SelectObject(hdc, hsh);
|
||||
MoveToEx(hdc, x+one, y+height-one, 0);
|
||||
LineTo(hdc, x+width-one, y+height-one);
|
||||
LineTo(hdc, x+width-one, y);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));
|
||||
|
||||
DeleteObject(hhi);
|
||||
DeleteObject(hsh);
|
||||
}
|
||||
|
||||
void CardButton::Clip(HDC hdc)
|
||||
{
|
||||
if(fVisible == false) return;
|
||||
|
||||
ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void CardButton::Draw(HDC hdc, bool fNormal)
|
||||
{
|
||||
SIZE textsize;
|
||||
int x, y; //text x, y
|
||||
int ix, iy; //icon x, y
|
||||
int iconwidth = 0;
|
||||
|
||||
RECT cliprect;
|
||||
|
||||
if(fVisible == 0) return;
|
||||
|
||||
if(hFont == 0)
|
||||
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
||||
else
|
||||
SelectObject(hdc, hFont);
|
||||
|
||||
GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
x = rect.left + 32 + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(uStyle & CB_ALIGN_LEFT)
|
||||
{
|
||||
x = rect.left + iconwidth;
|
||||
}
|
||||
else if(uStyle & CB_ALIGN_RIGHT)
|
||||
{
|
||||
x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);
|
||||
}
|
||||
else //centered
|
||||
{
|
||||
x = rect.right - rect.left - iconwidth;
|
||||
x = (x - textsize.cx) / 2;
|
||||
x += rect.left + iconwidth;
|
||||
}
|
||||
}
|
||||
|
||||
y = rect.bottom - rect.top;
|
||||
y = (y - textsize.cy) / 2;
|
||||
y += rect.top;
|
||||
|
||||
//calc icon position..
|
||||
ix = rect.left + 4;
|
||||
iy = rect.top + (rect.bottom-rect.top-32) / 2;
|
||||
|
||||
//if button is pressed, then shift text
|
||||
if(fNormal == false && (uStyle & CB_PUSHBUTTON))
|
||||
{
|
||||
x += 1;
|
||||
y += 1;
|
||||
ix += 1;
|
||||
iy += 1;
|
||||
}
|
||||
|
||||
SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);
|
||||
ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);
|
||||
|
||||
//
|
||||
// Calc icon pos
|
||||
//
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);
|
||||
}
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
DrawRect(hdc, &rect, fNormal);
|
||||
|
||||
SetBkColor(hdc, MAKE_PALETTERGB(crBack));
|
||||
SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
|
||||
|
||||
SelectClipRgn(hdc, 0);
|
||||
|
||||
ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBkColor(hdc, MAKE_PALETTERGB(crBack));
|
||||
SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
|
||||
|
||||
SelectClipRgn(hdc, 0);
|
||||
|
||||
ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
|
||||
}
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));
|
||||
DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);
|
||||
DeleteObject(hbr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CardButton::AdjustPosition(int winwidth, int winheight)
|
||||
{
|
||||
int width = rect.right-rect.left;
|
||||
int height = rect.bottom-rect.top;
|
||||
|
||||
width = width & ~0x1;
|
||||
|
||||
switch(xjustify)
|
||||
{
|
||||
case CS_XJUST_NONE:
|
||||
break;
|
||||
|
||||
case CS_XJUST_CENTER: //centered
|
||||
rect.left = (winwidth - (width)) / 2;
|
||||
rect.left += xadjust;
|
||||
rect.right = rect.left+width;
|
||||
break;
|
||||
|
||||
case CS_XJUST_RIGHT: //right-aligned
|
||||
rect.left = winwidth - width;
|
||||
rect.left += xadjust;
|
||||
rect.right = rect.left+width;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(yjustify)
|
||||
{
|
||||
case CS_YJUST_NONE:
|
||||
break;
|
||||
|
||||
case CS_YJUST_CENTER: //centered
|
||||
rect.top = (winheight - (height)) / 2;
|
||||
rect.top += yadjust;
|
||||
rect.bottom = rect.top+height;
|
||||
break;
|
||||
|
||||
case CS_YJUST_BOTTOM: //right-aligned
|
||||
rect.top = winheight - height;
|
||||
rect.top += yadjust;
|
||||
rect.bottom = rect.top+height;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CardButton::OnLButtonDown(HWND hwnd, int x, int y)
|
||||
{
|
||||
if((uStyle & CB_PUSHBUTTON) == 0)
|
||||
return 0;
|
||||
|
||||
//make sure that the user is allowed to do something
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseMutex(mxlock);
|
||||
}
|
||||
|
||||
fMouseDown = true;
|
||||
fButtonDown = true;
|
||||
|
||||
Redraw();
|
||||
|
||||
SetCapture(hwnd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CardButton::OnMouseMove(HWND hwnd, int x, int y)
|
||||
{
|
||||
if(fMouseDown)
|
||||
{
|
||||
bool fOldButtonDown = fButtonDown;
|
||||
|
||||
POINT pt;
|
||||
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
|
||||
if(PtInRect(&rect, pt))
|
||||
fButtonDown = true;
|
||||
else
|
||||
fButtonDown = false;
|
||||
|
||||
if(fButtonDown != fOldButtonDown)
|
||||
Redraw();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CardButton::OnLButtonUp(HWND hwnd, int x, int y)
|
||||
{
|
||||
if(fMouseDown)
|
||||
{
|
||||
fMouseDown = false;
|
||||
fButtonDown = false;
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
Redraw();
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
//if have clicked the button
|
||||
if(parentWnd.CardButtonFromPoint(x, y) == this)
|
||||
{
|
||||
if(ButtonCallback)
|
||||
{
|
||||
ButtonCallback(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND hwnd = (HWND)parentWnd;
|
||||
SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _countof(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)
|
||||
{
|
||||
CardButton *cb;
|
||||
|
||||
if(nNumButtons == MAXBUTTONS)
|
||||
return 0;
|
||||
|
||||
cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);
|
||||
Buttons[nNumButtons++] = cb;
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
cb->SetBackColor(CardButton::GetFace(crBackgnd));
|
||||
//cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));
|
||||
cb->SetForeColor(RGB(255,255,255));
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->SetBackColor(crBackgnd);
|
||||
cb->SetForeColor(RGB(255,255,255));
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
void CardButton::SetText(TCHAR *lpszFormat, ...)
|
||||
{
|
||||
int count;
|
||||
|
||||
va_list args;
|
||||
va_start(args, lpszFormat);
|
||||
|
||||
count = wvsprintf(szText, lpszFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int CardButton::Id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void CardButton::Show(bool fShow)
|
||||
{
|
||||
fVisible = fShow;
|
||||
}
|
||||
|
||||
void CardButton::Move(int x, int y, int width, int height)
|
||||
{
|
||||
SetRect(&rect, x, y, x+width, y+height);
|
||||
}
|
||||
|
||||
void CardButton::Redraw()
|
||||
{
|
||||
HDC hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);
|
||||
|
||||
Draw(hdc, !fButtonDown);
|
||||
|
||||
RestorePalette(hdc, hOldPal);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
}
|
||||
|
||||
void CardButton::SetForeColor(COLORREF cr)
|
||||
{
|
||||
crText = cr;
|
||||
}
|
||||
|
||||
void CardButton::SetBackColor(COLORREF cr)
|
||||
{
|
||||
crBack = cr;
|
||||
|
||||
crHighlight = GetHighlight(cr);
|
||||
crShadow = GetShadow(cr);
|
||||
|
||||
//crHighlight = ScaleLumRGB(cr, +0.25);
|
||||
//crShadow = ScaleLumRGB(cr, -0.25);
|
||||
}
|
||||
|
||||
// Static member
|
||||
COLORREF CardButton::GetHighlight(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);
|
||||
}
|
||||
|
||||
// Static member
|
||||
COLORREF CardButton::GetShadow(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25);
|
||||
}
|
||||
|
||||
COLORREF CardButton::GetFace(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);
|
||||
}
|
||||
|
||||
void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
|
||||
{
|
||||
xadjust = xAdjust;
|
||||
yadjust = yAdjust;
|
||||
xjustify = xJustify;
|
||||
yjustify = yJustify;
|
||||
}
|
||||
|
||||
void CardButton::SetIcon(HICON hicon, bool fRedraw)
|
||||
{
|
||||
hIcon = hicon;
|
||||
|
||||
if(fRedraw)
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void CardButton::SetFont(HFONT font)
|
||||
{
|
||||
//don't delete the existing font..
|
||||
hFont = font;
|
||||
}
|
||||
|
||||
void CardButton::SetButtonProc(pButtonProc proc)
|
||||
{
|
||||
ButtonCallback = proc;
|
||||
}
|
||||
|
||||
bool CardButton::Lock()
|
||||
{
|
||||
DWORD dw = WaitForSingleObject(mxlock, 0);
|
||||
|
||||
if(dw == WAIT_OBJECT_0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardButton::UnLock()
|
||||
{
|
||||
if(ReleaseMutex(mxlock))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CardButton::SetStyle(UINT style)
|
||||
{
|
||||
uStyle = style;
|
||||
}
|
||||
|
||||
UINT CardButton::GetStyle()
|
||||
{
|
||||
return uStyle;
|
||||
}
|
489
rosapps/games/solitaire/cardlib/cardbutton.cpp.bak
Normal file
489
rosapps/games/solitaire/cardlib/cardbutton.cpp.bak
Normal file
|
@ -0,0 +1,489 @@
|
|||
//
|
||||
// CardLib - CardButton class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardbutton.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
HPALETTE UseNicePalette(HDC, HPALETTE);
|
||||
void RestorePalette(HDC, HPALETTE);
|
||||
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
|
||||
|
||||
CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,
|
||||
int x, int y, int width, int height)
|
||||
|
||||
: parentWnd(parent), id(Id), fVisible(visible), uStyle(Style), ButtonCallback(0)
|
||||
{
|
||||
crText = RGB(255,255,255);
|
||||
crBack = RGB(0, 128, 0);
|
||||
|
||||
xadjust = 0;
|
||||
yadjust = 0;
|
||||
xjustify = 0;
|
||||
yjustify = 0;
|
||||
|
||||
fMouseDown = false;
|
||||
fButtonDown = false;
|
||||
|
||||
hIcon = 0;
|
||||
|
||||
SetText(szText);
|
||||
Move(x, y, width, height);
|
||||
|
||||
mxlock = CreateMutex(0, FALSE, 0);
|
||||
|
||||
hFont = 0;
|
||||
}
|
||||
|
||||
CardButton::~CardButton()
|
||||
{
|
||||
CloseHandle(mxlock);
|
||||
}
|
||||
|
||||
void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)
|
||||
{
|
||||
RECT fill;
|
||||
|
||||
HANDLE hOld;
|
||||
|
||||
HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));
|
||||
HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));
|
||||
HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);
|
||||
|
||||
int x = rect->left;
|
||||
int y = rect->top;
|
||||
int width = rect->right-rect->left - 1;
|
||||
int height = rect->bottom-rect->top - 1;
|
||||
|
||||
SetRect(&fill, x+1, y+1, x+width-1, y+height-1);
|
||||
|
||||
int one = 1;
|
||||
|
||||
if(!fNormal)
|
||||
{
|
||||
x += width;
|
||||
y += height;
|
||||
width = -width;
|
||||
height = -height;
|
||||
one = -1;
|
||||
OffsetRect(&fill, 1, 1);
|
||||
}
|
||||
|
||||
if(fNormal)
|
||||
hOld = SelectObject(hdc, hhi);
|
||||
else
|
||||
hOld = SelectObject(hdc, hhi);
|
||||
|
||||
MoveToEx(hdc, x, y+height, 0);
|
||||
LineTo(hdc, x, y);
|
||||
LineTo(hdc, x+width, y);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
hOld = SelectObject(hdc, hbl);
|
||||
LineTo(hdc, x+width, y+height);
|
||||
LineTo(hdc, x-one, y+height);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
hOld = SelectObject(hdc, hsh);
|
||||
MoveToEx(hdc, x+one, y+height-one, 0);
|
||||
LineTo(hdc, x+width-one, y+height-one);
|
||||
LineTo(hdc, x+width-one, y);
|
||||
SelectObject(hdc, hOld);
|
||||
|
||||
PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));
|
||||
|
||||
DeleteObject(hhi);
|
||||
DeleteObject(hsh);
|
||||
}
|
||||
|
||||
void CardButton::Clip(HDC hdc)
|
||||
{
|
||||
if(fVisible == false) return;
|
||||
|
||||
ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void CardButton::Draw(HDC hdc, bool fNormal)
|
||||
{
|
||||
SIZE textsize;
|
||||
int x, y; //text x, y
|
||||
int ix, iy; //icon x, y
|
||||
int iconwidth = 0;
|
||||
|
||||
RECT cliprect;
|
||||
|
||||
if(fVisible == 0) return;
|
||||
|
||||
if(hFont == 0)
|
||||
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
||||
else
|
||||
SelectObject(hdc, hFont);
|
||||
|
||||
GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
x = rect.left + 32 + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(uStyle & CB_ALIGN_LEFT)
|
||||
{
|
||||
x = rect.left + iconwidth;
|
||||
}
|
||||
else if(uStyle & CB_ALIGN_RIGHT)
|
||||
{
|
||||
x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);
|
||||
}
|
||||
else //centered
|
||||
{
|
||||
x = rect.right - rect.left - iconwidth;
|
||||
x = (x - textsize.cx) / 2;
|
||||
x += rect.left + iconwidth;
|
||||
}
|
||||
}
|
||||
|
||||
y = rect.bottom - rect.top;
|
||||
y = (y - textsize.cy) / 2;
|
||||
y += rect.top;
|
||||
|
||||
//calc icon position..
|
||||
ix = rect.left + 4;
|
||||
iy = rect.top + (rect.bottom-rect.top-32) / 2;
|
||||
|
||||
//if button is pressed, then shift text
|
||||
if(fNormal == false && (uStyle & CB_PUSHBUTTON))
|
||||
{
|
||||
x += 1;
|
||||
y += 1;
|
||||
ix += 1;
|
||||
iy += 1;
|
||||
}
|
||||
|
||||
SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);
|
||||
ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);
|
||||
|
||||
//
|
||||
// Calc icon pos
|
||||
//
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);
|
||||
}
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
DrawRect(hdc, &rect, fNormal);
|
||||
|
||||
SetBkColor(hdc, MAKE_PALETTERGB(crBack));
|
||||
SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
|
||||
|
||||
SelectClipRgn(hdc, 0);
|
||||
|
||||
ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBkColor(hdc, MAKE_PALETTERGB(crBack));
|
||||
SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
|
||||
|
||||
SelectClipRgn(hdc, 0);
|
||||
|
||||
ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
|
||||
}
|
||||
|
||||
if(hIcon)
|
||||
{
|
||||
HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));
|
||||
DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);
|
||||
DeleteObject(hbr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CardButton::AdjustPosition(int winwidth, int winheight)
|
||||
{
|
||||
int width = rect.right-rect.left;
|
||||
int height = rect.bottom-rect.top;
|
||||
|
||||
width = width & ~0x1;
|
||||
|
||||
switch(xjustify)
|
||||
{
|
||||
case CS_XJUST_NONE:
|
||||
break;
|
||||
|
||||
case CS_XJUST_CENTER: //centered
|
||||
rect.left = (winwidth - (width)) / 2;
|
||||
rect.left += xadjust;
|
||||
rect.right = rect.left+width;
|
||||
break;
|
||||
|
||||
case CS_XJUST_RIGHT: //right-aligned
|
||||
rect.left = winwidth - width;
|
||||
rect.left += xadjust;
|
||||
rect.right = rect.left+width;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(yjustify)
|
||||
{
|
||||
case CS_YJUST_NONE:
|
||||
break;
|
||||
|
||||
case CS_YJUST_CENTER: //centered
|
||||
rect.top = (winheight - (height)) / 2;
|
||||
rect.top += yadjust;
|
||||
rect.bottom = rect.top+height;
|
||||
break;
|
||||
|
||||
case CS_YJUST_BOTTOM: //right-aligned
|
||||
rect.top = winheight - height;
|
||||
rect.top += yadjust;
|
||||
rect.bottom = rect.top+height;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CardButton::OnLButtonDown(HWND hwnd, int x, int y)
|
||||
{
|
||||
if((uStyle & CB_PUSHBUTTON) == 0)
|
||||
return 0;
|
||||
|
||||
//make sure that the user is allowed to do something
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseMutex(mxlock);
|
||||
}
|
||||
|
||||
fMouseDown = true;
|
||||
fButtonDown = true;
|
||||
|
||||
Redraw();
|
||||
|
||||
SetCapture(hwnd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CardButton::OnMouseMove(HWND hwnd, int x, int y)
|
||||
{
|
||||
if(fMouseDown)
|
||||
{
|
||||
bool fOldButtonDown = fButtonDown;
|
||||
|
||||
POINT pt;
|
||||
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
|
||||
if(PtInRect(&rect, pt))
|
||||
fButtonDown = true;
|
||||
else
|
||||
fButtonDown = false;
|
||||
|
||||
if(fButtonDown != fOldButtonDown)
|
||||
Redraw();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CardButton::OnLButtonUp(HWND hwnd, int x, int y)
|
||||
{
|
||||
if(fMouseDown)
|
||||
{
|
||||
fMouseDown = false;
|
||||
fButtonDown = false;
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
Redraw();
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
//if have clicked the button
|
||||
if(parentWnd.CardButtonFromPoint(x, y) == this)
|
||||
{
|
||||
if(ButtonCallback)
|
||||
{
|
||||
ButtonCallback(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND hwnd = (HWND)parentWnd;
|
||||
SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _countof(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)
|
||||
{
|
||||
CardButton *cb;
|
||||
|
||||
if(nNumButtons == MAXBUTTONS)
|
||||
return 0;
|
||||
|
||||
cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);
|
||||
Buttons[nNumButtons++] = cb;
|
||||
|
||||
if(uStyle & CB_PUSHBUTTON)
|
||||
{
|
||||
cb->SetBackColor(CardButton::GetFace(crBackgnd));
|
||||
//cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));
|
||||
cb->SetForeColor(RGB(255,255,255));
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->SetBackColor(crBackgnd);
|
||||
cb->SetForeColor(RGB(255,255,255));
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
void CardButton::SetText(TCHAR *lpszFormat, ...)
|
||||
{
|
||||
int count;
|
||||
|
||||
va_list args;
|
||||
va_start(args, lpszFormat);
|
||||
|
||||
count = wvsprintf(szText, lpszFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int CardButton::Id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void CardButton::Show(bool fShow)
|
||||
{
|
||||
fVisible = fShow;
|
||||
}
|
||||
|
||||
void CardButton::Move(int x, int y, int width, int height)
|
||||
{
|
||||
SetRect(&rect, x, y, x+width, y+height);
|
||||
}
|
||||
|
||||
void CardButton::Redraw()
|
||||
{
|
||||
HDC hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);
|
||||
|
||||
Draw(hdc, !fButtonDown);
|
||||
|
||||
RestorePalette(hdc, hOldPal);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
}
|
||||
|
||||
void CardButton::SetForeColor(COLORREF cr)
|
||||
{
|
||||
crText = cr;
|
||||
}
|
||||
|
||||
void CardButton::SetBackColor(COLORREF cr)
|
||||
{
|
||||
crBack = cr;
|
||||
|
||||
crHighlight = GetHighlight(cr);
|
||||
crShadow = GetShadow(cr);
|
||||
|
||||
//crHighlight = ScaleLumRGB(cr, +0.25);
|
||||
//crShadow = ScaleLumRGB(cr, -0.25);
|
||||
}
|
||||
|
||||
// Static member
|
||||
COLORREF CardButton::GetHighlight(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);
|
||||
}
|
||||
|
||||
// Static member
|
||||
COLORREF CardButton::GetShadow(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25);
|
||||
}
|
||||
|
||||
COLORREF CardButton::GetFace(COLORREF crBase)
|
||||
{
|
||||
return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);
|
||||
}
|
||||
|
||||
void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
|
||||
{
|
||||
xadjust = xAdjust;
|
||||
yadjust = yAdjust;
|
||||
xjustify = xJustify;
|
||||
yjustify = yJustify;
|
||||
}
|
||||
|
||||
void CardButton::SetIcon(HICON hicon, bool fRedraw)
|
||||
{
|
||||
hIcon = hicon;
|
||||
|
||||
if(fRedraw)
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void CardButton::SetFont(HFONT font)
|
||||
{
|
||||
//don't delete the existing font..
|
||||
hFont = font;
|
||||
}
|
||||
|
||||
void CardButton::SetButtonProc(pButtonProc proc)
|
||||
{
|
||||
ButtonCallback = proc;
|
||||
}
|
||||
|
||||
bool CardButton::Lock()
|
||||
{
|
||||
DWORD dw = WaitForSingleObject(mxlock, 0);
|
||||
|
||||
if(dw == WAIT_OBJECT_0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardButton::UnLock()
|
||||
{
|
||||
if(ReleaseMutex(mxlock))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CardButton::SetStyle(UINT style)
|
||||
{
|
||||
uStyle = style;
|
||||
}
|
||||
|
||||
UINT CardButton::GetStyle()
|
||||
{
|
||||
return uStyle;
|
||||
}
|
101
rosapps/games/solitaire/cardlib/cardbutton.h
Normal file
101
rosapps/games/solitaire/cardlib/cardbutton.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
#ifndef CARDBUTTON_INCLUDED
|
||||
#define CARDBUTTON_INCLUDED
|
||||
|
||||
#define MAXBUTTONTEXT 64
|
||||
|
||||
#include "cardlib.h"
|
||||
|
||||
class CardButton
|
||||
{
|
||||
friend class CardWindow;
|
||||
|
||||
//
|
||||
// Constructor is PRIVATE - only a
|
||||
// CardWindow can create buttons!
|
||||
//
|
||||
CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
~CardButton();
|
||||
|
||||
public:
|
||||
|
||||
void SetStyle(UINT uStyle);
|
||||
UINT GetStyle();
|
||||
|
||||
void SetText(TCHAR *fmt, ...);
|
||||
void SetFont(HFONT font);
|
||||
|
||||
void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);
|
||||
|
||||
void SetForeColor(COLORREF cr);
|
||||
void SetBackColor(COLORREF cr);
|
||||
|
||||
void Move(int x, int y, int width, int height);
|
||||
void Show(bool fShow);
|
||||
void Redraw();
|
||||
int Id();
|
||||
|
||||
void SetIcon(HICON hicon, bool fRedraw);
|
||||
|
||||
void SetButtonProc(pButtonProc proc);
|
||||
|
||||
CardWindow &GetCardWindow() { return parentWnd; }
|
||||
|
||||
bool Lock();
|
||||
bool UnLock();
|
||||
|
||||
static COLORREF GetHighlight(COLORREF crBase);
|
||||
static COLORREF GetShadow(COLORREF crBase);
|
||||
static COLORREF GetFace(COLORREF crBase);
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Private member functions
|
||||
//
|
||||
void AdjustPosition(int winwidth, int winheight);
|
||||
|
||||
void DrawRect(HDC hdc, RECT *rect, bool fNormal);
|
||||
void Draw(HDC hdc, bool fNormal);
|
||||
void Clip(HDC hdc);
|
||||
|
||||
int OnLButtonDown(HWND hwnd, int x, int y);
|
||||
int OnMouseMove(HWND hwnd, int x, int y);
|
||||
int OnLButtonUp(HWND hwnd, int x, int y);
|
||||
|
||||
//
|
||||
// Private members
|
||||
//
|
||||
CardWindow &parentWnd;
|
||||
|
||||
RECT rect;
|
||||
int id;
|
||||
UINT uStyle;
|
||||
bool fVisible;
|
||||
|
||||
int xadjust;
|
||||
int xjustify;
|
||||
int yadjust;
|
||||
int yjustify;
|
||||
|
||||
HICON hIcon;
|
||||
HFONT hFont;
|
||||
|
||||
TCHAR szText[MAXBUTTONTEXT];
|
||||
|
||||
COLORREF crBack;
|
||||
COLORREF crText;
|
||||
COLORREF crHighlight;
|
||||
COLORREF crShadow;
|
||||
COLORREF crShadow2;
|
||||
|
||||
bool fMouseDown;
|
||||
bool fButtonDown;
|
||||
|
||||
HANDLE mxlock;
|
||||
|
||||
pButtonProc ButtonCallback;
|
||||
};
|
||||
|
||||
#endif
|
353
rosapps/games/solitaire/cardlib/cardcolor.cpp
Normal file
353
rosapps/games/solitaire/cardlib/cardcolor.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
//
|
||||
// Colour support
|
||||
//
|
||||
#include <windows.h>
|
||||
|
||||
#define MakeRGB RGB
|
||||
|
||||
#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )
|
||||
#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )
|
||||
|
||||
inline double fMax(double a, double b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
inline double fMin(double a, double b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
/******************************************************************************
|
||||
FUNCTION: RGBtoHLS
|
||||
PURPOSE: Convert from RGB to HLS
|
||||
IN: RGB color (0xBBGGRR)
|
||||
OUT: Hue, Saturation, Luminance from 0 to 1
|
||||
COPYRIGHT:1995-1997 Robert Mashlan
|
||||
Modified for LabWindows/CVI, 1999 Guillaume Dargaud
|
||||
******************************************************************************/
|
||||
void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S )
|
||||
{
|
||||
double delta;
|
||||
double r = (double)((rgb )&0xFF)/255;
|
||||
double g = (double)((rgb>> 8)&0xFF)/255;
|
||||
double b = (double)((rgb>>16)&0xFF)/255;
|
||||
double cmax = MAX3(r,g,b);
|
||||
double cmin = MIN3(r,g,b);
|
||||
*L=(cmax+cmin)/2.0;
|
||||
|
||||
if(cmax == cmin)
|
||||
{
|
||||
*S = *H = 0; // it's really undefined
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin);
|
||||
else *S = (cmax-cmin)/(2.0-cmax-cmin);
|
||||
|
||||
delta = cmax - cmin;
|
||||
|
||||
if(r == cmax)
|
||||
{
|
||||
*H = (g - b) / delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g == cmax) *H = 2.0 + (b-r) / delta;
|
||||
else *H = 4.0 + (r-g) / delta;
|
||||
}
|
||||
*H /= 6.0;
|
||||
if (*H < 0.0) *H += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FUNCTION: HueToRGB
|
||||
PURPOSE: Convert a hue (color) to RGB
|
||||
COPYRIGHT:1995-1997 Robert Mashlan
|
||||
Modified for LabWindows/CVI, 1999 Guillaume Dargaud
|
||||
******************************************************************************/
|
||||
double HueToRGB(const double m1, const double m2, double h )
|
||||
{
|
||||
if (h<0) h+=1.0;
|
||||
if (h>1) h-=1.0;
|
||||
if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);
|
||||
if (2.0*h < 1 ) return m2;
|
||||
if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
|
||||
return m1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
FUNCTION: HLStoRGB
|
||||
PURPOSE: Convert from HSL to RGB
|
||||
IN: Hue, Saturation, Luminance from 0 to 1
|
||||
RETURN: RGB color (0xBBGGRR)
|
||||
COPYRIGHT:1995-1997 Robert Mashlan
|
||||
Modified for LabWindows/CVI, 1999 Guillaume Dargaud
|
||||
******************************************************************************/
|
||||
|
||||
COLORREF HLStoRGB(const double H, const double L, const double S )
|
||||
{
|
||||
double r,g,b;
|
||||
double m1, m2;
|
||||
|
||||
if(S == 0)
|
||||
{
|
||||
r = g = b = L;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (L <= 0.5)
|
||||
m2 = L * (1.0 + S);
|
||||
else
|
||||
m2 = L + S - L * S;
|
||||
|
||||
m1 = 2.0 * L - m2;
|
||||
|
||||
r = HueToRGB(m1,m2,H+1.0/3.0);
|
||||
g = HueToRGB(m1,m2,H);
|
||||
b = HueToRGB(m1,m2,H-1.0/3.0);
|
||||
}
|
||||
|
||||
return RGB(r*255, g*255, b*255);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
FUNCTION: ColorScaleHSL
|
||||
PURPOSE: Returns the HSL linear interpolated color between 2 colors
|
||||
(more natural looking than RGB interpolation)
|
||||
For instance if the luminance is the same in Col1 and Col2,
|
||||
then the luminance of the result will be the same
|
||||
If Ratio=0, you get Col1,
|
||||
If Ratio=1, you get Col2
|
||||
IN: Col1: low color in hex 0xBBGGRR format
|
||||
Col2: high color in hex 0xBBGGRR format
|
||||
Ratio: 0 for low color, 1 for high color, or in between
|
||||
EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F
|
||||
******************************************************************************/
|
||||
COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio)
|
||||
{
|
||||
static double H1, H2, S1, S2, L1, L2;
|
||||
|
||||
if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
|
||||
else if (Ratio>=1) return Col2;
|
||||
|
||||
RGBtoHLS( Col1, &H1, &L1, &S1);
|
||||
RGBtoHLS( Col2, &H2, &L2, &S2);
|
||||
return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
FUNCTION: ColorScaleRGB
|
||||
PURPOSE: Returns the RGB linear interpolated color between 2 colors
|
||||
If Ratio=0, you get Col1,
|
||||
If Ratio=1, you get Col2
|
||||
IN: Col1: low color in hex 0xBBGGRR format
|
||||
Col2: high color in hex 0xBBGGRR format
|
||||
Ratio: 0 for low color, 1 for high color, or in between
|
||||
EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080
|
||||
******************************************************************************/
|
||||
COLORREF ColorScaleRGB( const COLORREF Col1,
|
||||
const COLORREF Col2,
|
||||
const double Ratio) {
|
||||
int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;
|
||||
int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;
|
||||
|
||||
if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
|
||||
else if (Ratio>=1) return Col2;
|
||||
|
||||
/* return RGB(
|
||||
(R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
|
||||
(G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
|
||||
(B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
|
||||
);*/
|
||||
|
||||
/*double r = Ratio;
|
||||
if(Col2 == 0)
|
||||
r = 1-Ratio;
|
||||
else
|
||||
r = 1+Ratio;
|
||||
R1 = (int)(double(R1) * r + 0.5);
|
||||
G1 = (int)(double(G1) * r + 0.5);
|
||||
B1 = (int)(double(B1) * r + 0.5);
|
||||
return RGB(R1,G1,B1);*/
|
||||
|
||||
return RGB(
|
||||
(R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
|
||||
(G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
|
||||
(B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
COLORREF ColorDarker(COLORREF col, double ratio)
|
||||
{
|
||||
static double Hue, Lum, Sat;
|
||||
|
||||
//RGBtoHLS(col, &Hue, &Lum, &Sat);
|
||||
|
||||
//col = HLStoRGB(Hue, fMax(0.0,Lum-ratio), Sat);
|
||||
|
||||
return ColorScaleHSL(col, RGB(0,0,0), ratio);
|
||||
|
||||
//return col;
|
||||
}
|
||||
|
||||
COLORREF ColorLighter(COLORREF col, double ratio)
|
||||
{
|
||||
static double Hue, Lum, Sat;
|
||||
|
||||
//RGBtoHLS(col, &Hue, &Lum, &Sat);
|
||||
|
||||
//col = HLStoRGB(Hue, fMin(1.0,Lum+ratio), Sat);
|
||||
|
||||
return ColorScaleHSL(col, RGB(255,255,255), ratio);
|
||||
|
||||
//return col;
|
||||
}
|
||||
|
||||
//
|
||||
// Experimental!!!
|
||||
//
|
||||
#if 0
|
||||
|
||||
typedef enum { Red, Green, Blue };
|
||||
|
||||
void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)
|
||||
{
|
||||
double mn, mx;
|
||||
int major;
|
||||
|
||||
BYTE red, green, blue;
|
||||
|
||||
red = GetRValue(rgb);
|
||||
green = GetGValue(rgb);
|
||||
blue = GetBValue(rgb);
|
||||
|
||||
if(red < green)
|
||||
{
|
||||
mn = red; mx = green; major = Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
mn = green; mx = red; major = Red;
|
||||
}
|
||||
|
||||
if(blue < mn)
|
||||
{
|
||||
mn = blue;
|
||||
}
|
||||
else if(blue > mx)
|
||||
{
|
||||
mx = blue; major = Blue;
|
||||
}
|
||||
|
||||
if(mn == mx)
|
||||
{
|
||||
*Lum = mn / 255;
|
||||
*Sat = 0;
|
||||
*Hue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*Lum = (mx + mn) / 510;
|
||||
|
||||
if(*Lum <= 0.5)
|
||||
*Sat = (mx-mn) / (mn+mx);
|
||||
else
|
||||
*Sat = (mx-mn) / (510-mn-mx);
|
||||
|
||||
switch(major)
|
||||
{
|
||||
case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;
|
||||
break;
|
||||
|
||||
case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;
|
||||
break;
|
||||
|
||||
case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(*Hue > 360.0)
|
||||
*Hue -= 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
static BYTE Value(double m1, double m2, double hue)
|
||||
{
|
||||
|
||||
if(hue > 360) hue -= 360;
|
||||
else if(hue < 0) hue += 360;
|
||||
|
||||
if(hue < 60)
|
||||
m1 = m1 + (m2 - m1) * hue / 60;
|
||||
else if(hue < 180)
|
||||
m1 = m2;
|
||||
else if(hue < 240)
|
||||
m1 = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
|
||||
return (BYTE)(m1 * 255);
|
||||
}
|
||||
|
||||
COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)
|
||||
{
|
||||
BYTE red, green, blue;
|
||||
|
||||
if(Sat == 0)
|
||||
{
|
||||
red = green = blue = (BYTE)(Lum * 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
double m1, m2;
|
||||
|
||||
if(Lum <= 0.5)
|
||||
m2 = Lum + Lum * Sat;
|
||||
else
|
||||
m2 = Lum + Sat - Lum * Sat;
|
||||
|
||||
m1 = 2 * Lum - m2;
|
||||
|
||||
red = Value(m1, m2, Hue + 120);
|
||||
green = Value(m1, m2, Hue);
|
||||
blue = Value(m1, m2, Hue - 120);
|
||||
}
|
||||
|
||||
return RGB(red, green, blue);
|
||||
}
|
||||
|
||||
COLORREF ScaleLumRGB(COLORREF col1, double ratio)
|
||||
{
|
||||
double H1, L1, S1;
|
||||
|
||||
RGBtoHLS(col1, &H1, &L1, &S1);
|
||||
|
||||
L1 += L1 * ratio;
|
||||
|
||||
return HLStoRGB(H1, L1, S1);
|
||||
}
|
||||
|
||||
COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio)
|
||||
{
|
||||
static double H1, H2, S1, S2, L1, L2;
|
||||
|
||||
if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1
|
||||
else if(Ratio >= 1) return Col2;
|
||||
|
||||
RGBtoHLS( Col1, &H1, &L1, &S1);
|
||||
RGBtoHLS( Col2, &H2, &L2, &S2);
|
||||
|
||||
return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);
|
||||
}
|
||||
|
||||
COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)
|
||||
{
|
||||
return ColorScaleHSL(Col1, Col2, Ratio);
|
||||
}
|
||||
#endif
|
16
rosapps/games/solitaire/cardlib/cardcolor.h
Normal file
16
rosapps/games/solitaire/cardlib/cardcolor.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
COLORREF ColorScaleRGB( const COLORREF Col1,
|
||||
const COLORREF Col2,
|
||||
const double Ratio);
|
||||
|
||||
COLORREF ColorScaleHSL( const COLORREF Col1,
|
||||
const COLORREF Col2,
|
||||
const double Ratio);
|
||||
|
||||
|
||||
COLORREF ColorDarker(COLORREF col, double ratio);
|
||||
COLORREF ColorLighter(COLORREF col, double ratio);
|
||||
|
||||
COLORREF ScaleLumRGB(COLORREF col1, double ratio);
|
||||
|
||||
#define MAKE_PALETTERGB(colref) (0x02000000 | colref)
|
90
rosapps/games/solitaire/cardlib/cardcount.cpp
Normal file
90
rosapps/games/solitaire/cardlib/cardcount.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// CardCount is a helper library for CardStacks.
|
||||
//
|
||||
// When you initialize a CardCount object with a
|
||||
// cardstack, it keeps track of the number of cards
|
||||
// the stack contains.
|
||||
//
|
||||
// e.g. CardCount count(cardstack);
|
||||
//
|
||||
// Then you can do:
|
||||
//
|
||||
// int num_fives = count[5]
|
||||
//
|
||||
// count.Add(cardstack2); - combine with another stack
|
||||
//
|
||||
// int num_aces = count[1] - aces low
|
||||
// int num_aces = count[14] - aces high
|
||||
//
|
||||
// count.Clear();
|
||||
//
|
||||
#include "cardcount.h"
|
||||
|
||||
CardCount::CardCount()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
CardCount::CardCount(const CardStack &cs)
|
||||
{
|
||||
Init(cs);
|
||||
}
|
||||
|
||||
void CardCount::Clear()
|
||||
{
|
||||
for(int i = 0; i < 13; i++)
|
||||
count[i] = 0;
|
||||
}
|
||||
|
||||
void CardCount::Add(const CardStack &cs)
|
||||
{
|
||||
for(int i = 0; i < cs.NumCards(); i++)
|
||||
{
|
||||
Card card = cs[i];
|
||||
|
||||
int val = card.LoVal();
|
||||
count[val - 1]++;
|
||||
}
|
||||
}
|
||||
|
||||
void CardCount::Sub(const CardStack &cs)
|
||||
{
|
||||
for(int i = 0; i < cs.NumCards(); i++)
|
||||
{
|
||||
Card card = cs[i];
|
||||
int val = card.LoVal();
|
||||
|
||||
if(count[val - 1] > 0)
|
||||
count[val - 1]--;
|
||||
}
|
||||
}
|
||||
|
||||
void CardCount::Init(const CardStack &cs)
|
||||
{
|
||||
Clear();
|
||||
Add(cs);
|
||||
}
|
||||
|
||||
int CardCount::operator [] (size_t index) const
|
||||
{
|
||||
if(index < 1) return 0;
|
||||
else if(index > 14) return 0; //if out of range
|
||||
else if(index == 14) index = 1; //if a "ace-high"
|
||||
|
||||
return count[index - 1];
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement specified item by one
|
||||
//
|
||||
void CardCount::Dec(size_t index)
|
||||
{
|
||||
if(index < 1) return;
|
||||
else if(index > 14) return; //if out of range
|
||||
else if(index == 14) index = 1; //if a "ace-high"
|
||||
|
||||
index -= 1;
|
||||
|
||||
if(count[index] > 0)
|
||||
count[index]--;
|
||||
}
|
31
rosapps/games/solitaire/cardlib/cardcount.h
Normal file
31
rosapps/games/solitaire/cardlib/cardcount.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _CARDCOUNT_INCLUDED
|
||||
#define _CARDCOUNT_INCLUDED
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cardstack.h"
|
||||
|
||||
class CardCount
|
||||
{
|
||||
public:
|
||||
CardCount();
|
||||
CardCount(const CardStack &cs);
|
||||
|
||||
void Init(const CardStack &cs);
|
||||
void Clear();
|
||||
void Add(const CardStack &cs);
|
||||
void Sub(const CardStack &cs);
|
||||
|
||||
void Dec(size_t index);
|
||||
|
||||
int operator[] (size_t index) const;
|
||||
|
||||
CardCount &operator = (const CardStack &cs);
|
||||
CardCount &operator += (const CardStack &cs);
|
||||
|
||||
private:
|
||||
int count[13]; //13 different card values
|
||||
//(ace,2,3,4,5,6,7,8,9,10,J,Q,K)
|
||||
};
|
||||
|
||||
#endif
|
122
rosapps/games/solitaire/cardlib/cardlib.cpp
Normal file
122
rosapps/games/solitaire/cardlib/cardlib.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// CardLib - not much of interest in here
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "cardlib.h"
|
||||
#include "globals.h"
|
||||
|
||||
void LoadCardBitmaps(void);
|
||||
|
||||
static bool __CARDLIB_ACES_HIGH = false;
|
||||
extern double __CARDZOOMSPEED;
|
||||
|
||||
//
|
||||
// Global variables!
|
||||
//
|
||||
HDC __hdcCardBitmaps;
|
||||
HBITMAP __hbmCardBitmaps;
|
||||
|
||||
HDC __hdcPlaceHolder;
|
||||
HBITMAP __hbmPlaceHolder;
|
||||
HPALETTE __holdplacepal;
|
||||
|
||||
int __cardwidth;
|
||||
int __cardheight;
|
||||
|
||||
HPALETTE __hPalette;
|
||||
|
||||
|
||||
//
|
||||
// Cardlib global functions!
|
||||
//
|
||||
void CardLib_SetZoomSpeed(int speed)
|
||||
{
|
||||
__CARDZOOMSPEED = (double)speed;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
It's dangerous to use these operators, because of all
|
||||
the implicit conversions that could take place, which
|
||||
would have unpredicted side-effects.
|
||||
|
||||
e.g. Card card(Hearts, 4);
|
||||
if(card == 4) - how does 4 get converted??
|
||||
It uses the Card(int uval) constructor,
|
||||
which results in a 2 of clubs...
|
||||
not what was expected
|
||||
*/
|
||||
/*
|
||||
void CardLib_SetAcesHigh(bool fHigh);
|
||||
bool operator != (const Card &lhs, const Card &rhs);
|
||||
bool operator == (const Card &lhs, const Card &rhs);
|
||||
bool operator < (const Card &lhs, const Card &rhs);
|
||||
bool operator <= (const Card &lhs, const Card &rhs);
|
||||
bool operator > (const Card &lhs, const Card &rhs);
|
||||
bool operator >= (const Card &lhs, const Card &rhs);
|
||||
*/
|
||||
|
||||
/*
|
||||
void CardLib_SetAcesHigh(bool fHigh)
|
||||
{
|
||||
__CARDLIB_ACES_HIGH = fHigh;
|
||||
}
|
||||
|
||||
bool operator == (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() == rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() == rhs.LoVal();
|
||||
}
|
||||
|
||||
bool operator != (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() != rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() != rhs.LoVal();
|
||||
}
|
||||
|
||||
bool operator > (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() > rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() > rhs.LoVal();
|
||||
}
|
||||
|
||||
bool operator >= (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() >= rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() >= rhs.LoVal();
|
||||
}
|
||||
|
||||
bool operator < (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() < rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() < rhs.LoVal();
|
||||
}
|
||||
|
||||
bool operator <= (const Card &lhs, const Card &rhs)
|
||||
{
|
||||
if(__CARDLIB_ACES_HIGH)
|
||||
return lhs.HiVal() <= rhs.HiVal();
|
||||
else
|
||||
return lhs.LoVal() <= rhs.LoVal();
|
||||
}
|
||||
*/
|
||||
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour)
|
||||
{
|
||||
COLORREF oldcr = SetBkColor(hdc, colour);
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0);
|
||||
SetBkColor(hdc, oldcr);
|
||||
}
|
101
rosapps/games/solitaire/cardlib/cardlib.h
Normal file
101
rosapps/games/solitaire/cardlib/cardlib.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
#ifndef CARDLIB_INCLUDED
|
||||
#define CARDLIB_INCLUDED
|
||||
|
||||
#define CARDLIBPROC __stdcall
|
||||
|
||||
void CardBlt(HDC hdc, int x, int y, int nCardNum);
|
||||
void CardLib_SetZoomSpeed(int);
|
||||
|
||||
#define CS_EI_NONE 0
|
||||
#define CS_EI_SUNK 1
|
||||
|
||||
#define CS_DEFXOFF 12 //x-offset
|
||||
#define CS_DEFYOFF 18 //y-offset
|
||||
#define CS_NO3D 1 //default 3d counts (recommened)
|
||||
#define CS_DEF3D 10 //(best for decks)
|
||||
|
||||
//#define CS_EI_CIRC 2
|
||||
//#define CS_EI_X 3
|
||||
|
||||
#define CS_DRAG_NONE 0
|
||||
#define CS_DRAG_TOP 1
|
||||
#define CS_DRAG_ALL 2
|
||||
#define CS_DRAG_CALLBACK 3
|
||||
|
||||
#define CS_DROP_NONE 0
|
||||
#define CS_DROP_ALL 1
|
||||
#define CS_DROP_CALLBACK 2
|
||||
|
||||
#define CS_XJUST_NONE 0
|
||||
#define CS_XJUST_RIGHT 1
|
||||
#define CS_XJUST_CENTER 2
|
||||
|
||||
#define CS_YJUST_NONE 0
|
||||
#define CS_YJUST_BOTTOM 1
|
||||
#define CS_YJUST_CENTER 2
|
||||
|
||||
#define CB_STATIC 0 //static text label
|
||||
#define CB_PUSHBUTTON 1 //normal button
|
||||
#define CB_ALIGN_CENTER 0 //centered is default
|
||||
#define CB_ALIGN_LEFT 2
|
||||
#define CB_ALIGN_RIGHT 4
|
||||
|
||||
#define CS_FACE_UP 0 //all cards face-up
|
||||
#define CS_FACE_DOWN 1 //all cards face-down
|
||||
#define CS_FACE_DOWNUP 2 //bottom X cards down, top-most face-up
|
||||
#define CS_FACE_UPDOWN 3 //bottom X cards up, top-most face-down
|
||||
#define CS_FACE_ANY 4 //cards can be any orientation
|
||||
|
||||
#define CS_DROPZONE_NODROP -1
|
||||
|
||||
//
|
||||
// Define the standard card-back indices
|
||||
//
|
||||
#define ecbCROSSHATCH 53
|
||||
#define ecbWEAVE1 54
|
||||
#define ecbWEAVE2 55
|
||||
#define ecbROBOT 56
|
||||
#define ecbFLOWERS 57
|
||||
#define ecbVINE1 58
|
||||
#define ecbVINE2 59
|
||||
#define ecbFISH1 60
|
||||
#define ecbFISH2 61
|
||||
#define ecbSHELLS 62
|
||||
#define ecbCASTLE 63
|
||||
#define ecbISLAND 64
|
||||
#define ecbCARDHAND 65
|
||||
#define ecbUNUSED 66
|
||||
#define ecbTHE_X 67
|
||||
#define ecbTHE_O 68
|
||||
|
||||
|
||||
class CardRegion;
|
||||
class CardButton;
|
||||
class CardStack;
|
||||
|
||||
typedef bool (CARDLIBPROC *pCanDragProc) (CardRegion &stackobj, int iNumDragging);
|
||||
typedef bool (CARDLIBPROC *pCanDropProc) (CardRegion &stackobj, const CardStack &cards);
|
||||
typedef void (CARDLIBPROC *pClickProc) (CardRegion &stackobj, int iNumCards);
|
||||
typedef void (CARDLIBPROC *pAddProc) (CardRegion &stackobj, const CardStack &cards);
|
||||
typedef void (CARDLIBPROC *pRemoveProc) (CardRegion &stackobj, int iNumRemoved);
|
||||
|
||||
typedef void (CARDLIBPROC *pResizeWndProc) (int width, int height);
|
||||
typedef int (CARDLIBPROC *pDropZoneProc) (int dzid, const CardStack &cards);
|
||||
|
||||
typedef void (CARDLIBPROC *pButtonProc) (CardButton &pButton);
|
||||
|
||||
|
||||
#include "card.h"
|
||||
#include "cardbutton.h"
|
||||
#include "cardstack.h"
|
||||
#include "cardregion.h"
|
||||
#include "cardcount.h"
|
||||
#include "cardwindow.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj);
|
||||
void CardLib_SetStackClickProc(pDebugClickProc proc);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
658
rosapps/games/solitaire/cardlib/cardregion.cpp
Normal file
658
rosapps/games/solitaire/cardlib/cardregion.cpp
Normal file
|
@ -0,0 +1,658 @@
|
|||
//
|
||||
// CardLib - CardRegion class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardregion.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height);
|
||||
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
|
||||
|
||||
CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset)
|
||||
: parentWnd(parent), id(Id), fVisible(visible), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset)
|
||||
{
|
||||
width = __cardwidth;
|
||||
height = __cardheight;
|
||||
|
||||
crBackgnd = RGB(0, 64, 100);
|
||||
|
||||
uFaceDirType = CS_FACE_UP;
|
||||
nFaceDirOption = 0;
|
||||
uEmptyImage = CS_EI_SUNK;
|
||||
|
||||
fVisible = visible;
|
||||
|
||||
nThreedCount = 1;
|
||||
nBackCardIdx = 53;
|
||||
|
||||
Update(); //Update this stack's size+card count
|
||||
|
||||
hdcBackGnd = 0;
|
||||
hbmBackGnd = 0;
|
||||
hdcDragCard = 0;
|
||||
hbmDragCard = 0;
|
||||
|
||||
nDragCardWidth = 0;
|
||||
nDragCardHeight = 0;
|
||||
|
||||
CanDragCallback = 0;
|
||||
CanDropCallback = 0;
|
||||
AddCallback = 0;
|
||||
RemoveCallback = 0;
|
||||
ClickCallback = 0;
|
||||
DblClickCallback = 0;
|
||||
|
||||
uDragRule = CS_DRAG_ALL;
|
||||
uDropRule = CS_DROP_ALL;
|
||||
|
||||
xjustify = yjustify = xadjust = yadjust = 0;
|
||||
|
||||
nFlashCount = 0;
|
||||
fFlashVisible = false;
|
||||
uFlashTimer = -1;
|
||||
|
||||
fMouseDragging = false;
|
||||
|
||||
mxlock = CreateMutex(0, FALSE, 0);
|
||||
}
|
||||
|
||||
CardRegion::~CardRegion()
|
||||
{
|
||||
CloseHandle(mxlock);
|
||||
}
|
||||
|
||||
void CardRegion::SetBackColor(COLORREF cr)
|
||||
{
|
||||
crBackgnd = cr;
|
||||
}
|
||||
|
||||
int CardRegion::CalcApparentCards(int realnum)
|
||||
{
|
||||
return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount;
|
||||
}
|
||||
|
||||
void CardRegion::CalcApparentCards()
|
||||
{
|
||||
nNumApparentCards = CalcApparentCards(cardstack.NumCards());
|
||||
}
|
||||
|
||||
|
||||
void CardRegion::UpdateSize(void)
|
||||
{
|
||||
if(cardstack.NumCards() > 0)
|
||||
{
|
||||
if(xoffset > 0)
|
||||
width = (nNumApparentCards - 1) * xoffset + __cardwidth;
|
||||
else
|
||||
width = (nNumApparentCards - 1) * -xoffset + __cardwidth;
|
||||
|
||||
if(yoffset > 0)
|
||||
height = (nNumApparentCards - 1) * yoffset + __cardheight;
|
||||
else
|
||||
height = (nNumApparentCards - 1) * -yoffset + __cardheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = __cardwidth;
|
||||
height = __cardheight;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int CardRegion::GetOverlapRatio(int x, int y, int w, int h)
|
||||
{
|
||||
RECT me, him;
|
||||
RECT inter;
|
||||
SetRect(&him, x, y, x+w, y+h);
|
||||
SetRect(&me, xpos, ypos, xpos+width, ypos+height);
|
||||
|
||||
//see if the specified rectangle overlaps us
|
||||
if(IntersectRect(&inter, &me, &him))
|
||||
{
|
||||
int wi = inter.right - inter.left;
|
||||
int hi = inter.bottom - inter.top;
|
||||
|
||||
int overlap = wi * hi;
|
||||
int total = width * height;
|
||||
|
||||
int percent = (overlap << 16) / total;
|
||||
return (percent * 100) >> 16;
|
||||
}
|
||||
//do not overlap
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc)
|
||||
{
|
||||
switch(uDragType)
|
||||
{
|
||||
case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP:
|
||||
uDragRule = uDragType;
|
||||
return true;
|
||||
|
||||
case CS_DRAG_CALLBACK:
|
||||
uDragRule = uDragType;
|
||||
CanDragCallback = proc;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc)
|
||||
{
|
||||
switch(uDropType)
|
||||
{
|
||||
case CS_DROP_NONE: case CS_DROP_ALL:
|
||||
uDropRule = uDropType;
|
||||
return true;
|
||||
|
||||
case CS_DROP_CALLBACK:
|
||||
uDropRule = uDropType;
|
||||
CanDropCallback = proc;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CardRegion::SetClickProc(pClickProc proc)
|
||||
{
|
||||
ClickCallback = proc;
|
||||
}
|
||||
|
||||
void CardRegion::SetDblClickProc(pClickProc proc)
|
||||
{
|
||||
DblClickCallback = proc;
|
||||
}
|
||||
|
||||
void CardRegion::SetAddCardProc(pAddProc proc)
|
||||
{
|
||||
AddCallback = proc;
|
||||
}
|
||||
|
||||
void CardRegion::SetRemoveCardProc(pRemoveProc proc)
|
||||
{
|
||||
RemoveCallback = proc;
|
||||
}
|
||||
|
||||
void CardRegion::Update()
|
||||
{
|
||||
CalcApparentCards();
|
||||
UpdateSize();
|
||||
UpdateFaceDir(cardstack);
|
||||
}
|
||||
|
||||
|
||||
bool CardRegion::SetThreedCount(int count)
|
||||
{
|
||||
if(count < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nThreedCount = count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CardRegion::SetOffsets(int x, int y)
|
||||
{
|
||||
xoffset = x;
|
||||
yoffset = y;
|
||||
}
|
||||
|
||||
void CardRegion::SetPos(int x, int y)
|
||||
{
|
||||
xpos = x;
|
||||
ypos = y;
|
||||
}
|
||||
|
||||
void CardRegion::Show(bool fShow)
|
||||
{
|
||||
fVisible = fShow;
|
||||
}
|
||||
|
||||
bool CardRegion::IsVisible()
|
||||
{
|
||||
return fVisible;
|
||||
}
|
||||
|
||||
void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
|
||||
{
|
||||
xjustify = xJustify;
|
||||
yjustify = yJustify;
|
||||
xadjust = xAdjust;
|
||||
yadjust = yAdjust;
|
||||
}
|
||||
|
||||
void CardRegion::SetFaceDirection(UINT uDirType, int nOption)
|
||||
{
|
||||
switch(uDirType)
|
||||
{
|
||||
case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP:
|
||||
case CS_FACE_UPDOWN: case CS_FACE_ANY:
|
||||
uFaceDirType = uDirType;
|
||||
nFaceDirOption = nOption;
|
||||
|
||||
UpdateFaceDir(cardstack);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT CardRegion::GetFaceDirection(int *pnOption)
|
||||
{
|
||||
if(pnOption)
|
||||
*pnOption = nFaceDirOption;
|
||||
|
||||
return uFaceDirType;
|
||||
}
|
||||
|
||||
void CardRegion::AdjustPosition(int winwidth, int winheight)
|
||||
{
|
||||
Update(); //Update this stack's card count + size
|
||||
|
||||
switch(xjustify)
|
||||
{
|
||||
default: case CS_XJUST_NONE: break;
|
||||
|
||||
case CS_XJUST_CENTER: //centered
|
||||
xpos = (winwidth - (width & ~0x1)) / 2;
|
||||
xpos += xadjust;
|
||||
|
||||
if(xoffset < 0) xpos += (width - __cardwidth);
|
||||
|
||||
break;
|
||||
|
||||
case CS_XJUST_RIGHT: //right-aligned
|
||||
xpos = winwidth - __cardwidth;//width - 20;
|
||||
xpos += xadjust;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(yjustify)
|
||||
{
|
||||
default: case CS_YJUST_NONE: break;
|
||||
|
||||
case CS_YJUST_CENTER: //centered
|
||||
ypos = (winheight - height) / 2;
|
||||
ypos += yadjust;
|
||||
if(yoffset < 0) ypos += (height - __cardheight);
|
||||
break;
|
||||
|
||||
case CS_YJUST_BOTTOM: //bottom-aligned
|
||||
ypos = winheight - __cardheight;//height - 20;
|
||||
ypos += yadjust;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CardRegion::Flash(int count, int milliseconds)
|
||||
{
|
||||
if(count <= 0) return;
|
||||
|
||||
nFlashCount = count;
|
||||
fFlashVisible = false;
|
||||
uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0);
|
||||
|
||||
parentWnd.Redraw();
|
||||
}
|
||||
|
||||
void CardRegion::StopFlash()
|
||||
{
|
||||
if(uFlashTimer != -1)
|
||||
{
|
||||
KillTimer((HWND)parentWnd, uFlashTimer);
|
||||
nFlashCount = 0;
|
||||
uFlashTimer = -1;
|
||||
fFlashVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CardRegion::DoFlash()
|
||||
{
|
||||
if(uFlashTimer != -1)
|
||||
{
|
||||
fFlashVisible = !fFlashVisible;
|
||||
|
||||
if(--nFlashCount == 0)
|
||||
{
|
||||
KillTimer((HWND)parentWnd, uFlashTimer);
|
||||
uFlashTimer = -1;
|
||||
fFlashVisible = true;
|
||||
}
|
||||
|
||||
parentWnd.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
int CardRegion::Id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void CardRegion::SetEmptyImage(UINT uImage)
|
||||
{
|
||||
switch(uImage)
|
||||
{
|
||||
case CS_EI_NONE: case CS_EI_SUNK:
|
||||
uEmptyImage = uImage;
|
||||
break;
|
||||
|
||||
default:
|
||||
uEmptyImage = CS_EI_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CardRegion::SetBackCardIdx(UINT uBackIdx)
|
||||
{
|
||||
if(uBackIdx >= 52 && uBackIdx <= 68)
|
||||
nBackCardIdx = uBackIdx;
|
||||
}
|
||||
|
||||
void CardRegion::SetCardStack(const CardStack &cs)
|
||||
{
|
||||
//make a complete copy of the specified stack..
|
||||
cardstack = cs;
|
||||
|
||||
// Update the face-direction and stack-size
|
||||
Update();
|
||||
}
|
||||
|
||||
const CardStack & CardRegion::GetCardStack()
|
||||
{
|
||||
//return reference to our internal stack
|
||||
return cardstack;
|
||||
}
|
||||
|
||||
//
|
||||
// Update specified card-stack using THIS stack's
|
||||
// face direction rules!
|
||||
//
|
||||
void CardRegion::UpdateFaceDir(CardStack &cards)
|
||||
{
|
||||
int i, n, num;
|
||||
|
||||
num = cards.NumCards();
|
||||
|
||||
//Now apply the face direction rules..
|
||||
switch(uFaceDirType)
|
||||
{
|
||||
case CS_FACE_UP:
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
cards[i].SetFaceUp(true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CS_FACE_DOWN:
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
cards[i].SetFaceUp(false);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CS_FACE_DOWNUP:
|
||||
|
||||
num = cardstack.NumCards();
|
||||
n = min(nFaceDirOption, num);
|
||||
|
||||
//bottom n cards..
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
cards[num - i - 1].SetFaceUp(false);
|
||||
}
|
||||
|
||||
for(i = n; i < num; i++)
|
||||
{
|
||||
cards[num - i - 1].SetFaceUp(true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CS_FACE_UPDOWN:
|
||||
|
||||
num = cardstack.NumCards();
|
||||
n = min(nFaceDirOption, num);
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
cards[num - i - 1].SetFaceUp(true);
|
||||
}
|
||||
|
||||
for(i = n; i < num; i++)
|
||||
{
|
||||
cards[num - i - 1].SetFaceUp(false);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CS_FACE_ANY: //cards can be any orientation
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate)
|
||||
{
|
||||
HDC hdc;
|
||||
|
||||
int x, y;
|
||||
|
||||
if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; }
|
||||
|
||||
if(nNumCards < 0 || nNumCards > cardstack.NumCards())
|
||||
return false;
|
||||
|
||||
x = xpos + xoffset * (nNumApparentCards - nNumCards);
|
||||
y = ypos + yoffset * (nNumApparentCards - nNumCards);
|
||||
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
|
||||
dragstack = cardstack.Pop(nNumCards);
|
||||
|
||||
//Alter the drag-stack so that it's cards are the same way up
|
||||
//as the destination. Use the destination's drag-rules
|
||||
//instead of this ones!!
|
||||
CardStack temp;
|
||||
temp.Push(pDestStack->GetCardStack());
|
||||
temp.Push(dragstack);
|
||||
|
||||
pDestStack->UpdateFaceDir(temp);
|
||||
|
||||
dragstack = temp.Pop(nNumCards);
|
||||
|
||||
if(fAnimate)
|
||||
{
|
||||
iNumDragCards = nNumCards;
|
||||
PrepareDragBitmaps(nNumCards);
|
||||
}
|
||||
|
||||
Update(); //Update this stack's size+card count
|
||||
|
||||
if(fAnimate)
|
||||
{
|
||||
hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
ZoomCard(hdc, x, y, pDestStack);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
ReleaseDragBitmaps();
|
||||
}
|
||||
|
||||
// Get a copy of the cardstack
|
||||
CardStack cs = pDestStack->GetCardStack();
|
||||
cs.Push(dragstack);
|
||||
|
||||
pDestStack->SetCardStack(cs);
|
||||
|
||||
//cs = pDestStack->GetCardStack();
|
||||
//pDestStack->Update();
|
||||
//pDestStack->UpdateFaceDir(cs);
|
||||
|
||||
RedrawIfNotDim(pDestStack, false);
|
||||
|
||||
//forcedfacedir = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Simple wrappers
|
||||
//
|
||||
int CardRegion::NumCards() const
|
||||
{
|
||||
if(fMouseDragging)
|
||||
return cardstack.NumCards() + dragstack.NumCards();
|
||||
else
|
||||
return cardstack.NumCards();
|
||||
}
|
||||
|
||||
bool CardRegion::Lock()
|
||||
{
|
||||
DWORD dw = WaitForSingleObject(mxlock, 0);
|
||||
|
||||
if(dw == WAIT_OBJECT_0)
|
||||
{
|
||||
//TRACE("LockStack succeeded\n");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TRACE("LockStack failed\n");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardRegion::UnLock()
|
||||
{
|
||||
if(ReleaseMutex(mxlock))
|
||||
{
|
||||
//TRACE("Unlocking stack\n");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TRACE("Unlocking stack failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num)
|
||||
{
|
||||
//search the stack for the specified card value...
|
||||
while(num--)
|
||||
{
|
||||
for(int i = 0; i < cardstack.NumCards(); i++)
|
||||
{
|
||||
if(cardstack[i].HiVal() == value)
|
||||
{
|
||||
//swap the card with one at top pos...
|
||||
Card card = cardstack.RemoveCard(i);
|
||||
cardstack.Push(card);
|
||||
|
||||
Redraw();
|
||||
|
||||
MoveCard(pDestStack, 1, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Redraw the current stack if it has a different
|
||||
// layout than the comparison stack.
|
||||
//
|
||||
void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw)
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
if( pCompare->xoffset != xoffset ||
|
||||
pCompare->yoffset != yoffset ||
|
||||
pCompare->nThreedCount != nThreedCount ||
|
||||
pCompare->uFaceDirType != uFaceDirType ||
|
||||
pCompare->uFaceDirType != CS_FACE_ANY
|
||||
)
|
||||
{
|
||||
if(fFullRedraw)
|
||||
parentWnd.Redraw();
|
||||
else
|
||||
pCompare->Redraw();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// SimulateDrag mimicks the complete drag+drop process.
|
||||
// It basically just a MoveCard(..), but it calls the
|
||||
// event callbacks as well.
|
||||
//
|
||||
bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate)
|
||||
{
|
||||
if(pDestStack == 0)
|
||||
return false;
|
||||
|
||||
if(CanDragCards(iNumDragCards) != false)
|
||||
{
|
||||
//make a list of the cards that would be in the drag list
|
||||
CardStack tempstack = cardstack.Top(iNumDragCards);
|
||||
|
||||
if(pDestStack->CanDropCards(tempstack))
|
||||
{
|
||||
MoveCard(pDestStack, iNumDragCards, fAnimate);
|
||||
|
||||
if(RemoveCallback)
|
||||
RemoveCallback(*this, iNumDragCards);
|
||||
|
||||
if(pDestStack->AddCallback)
|
||||
pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);
|
||||
|
||||
RedrawIfNotDim(pDestStack, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
216
rosapps/games/solitaire/cardlib/cardregion.h
Normal file
216
rosapps/games/solitaire/cardlib/cardregion.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
#ifndef CARDREGION_INCLUDED
|
||||
#define CARDREGION_INCLUDED
|
||||
|
||||
#include "globals.h"
|
||||
#include "cardstack.h"
|
||||
#include "cardlib.h"
|
||||
|
||||
class CardWindow;
|
||||
|
||||
//
|
||||
// This class defines a physical card-stack,
|
||||
// which draws the cards, supports
|
||||
//
|
||||
|
||||
class CardRegion
|
||||
{
|
||||
friend class CardWindow;
|
||||
friend class CardStack;
|
||||
|
||||
//
|
||||
// Constructor is PRIVATE - only
|
||||
// a CardWindow can create cardstacks!
|
||||
//
|
||||
CardRegion(CardWindow &parent, int id, bool fVisible,
|
||||
int x, int y, int xOffset, int yOffset);
|
||||
|
||||
~CardRegion();
|
||||
|
||||
public:
|
||||
|
||||
void SetBackColor(COLORREF cr);
|
||||
|
||||
void SetCardStack(const CardStack &cs);
|
||||
const CardStack & GetCardStack();
|
||||
|
||||
//
|
||||
// Event-callback support
|
||||
//
|
||||
bool SetDragRule(UINT uDragType, pCanDragProc proc = 0);
|
||||
bool SetDropRule(UINT uDropType, pCanDropProc proc = 0);
|
||||
|
||||
void SetClickProc (pClickProc proc);
|
||||
void SetDblClickProc (pClickProc proc);
|
||||
|
||||
void SetAddCardProc (pAddProc proc);
|
||||
void SetRemoveCardProc (pRemoveProc proc);
|
||||
|
||||
//
|
||||
// Physical attribute support
|
||||
//
|
||||
bool SetThreedCount (int count);
|
||||
void SetOffsets (int x, int y);
|
||||
void SetPos (int x, int y);
|
||||
void Show (bool fShow);
|
||||
bool IsVisible ();
|
||||
|
||||
void SetEmptyImage (UINT uImage);
|
||||
void SetBackCardIdx (UINT uBackIdx);
|
||||
void SetPlacement (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);
|
||||
|
||||
void Update();
|
||||
void Redraw();
|
||||
|
||||
void SetFaceDirection(UINT uDirType, int nOption);
|
||||
UINT GetFaceDirection(int *pnOption);
|
||||
|
||||
void Flash(int count, int timeout);
|
||||
void StopFlash();
|
||||
|
||||
int Id();
|
||||
|
||||
CardWindow &GetCardWindow() { return parentWnd; }
|
||||
|
||||
bool PlayCard(CardRegion *pDestStack, int value, int num);
|
||||
bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate);
|
||||
bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate);
|
||||
|
||||
bool Lock();
|
||||
bool UnLock();
|
||||
|
||||
//
|
||||
// Common wrappers for the CardStack object
|
||||
//
|
||||
int NumCards() const;
|
||||
void NewDeck() { cardstack.NewDeck(); }
|
||||
void Shuffle() { cardstack.Shuffle(); }
|
||||
void Clear() { cardstack.Clear(); }
|
||||
|
||||
void Reverse() { cardstack.Reverse(); }
|
||||
|
||||
void Push(const Card card) { cardstack.Push(card); }
|
||||
void Push(const CardStack &cs) { cardstack.Push(cs); }
|
||||
|
||||
Card Pop() { return cardstack.Pop(); }
|
||||
CardStack Pop(int items) { return cardstack.Pop(items); }
|
||||
|
||||
Card Top() { return cardstack.Top(); }
|
||||
CardStack Top(int items) { return cardstack.Top(items); }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void DoFlash();
|
||||
void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw);
|
||||
|
||||
void UpdateFaceDir(CardStack &cards);
|
||||
void Clip(HDC hdc);
|
||||
void Render(HDC hdc);
|
||||
int GetOverlapRatio(int x, int y, int width, int height);
|
||||
|
||||
void MoveDragCardTo(HDC hdc, int x, int y);
|
||||
void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest);
|
||||
|
||||
void RenderBottomMost(HDC hdc, int minustopmost = 0);
|
||||
void PrepareDragBitmaps(int numtodrag);
|
||||
void PrepareDragBitmapsThreed(int numtodrag);
|
||||
void ReleaseDragBitmaps(void);
|
||||
|
||||
bool CanDragCards(int iNumCards);
|
||||
bool CanDropCards(CardStack &cards);
|
||||
|
||||
void CalcApparentCards();
|
||||
int CalcApparentCards(int realnum);
|
||||
|
||||
void UpdateSize();
|
||||
void AdjustPosition(int winwidth, int winheight);
|
||||
|
||||
bool IsPointInStack(int x, int y);
|
||||
|
||||
int GetNumDragCards(int x, int y);
|
||||
bool OnLButtonDown(int x, int y);
|
||||
bool OnLButtonDblClk(int x, int y);
|
||||
bool OnMouseMove(int x, int y);
|
||||
bool OnLButtonUp(int x, int y);
|
||||
|
||||
|
||||
//
|
||||
// Private data members
|
||||
//
|
||||
|
||||
int id;
|
||||
|
||||
CardWindow &parentWnd;
|
||||
|
||||
CardStack cardstack; //cards in this stack
|
||||
CardStack dragstack; //cards which we might be dragging
|
||||
|
||||
bool fMouseDragging;
|
||||
|
||||
int xoffset; //direction that cards take
|
||||
int yoffset;
|
||||
|
||||
int xpos; //coordinates of stack
|
||||
int ypos;
|
||||
|
||||
int width; //stack-size of all cards
|
||||
int height;
|
||||
|
||||
//
|
||||
// justify / placement vars
|
||||
int xjustify;
|
||||
int yjustify;
|
||||
int xadjust;
|
||||
int yadjust;
|
||||
|
||||
//
|
||||
// Used for mouse-dragging / moving cards
|
||||
//
|
||||
int iNumDragCards;
|
||||
int mousexoffset;
|
||||
int mouseyoffset;
|
||||
int oldx;
|
||||
int oldy;
|
||||
|
||||
int nDragCardWidth;
|
||||
int nDragCardHeight;
|
||||
|
||||
HDC hdcBackGnd;
|
||||
HBITMAP hbmBackGnd;
|
||||
HDC hdcDragCard;
|
||||
HBITMAP hbmDragCard;
|
||||
|
||||
int nNumApparentCards;
|
||||
int nThreedCount;
|
||||
bool fVisible;
|
||||
|
||||
int nFlashCount;
|
||||
bool fFlashVisible;
|
||||
UINT uFlashTimer;
|
||||
|
||||
COLORREF crBackgnd;
|
||||
|
||||
UINT uEmptyImage;
|
||||
UINT uFaceDirType;
|
||||
int nFaceDirOption;
|
||||
int nBackCardIdx;
|
||||
|
||||
UINT uDragRule;
|
||||
UINT uDropRule;
|
||||
|
||||
//
|
||||
// Stack callback support
|
||||
//
|
||||
pCanDragProc CanDragCallback;
|
||||
pCanDropProc CanDropCallback;
|
||||
pClickProc ClickCallback;
|
||||
pClickProc DblClickCallback;
|
||||
pAddProc AddCallback;
|
||||
pRemoveProc RemoveCallback;
|
||||
|
||||
//locking mechanism to prevent user dragging etc
|
||||
HANDLE mxlock;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
613
rosapps/games/solitaire/cardlib/cardrgndraw.cpp
Normal file
613
rosapps/games/solitaire/cardlib/cardrgndraw.cpp
Normal file
|
@ -0,0 +1,613 @@
|
|||
//
|
||||
// CardLib - CardRegion drawing support
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "cardlib.h"
|
||||
#include "cardregion.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette);
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
|
||||
void CardBlt(HDC hdc, int x, int y, int nCardNum);
|
||||
void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
|
||||
|
||||
//
|
||||
// Draw specified card at position x, y
|
||||
// xoff - source offset from left of card
|
||||
// yoff - source offset from top of card
|
||||
// width - width to draw
|
||||
// height - height to draw
|
||||
//
|
||||
void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height)
|
||||
{
|
||||
int sx = nCardNum * __cardwidth;
|
||||
int sy = 0;
|
||||
int width = __cardwidth;
|
||||
int height = __cardheight;
|
||||
|
||||
//draw main center band
|
||||
BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY);
|
||||
|
||||
//draw the two bits to the left
|
||||
BitBlt(hdc, x, y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY);
|
||||
BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY);
|
||||
|
||||
//draw the two bits to the right
|
||||
BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY);
|
||||
BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY);
|
||||
}
|
||||
|
||||
//
|
||||
// Draw a shape this this:
|
||||
//
|
||||
// ++++++++++++
|
||||
// ++++++++++++++
|
||||
// ++ ++
|
||||
//
|
||||
void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips)
|
||||
{
|
||||
int sx = nCardNum * __cardwidth;
|
||||
int sy = 0;
|
||||
int one = 1;
|
||||
int two = 2;
|
||||
BOOL tips = fDrawTips ? FALSE : TRUE;
|
||||
|
||||
if(height == 0) return;
|
||||
|
||||
if(height < 0)
|
||||
{
|
||||
sy = sy + __cardheight;
|
||||
y -= height;
|
||||
one = -one;
|
||||
two = -two;
|
||||
}
|
||||
|
||||
// draw the main vertical band
|
||||
//
|
||||
BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY);
|
||||
|
||||
//if(height <= 1) return;
|
||||
|
||||
// draw the "lips" at the left and right
|
||||
BitBlt(hdc, x+1, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1, sy+one, SRCCOPY);
|
||||
BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY);
|
||||
|
||||
//if(height <= 2) return;
|
||||
|
||||
// draw the outer-most lips
|
||||
BitBlt(hdc, x, y+two, 1, height-two*tips, __hdcCardBitmaps, sx, sy+two, SRCCOPY);
|
||||
BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY);
|
||||
}
|
||||
|
||||
//
|
||||
// Draw a shape like this:
|
||||
//
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
// +++
|
||||
//
|
||||
//
|
||||
void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips)
|
||||
{
|
||||
int sx = nCardNum * __cardwidth;
|
||||
int sy = 0;
|
||||
int one = 1;
|
||||
int two = 2;
|
||||
BOOL tips = fDrawTips ? FALSE : TRUE;
|
||||
|
||||
if(width == 0) return;
|
||||
|
||||
|
||||
if(width < 0)
|
||||
{
|
||||
sx = sx + __cardwidth;
|
||||
x -= width;
|
||||
one = -1;
|
||||
two = -2;
|
||||
}
|
||||
|
||||
// draw the main vertical band
|
||||
//
|
||||
BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY);
|
||||
|
||||
//if(width <= 1) return;
|
||||
|
||||
// draw the "lips" at the top and bottom
|
||||
BitBlt(hdc, x+one, y+1, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1, SRCCOPY);
|
||||
BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY);
|
||||
|
||||
//if(width <= 2) return;
|
||||
|
||||
// draw the outer-most lips
|
||||
BitBlt(hdc, x+two, y, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy, SRCCOPY);
|
||||
BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY);
|
||||
}
|
||||
|
||||
//
|
||||
// xdir - <0 or >0
|
||||
// ydir - <0 or >0
|
||||
//
|
||||
void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir)
|
||||
{
|
||||
int sx = cardval * __cardwidth;
|
||||
int sy = 0;
|
||||
|
||||
HDC hdcSource = __hdcCardBitmaps;
|
||||
|
||||
if(xdir < 0)
|
||||
{
|
||||
x += __cardwidth + xdir - 1;
|
||||
sx += __cardwidth + xdir - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xdir;
|
||||
sx += xdir;
|
||||
}
|
||||
|
||||
if(ydir < 0)
|
||||
{
|
||||
y += __cardheight + ydir - 1;
|
||||
sy += __cardheight + ydir - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
y += ydir;
|
||||
sy += ydir;
|
||||
}
|
||||
|
||||
//convert x,y directions to -1, +1
|
||||
xdir = xdir < 0 ? -1 : 1;
|
||||
ydir = ydir < 0 ? -1 : 1;
|
||||
|
||||
SetPixel(hdc, x+xdir, y , GetPixel(hdcSource, sx+xdir, sy));
|
||||
SetPixel(hdc, x, y, GetPixel(hdcSource, sx, sy));
|
||||
SetPixel(hdc, x, y+ydir, GetPixel(hdcSource, sx, sy+ydir));
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Draw a card (i.e. miss out the corners)
|
||||
//
|
||||
void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height)
|
||||
{
|
||||
//draw main center band
|
||||
BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY);
|
||||
|
||||
//draw the two bits to the left
|
||||
BitBlt(hdc, x, y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY);
|
||||
BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY);
|
||||
|
||||
//draw the two bits to the right
|
||||
BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY);
|
||||
BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY);
|
||||
}
|
||||
|
||||
//
|
||||
// Clip a card SHAPE - basically any rectangle
|
||||
// with rounded corners
|
||||
//
|
||||
int ClipCard(HDC hdc, int x, int y, int width, int height)
|
||||
{
|
||||
ExcludeClipRect(hdc, x+2, y, x+2+width-4, y+ height);
|
||||
ExcludeClipRect(hdc, x, y+2, x+1, y+2+height-4);
|
||||
ExcludeClipRect(hdc, x+1, y+1, x+2, y+1+height-2);
|
||||
ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2);
|
||||
ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CardRegion::Clip(HDC hdc)
|
||||
{
|
||||
int numtoclip;
|
||||
|
||||
if(fVisible == false)
|
||||
return;
|
||||
|
||||
Update(); //Update this stack's size+card count
|
||||
numtoclip = nNumApparentCards;
|
||||
|
||||
//if we are making this stack flash on/off, then only
|
||||
//clip the stack for drawing if the flash is in its ON state
|
||||
if(nFlashCount != 0)
|
||||
{
|
||||
if(fFlashVisible == FALSE)
|
||||
numtoclip = 0;
|
||||
}
|
||||
|
||||
//if offset along a diagonal
|
||||
if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0)
|
||||
{
|
||||
for(int j = 0; j < numtoclip; j ++)
|
||||
{
|
||||
ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight);
|
||||
}
|
||||
}
|
||||
//otherwise if just offset along a horizontal/vertical axis
|
||||
else
|
||||
{
|
||||
if(yoffset < 0 && numtoclip > 0)
|
||||
{
|
||||
ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height);
|
||||
}
|
||||
else if(xoffset < 0 && numtoclip > 0)
|
||||
{
|
||||
ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipCard(hdc, xpos, ypos, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CardRegion::Render(HDC hdc)
|
||||
{
|
||||
int cardnum = 0;
|
||||
int numtodraw;
|
||||
BOOL fDrawTips;
|
||||
|
||||
Update(); //Update this stack's card count + size
|
||||
|
||||
numtodraw = nNumApparentCards;
|
||||
|
||||
if(nFlashCount != 0)
|
||||
{
|
||||
if(fFlashVisible == false)
|
||||
numtodraw = 0;
|
||||
}
|
||||
|
||||
if(fVisible == 0) return;
|
||||
|
||||
cardnum = cardstack.NumCards() - numtodraw;
|
||||
int counter;
|
||||
|
||||
for(counter = 0; counter < numtodraw; counter++)
|
||||
{
|
||||
int cardval;
|
||||
|
||||
int x = xoffset * counter + xpos;
|
||||
int y = yoffset * counter + ypos;
|
||||
|
||||
//if about to draw last card, then actually draw the top card
|
||||
if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1;
|
||||
|
||||
Card card = cardstack.cardlist[cardnum];
|
||||
cardval = card.Idx();
|
||||
|
||||
if(card.FaceDown())
|
||||
cardval = nBackCardIdx; //card-back
|
||||
|
||||
//only draw the visible part of the card
|
||||
if(counter < numtodraw - 1)
|
||||
{
|
||||
if(yoffset != 0 && xoffset != 0)
|
||||
fDrawTips = FALSE;
|
||||
else
|
||||
fDrawTips = TRUE;
|
||||
|
||||
if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1)
|
||||
fDrawTips = TRUE;
|
||||
|
||||
//draw horizontal strips
|
||||
if(yoffset > 0)
|
||||
{
|
||||
DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips);
|
||||
}
|
||||
else if(yoffset < 0)
|
||||
{
|
||||
DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips);
|
||||
}
|
||||
|
||||
//draw some vertical bars
|
||||
if(xoffset > 0)
|
||||
{
|
||||
DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips);
|
||||
}
|
||||
else if(xoffset < 0)
|
||||
{
|
||||
DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips);
|
||||
}
|
||||
|
||||
if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE)
|
||||
{
|
||||
//if we didn't draw any tips, then this is a 2-dim stack
|
||||
//(i.e, it goes at a diagonal).
|
||||
//in this case, we need to fill in the small triangle in
|
||||
//each corner!
|
||||
DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset);
|
||||
}
|
||||
}
|
||||
//if the top card, draw the whole thing
|
||||
else
|
||||
{
|
||||
CardBlt(hdc, x, y, cardval);
|
||||
}
|
||||
|
||||
cardnum ++;
|
||||
|
||||
} //end of index
|
||||
|
||||
if(counter == 0) //if the cardstack is empty, then draw it that way
|
||||
{
|
||||
int x = xpos;
|
||||
int y = ypos;
|
||||
|
||||
switch(uEmptyImage)
|
||||
{
|
||||
default: case CS_EI_NONE:
|
||||
//this wipes the RECT variable, so watch out!
|
||||
//SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);
|
||||
//PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
|
||||
parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y);
|
||||
break;
|
||||
|
||||
case CS_EI_SUNK: //case CS_EI_CIRC: case CS_EI_X:
|
||||
DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int calc_offset(int offset, int numcards, int numtodrag, int realvisible)
|
||||
{
|
||||
if(offset >= 0)
|
||||
return -offset * numcards;
|
||||
else
|
||||
return -offset * (numtodrag) +
|
||||
-offset * (realvisible - 1);
|
||||
}
|
||||
|
||||
void CardRegion::PrepareDragBitmaps(int numtodrag)
|
||||
{
|
||||
RECT rect;
|
||||
HDC hdc;
|
||||
int icard;
|
||||
int numcards = cardstack.NumCards();
|
||||
int xoff, yoff;
|
||||
|
||||
if(nThreedCount > 1)
|
||||
{
|
||||
PrepareDragBitmapsThreed(numtodrag);
|
||||
return;
|
||||
}
|
||||
|
||||
//work out how big the bitmaps need to be
|
||||
nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;
|
||||
nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;
|
||||
|
||||
//Create bitmap for the back-buffer
|
||||
hdc = GetDC(NULL);
|
||||
hdcBackGnd = CreateCompatibleDC(hdc);
|
||||
hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
|
||||
SelectObject(hdcBackGnd, hbmBackGnd);
|
||||
|
||||
//Create bitmap for the drag-image
|
||||
hdcDragCard = CreateCompatibleDC(hdc);
|
||||
hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
|
||||
SelectObject(hdcDragCard, hbmDragCard);
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
UseNicePalette(hdcBackGnd, __hPalette);
|
||||
UseNicePalette(hdcDragCard, __hPalette);
|
||||
|
||||
int realvisible = numcards / nThreedCount;
|
||||
|
||||
//if(numcards > 0 && realvisible == 0) realvisible = 1;
|
||||
int iwhichcard = numcards - 1;
|
||||
if(nThreedCount == 1) iwhichcard = 0;
|
||||
|
||||
//grab the first bit of background so we can prep the back buffer; do this by
|
||||
//rendering the card stack (minus the card we are dragging) to the temporary
|
||||
//background buffer, so it appears if we have lifted the card from the stack
|
||||
//PaintRect(hdcBackGnd, &rect, crBackgnd);
|
||||
SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
|
||||
|
||||
xoff = calc_offset(xoffset, numcards, numtodrag, realvisible);
|
||||
yoff = calc_offset(yoffset, numcards, numtodrag, realvisible);
|
||||
|
||||
parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff, ypos - yoff);
|
||||
|
||||
//
|
||||
// Render the cardstack into the back-buffer. The stack
|
||||
// has already had the dragcards removed, so just draw
|
||||
// what is left
|
||||
//
|
||||
for(icard = 0; icard < realvisible; icard++)
|
||||
{
|
||||
Card card = cardstack.cardlist[iwhichcard];
|
||||
int nCardVal;
|
||||
|
||||
nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
|
||||
|
||||
xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
|
||||
yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
|
||||
|
||||
CardBlt(hdcBackGnd, xoff, yoff, nCardVal);
|
||||
iwhichcard++;
|
||||
}
|
||||
|
||||
//
|
||||
// If there are no cards under this one, just draw the place holder
|
||||
//
|
||||
if(numcards == 0)
|
||||
{
|
||||
int xoff = 0, yoff = 0;
|
||||
|
||||
if(xoffset < 0) xoff = nDragCardWidth - __cardwidth;
|
||||
if(yoffset < 0) yoff = nDragCardHeight - __cardheight;
|
||||
|
||||
switch(uEmptyImage)
|
||||
{
|
||||
case CS_EI_NONE:
|
||||
//No need to draw anything: We already cleared the
|
||||
//back-buffer before the main loop..
|
||||
|
||||
//SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);
|
||||
//PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));
|
||||
//parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);
|
||||
break;
|
||||
|
||||
case CS_EI_SUNK:
|
||||
DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now render the drag-cards into the dragcard image
|
||||
//
|
||||
PaintRect(hdcDragCard, &rect, crBackgnd);
|
||||
|
||||
for(icard = 0; icard < numtodrag; icard++)
|
||||
{
|
||||
int nCardVal;
|
||||
|
||||
if(xoffset >= 0) xoff = xoffset * icard;
|
||||
else xoff = -xoffset * (numtodrag - icard - 1);
|
||||
|
||||
if(yoffset >= 0) yoff = yoffset * icard;
|
||||
else yoff = -yoffset * (numtodrag - icard - 1);
|
||||
|
||||
Card card = dragstack.cardlist[icard];
|
||||
|
||||
nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
|
||||
|
||||
CardBlt(hdcDragCard, xoff, yoff, nCardVal);
|
||||
}
|
||||
}
|
||||
|
||||
void CardRegion::PrepareDragBitmapsThreed(int numtodrag)
|
||||
{
|
||||
RECT rect;
|
||||
HDC hdc;
|
||||
int icard;
|
||||
int numunder = 0;
|
||||
int iwhichcard;
|
||||
|
||||
int numcards = cardstack.NumCards();
|
||||
|
||||
//work out how big the bitmaps need to be
|
||||
nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;
|
||||
nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;
|
||||
|
||||
//Create bitmap for the back-buffer
|
||||
hdc = GetDC(NULL);
|
||||
hdcBackGnd = CreateCompatibleDC(hdc);
|
||||
hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
|
||||
SelectObject(hdcBackGnd, hbmBackGnd);
|
||||
|
||||
//create bitmap for the drag-image
|
||||
hdcDragCard = CreateCompatibleDC(hdc);
|
||||
hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);
|
||||
SelectObject(hdcDragCard, hbmDragCard);
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
UseNicePalette(hdcBackGnd, __hPalette);
|
||||
UseNicePalette(hdcDragCard, __hPalette);
|
||||
|
||||
//grab the first bit of background so we can prep the back buffer; do this by
|
||||
//rendering the card stack (minus the card we are dragging) to the temporary
|
||||
//background buffer, so it appears if we have lifted the card from the stack
|
||||
//--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
|
||||
//--PaintRect(hdcBackGnd, &rect, crBackgnd);
|
||||
|
||||
int threedadjust = numcards % nThreedCount == 0;
|
||||
|
||||
numunder = CalcApparentCards(numcards);
|
||||
iwhichcard = (numcards+numtodrag) - numunder - 1;
|
||||
if(nThreedCount == 1) iwhichcard = 0;
|
||||
|
||||
int xoff = calc_offset(xoffset, numunder, numtodrag, numunder);
|
||||
int yoff = calc_offset(yoffset, numunder, numtodrag, numunder);
|
||||
|
||||
parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff);
|
||||
|
||||
//
|
||||
// Render the cardstack into the back-buffer. The stack
|
||||
// has already had the dragcards removed, so just draw
|
||||
// what is left
|
||||
//
|
||||
for(icard = 0; icard < numunder; icard++)
|
||||
{
|
||||
Card card = cardstack.cardlist[iwhichcard];
|
||||
int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
|
||||
|
||||
CardBlt(hdcBackGnd,
|
||||
xoffset * icard - xoffset*(numunder-numtodrag+threedadjust),
|
||||
yoffset * icard - yoffset*(numunder-numtodrag+threedadjust),
|
||||
nCardVal);
|
||||
|
||||
iwhichcard++;
|
||||
}
|
||||
|
||||
//
|
||||
// If there are no cards under this one, just draw the place holder
|
||||
//
|
||||
if(numcards == 0)
|
||||
{
|
||||
switch(uEmptyImage)
|
||||
{
|
||||
case CS_EI_NONE:
|
||||
//no need! we've already cleared the whole
|
||||
//back-buffer before the main loop!
|
||||
//SetRect(&rect, 0, 0, __cardwidth, __cardheight);
|
||||
//PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));
|
||||
break;
|
||||
|
||||
case CS_EI_SUNK:
|
||||
DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now render the drag-cards into the dragcard image
|
||||
//
|
||||
PaintRect(hdcDragCard, &rect, crBackgnd);
|
||||
|
||||
for(icard = 0; icard < numtodrag; icard++)
|
||||
{
|
||||
Card card = dragstack.cardlist[icard];
|
||||
int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;
|
||||
|
||||
CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal);
|
||||
}
|
||||
}
|
||||
|
||||
void CardRegion::ReleaseDragBitmaps(void)
|
||||
{
|
||||
//SelectObject(hdcBackGnd, hOld1);
|
||||
DeleteObject(hbmBackGnd);
|
||||
DeleteDC(hdcBackGnd);
|
||||
|
||||
//SelectObject(hdcDragCard, hOld2);
|
||||
DeleteObject(hbmDragCard);
|
||||
DeleteDC(hdcDragCard);
|
||||
}
|
||||
|
||||
|
||||
void CardRegion::Redraw()
|
||||
{
|
||||
HDC hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
Update();
|
||||
Render(hdc);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
}
|
618
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp
Normal file
618
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp
Normal file
|
@ -0,0 +1,618 @@
|
|||
//
|
||||
// CardLib - CardRegion mouse-related stuff
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardregion.h"
|
||||
|
||||
double __CARDZOOMSPEED = 32;
|
||||
|
||||
int ClipCard(HDC hdc, int x, int y, int width, int height);
|
||||
void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
static pDebugClickProc DebugStackClickProc = 0;
|
||||
|
||||
void CardLib_SetStackClickProc(pDebugClickProc proc)
|
||||
{
|
||||
DebugStackClickProc = proc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)
|
||||
{
|
||||
int maxoverlap = 0;
|
||||
int maxoverlapidx = -1;
|
||||
|
||||
//find the stack which is most covered by the dropped
|
||||
//cards. Only include those which allow drops.
|
||||
//
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
int percent = Regions[i]->GetOverlapRatio(x, y, w, h);
|
||||
|
||||
//if this stack has the biggest coverage yet
|
||||
if(percent > maxoverlap && Regions[i]->IsVisible())
|
||||
{
|
||||
maxoverlap = percent;
|
||||
maxoverlapidx = i;
|
||||
}
|
||||
}
|
||||
|
||||
//if we found a stack to drop onto
|
||||
if(maxoverlapidx != -1)
|
||||
{
|
||||
return Regions[maxoverlapidx];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::IsPointInStack(int x, int y)
|
||||
{
|
||||
int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;
|
||||
int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;
|
||||
|
||||
if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int CardRegion::GetNumDragCards(int x, int y)
|
||||
{
|
||||
int cardindex = 0; //index from stack start
|
||||
int maxidx;
|
||||
|
||||
//make x,y relative to the stack's upper left corner
|
||||
x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);
|
||||
y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);
|
||||
|
||||
//if stack is empty, cannot drag any cards from it
|
||||
if(cardstack.NumCards() <= 0)
|
||||
return 0;
|
||||
|
||||
//see which card in the stack has been clicked on
|
||||
//top-bottom ordering
|
||||
if(yoffset > 0)
|
||||
{
|
||||
if(y < height - __cardheight)
|
||||
cardindex = y / yoffset;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
else if(yoffset < 0)
|
||||
{
|
||||
if(y < __cardheight)
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;
|
||||
}
|
||||
else //yoffset == 0
|
||||
{
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
|
||||
maxidx = cardindex;
|
||||
|
||||
//if left-right
|
||||
if(xoffset > 0)
|
||||
{
|
||||
if(x < width - __cardwidth)
|
||||
cardindex = x / xoffset;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
else if(xoffset < 0)
|
||||
{
|
||||
if(x < __cardwidth)
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
|
||||
if(cardindex > maxidx) cardindex = maxidx;
|
||||
|
||||
if(cardindex > cardstack.NumCards())
|
||||
cardindex = 1;
|
||||
|
||||
//if are trying to drag too many cards at once
|
||||
return cardstack.NumCards() - cardindex;
|
||||
}
|
||||
|
||||
bool CardRegion::CanDragCards(int iNumCards)
|
||||
{
|
||||
if(iNumCards <= 0) return false;
|
||||
if(nThreedCount > 1 && iNumCards > 1) return false;
|
||||
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
// TRACE("Failed to gain access to card stack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ReleaseMutex(mxlock);
|
||||
|
||||
switch(uDragRule)
|
||||
{
|
||||
case CS_DRAG_ALL:
|
||||
return true;
|
||||
|
||||
case CS_DRAG_TOP:
|
||||
|
||||
if(iNumCards == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
case CS_DRAG_NONE:
|
||||
return false;
|
||||
|
||||
case CS_DRAG_CALLBACK:
|
||||
|
||||
if(CanDragCallback)
|
||||
{
|
||||
return CanDragCallback(*this, iNumCards);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::CanDropCards(CardStack &cards)
|
||||
{
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReleaseMutex(mxlock);
|
||||
|
||||
switch(uDropRule)
|
||||
{
|
||||
case CS_DROP_ALL:
|
||||
return true;
|
||||
|
||||
case CS_DROP_NONE:
|
||||
return false;
|
||||
|
||||
case CS_DROP_CALLBACK:
|
||||
|
||||
if(CanDropCallback)
|
||||
{
|
||||
return CanDropCallback(*this, cards);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::OnLButtonDblClk(int x, int y)
|
||||
{
|
||||
iNumDragCards = GetNumDragCards(x, y);
|
||||
|
||||
if(DblClickCallback)
|
||||
DblClickCallback(*this, iNumDragCards);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardRegion::OnLButtonDown(int x, int y)
|
||||
{
|
||||
iNumDragCards = GetNumDragCards(x, y);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(DebugStackClickProc)
|
||||
{
|
||||
if(!DebugStackClickProc(*this))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ClickCallback)
|
||||
ClickCallback(*this, iNumDragCards);
|
||||
|
||||
if(CanDragCards(iNumDragCards) != false)
|
||||
{
|
||||
|
||||
//offset of the mouse cursor relative to the top-left corner
|
||||
//of the cards that are being dragged
|
||||
mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);
|
||||
mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);
|
||||
|
||||
if(xoffset < 0)
|
||||
mousexoffset += -xoffset * (iNumDragCards - 1);
|
||||
|
||||
if(yoffset < 0)
|
||||
mouseyoffset += -yoffset * (iNumDragCards - 1);
|
||||
|
||||
//remove the cards from the source stack
|
||||
dragstack = cardstack.Pop(iNumDragCards);
|
||||
|
||||
//prepare the back buffer, and the drag image
|
||||
PrepareDragBitmaps(iNumDragCards);
|
||||
|
||||
oldx = x - mousexoffset;
|
||||
oldy = y - mouseyoffset;
|
||||
|
||||
Update(); //Update this stack's card count + size
|
||||
|
||||
SetCapture((HWND)parentWnd);
|
||||
|
||||
//set AFTER settings the dragstack...
|
||||
fMouseDragging = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
if(pDestStack && pDestStack->CanDropCards(dragstack))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, let the cards snap back onto this stack
|
||||
//
|
||||
else
|
||||
{
|
||||
|
||||
hdc = GetDC((HWND)parentWnd);
|
||||
ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);
|
||||
cardstack += dragstack;
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
|
||||
Update(); //Update this stack's card count + size
|
||||
}
|
||||
|
||||
ReleaseDragBitmaps();
|
||||
ReleaseCapture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardRegion::OnMouseMove(int x, int y)
|
||||
{
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
x -= mousexoffset;
|
||||
y -= mouseyoffset;
|
||||
|
||||
MoveDragCardTo(hdc, x, y);
|
||||
|
||||
//BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
|
||||
//BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// There is a bug in BitBlt when the source x,y
|
||||
// become < 0. So this wrapper function simply adjusts
|
||||
// the coords so that we never try to blt in from this range
|
||||
//
|
||||
BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)
|
||||
{
|
||||
if(srcx < 0)
|
||||
{
|
||||
x = 0 - srcx;
|
||||
width = width + srcx;
|
||||
srcx = 0;
|
||||
}
|
||||
|
||||
if(srcy < 0)
|
||||
{
|
||||
y = 0 - srcy;
|
||||
height = height + srcy;
|
||||
srcy = 0;
|
||||
}
|
||||
|
||||
return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);
|
||||
}
|
||||
|
||||
void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)
|
||||
{
|
||||
RECT inter, rect1, rect2;
|
||||
|
||||
//mask off the new position of the drag-card, so
|
||||
//that it will not be painted over
|
||||
ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);
|
||||
|
||||
//restore the area covered by the card at its previous position
|
||||
BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
|
||||
|
||||
//remove clipping so we can draw the card at its new place
|
||||
SelectClipRgn(hdc, NULL);
|
||||
|
||||
//if the card's old and new positions overlap, then we
|
||||
//need some funky code to update the "saved background" image,
|
||||
SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);
|
||||
SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight);
|
||||
|
||||
if(IntersectRect(&inter, &rect1, &rect2))
|
||||
{
|
||||
int interwidth = inter.right-inter.left;
|
||||
int interheight = inter.bottom-inter.top;
|
||||
int destx, desty, srcx, srcy;
|
||||
|
||||
if(rect2.left > rect1.left)
|
||||
{
|
||||
destx = 0; srcx = nDragCardWidth - interwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
destx = nDragCardWidth - interwidth; srcx = 0;
|
||||
}
|
||||
|
||||
if(rect2.top > rect1.top)
|
||||
{
|
||||
desty = 0; srcy = nDragCardHeight - interheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
desty = nDragCardHeight - interheight; srcy = 0;
|
||||
}
|
||||
|
||||
//shift the bit we didn't use for the restore (due to the clipping)
|
||||
//into the opposite corner
|
||||
BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);
|
||||
|
||||
ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);
|
||||
|
||||
//this bit requires us to clip the BitBlt (from screen to background)
|
||||
//as BitBlt is a bit buggy it seems
|
||||
ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
|
||||
SelectClipRgn(hdcBackGnd, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
|
||||
}
|
||||
|
||||
//finally draw the card to the screen
|
||||
DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);
|
||||
}
|
||||
|
||||
|
||||
//extern "C" int _fltused(void) { return 0; }
|
||||
//extern "C" int _ftol(void) { return 0; }
|
||||
|
||||
//
|
||||
// Better do this in fixed-point, to stop
|
||||
// VC from linking in floatingpoint-long conversions
|
||||
//
|
||||
//#define FIXED_PREC_MOVE
|
||||
#ifdef FIXED_PREC_MOVE
|
||||
#define PRECISION 12
|
||||
void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)
|
||||
{
|
||||
long dx, dy, x , y;
|
||||
|
||||
|
||||
int apparentcards;
|
||||
x = xpos << PRECISION; y = ypos << PRECISION;
|
||||
|
||||
oldx = (int)xpos;
|
||||
oldy = (int)ypos;
|
||||
|
||||
apparentcards=dest->numcards/dest->threedcount;
|
||||
|
||||
int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards);
|
||||
int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);
|
||||
|
||||
//normalise the motion vector
|
||||
dx = (idestx<<PRECISION) - x;
|
||||
dy = (idesty<<PRECISION) - y;
|
||||
long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);
|
||||
|
||||
dx *= recip * 16;//CARDZOOMSPEED;
|
||||
dy *= recip * 16;//CARDZOOMSPEED;
|
||||
|
||||
//if(dx < 0) dxinc = 1.001; else
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int ix, iy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
ix = (int)x>>PRECISION;
|
||||
iy = (int)y>>PRECISION;
|
||||
if(dx < 0 && ix < idestx) ix = idestx;
|
||||
else if(dx > 0 && ix > idestx) ix = idestx;
|
||||
|
||||
if(dy < 0 && iy < idesty) iy = idesty;
|
||||
else if(dy > 0 && iy > idesty) iy = idesty;
|
||||
|
||||
MoveDragCardTo(hdc, ix, iy);
|
||||
|
||||
if(ix == idestx && iy == idesty)
|
||||
break;
|
||||
|
||||
oldx = (int)x >> PRECISION;
|
||||
oldy = (int)y >> PRECISION;
|
||||
|
||||
//dx *= 1.2;
|
||||
//dy *= 1.2;
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)
|
||||
{
|
||||
double dx, dy, x ,y;
|
||||
int apparentcards;
|
||||
x = (double)xpos; y = (double)ypos;
|
||||
|
||||
oldx = (int)x;
|
||||
oldy = (int)y;
|
||||
|
||||
apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;
|
||||
|
||||
int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);
|
||||
int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);
|
||||
|
||||
if(pDestStack->yoffset < 0)
|
||||
idesty += pDestStack->yoffset * (iNumDragCards-1);
|
||||
|
||||
if(pDestStack->xoffset < 0)
|
||||
idestx += pDestStack->xoffset * (iNumDragCards-1);
|
||||
|
||||
//normalise the motion vector
|
||||
dx = idestx - x;
|
||||
dy = idesty - y;
|
||||
double recip = 1.0 / sqrt(dx*dx + dy*dy);
|
||||
dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;
|
||||
|
||||
//if(dx < 0) dxinc = 1.001; else
|
||||
|
||||
for(;;)
|
||||
{
|
||||
bool attarget = true;
|
||||
int ix, iy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
ix = (int)x;
|
||||
iy = (int)y;
|
||||
if(dx < 0.0 && ix < idestx) ix = idestx;
|
||||
else if(dx > 0.0 && ix > idestx) ix = idestx;
|
||||
else attarget = false;
|
||||
|
||||
if(dy < 0.0 && iy < idesty) iy = idesty;
|
||||
else if(dy > 0.0 && iy > idesty) iy = idesty;
|
||||
else attarget = false;
|
||||
|
||||
//if the target stack wants the drag cards drawn differently
|
||||
//to how they are, then redraw the drag card image just before
|
||||
//the cards land
|
||||
/*if(attarget == true)
|
||||
{
|
||||
for(int i = 0; i < iNumDragCards; i++)
|
||||
{
|
||||
int xdraw = pDestStack->xoffset*i;
|
||||
int ydraw = pDestStack->yoffset*i;
|
||||
|
||||
if(pDestStack->yoffset < 0)
|
||||
ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);
|
||||
if(pDestStack->xoffset < 0)
|
||||
xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);
|
||||
|
||||
if(pDestStack->facedirection == CS_FACEUP &&
|
||||
pDestStack->numcards+i >= dest->numfacedown)
|
||||
{
|
||||
//cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
MoveDragCardTo(hdc, ix, iy);
|
||||
|
||||
if(attarget || ix == idestx && iy == idesty)
|
||||
break;
|
||||
|
||||
oldx = (int)x;
|
||||
oldy = (int)y;
|
||||
|
||||
//dx *= 1.2;
|
||||
//dy *= 1.2;
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
#endif
|
618
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp.bak
Normal file
618
rosapps/games/solitaire/cardlib/cardrgnmouse.cpp.bak
Normal file
|
@ -0,0 +1,618 @@
|
|||
//
|
||||
// CardLib - CardRegion mouse-related stuff
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardregion.h"
|
||||
|
||||
double __CARDZOOMSPEED = 32;
|
||||
|
||||
int ClipCard(HDC hdc, int x, int y, int width, int height);
|
||||
void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
static pDebugClickProc DebugStackClickProc = 0;
|
||||
|
||||
void CardLib_SetStackClickProc(pDebugClickProc proc)
|
||||
{
|
||||
DebugStackClickProc = proc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)
|
||||
{
|
||||
int maxoverlap = 0;
|
||||
int maxoverlapidx = -1;
|
||||
|
||||
//find the stack which is most covered by the dropped
|
||||
//cards. Only include those which allow drops.
|
||||
//
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
int percent = Regions[i]->GetOverlapRatio(x, y, w, h);
|
||||
|
||||
//if this stack has the biggest coverage yet
|
||||
if(percent > maxoverlap && Regions[i]->IsVisible())
|
||||
{
|
||||
maxoverlap = percent;
|
||||
maxoverlapidx = i;
|
||||
}
|
||||
}
|
||||
|
||||
//if we found a stack to drop onto
|
||||
if(maxoverlapidx != -1)
|
||||
{
|
||||
return Regions[maxoverlapidx];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::IsPointInStack(int x, int y)
|
||||
{
|
||||
int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;
|
||||
int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;
|
||||
|
||||
if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int CardRegion::GetNumDragCards(int x, int y)
|
||||
{
|
||||
int cardindex = 0; //index from stack start
|
||||
int maxidx;
|
||||
|
||||
//make x,y relative to the stack's upper left corner
|
||||
x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);
|
||||
y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);
|
||||
|
||||
//if stack is empty, cannot drag any cards from it
|
||||
if(cardstack.NumCards() <= 0)
|
||||
return 0;
|
||||
|
||||
//see which card in the stack has been clicked on
|
||||
//top-bottom ordering
|
||||
if(yoffset > 0)
|
||||
{
|
||||
if(y < height - __cardheight)
|
||||
cardindex = y / yoffset;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
else if(yoffset < 0)
|
||||
{
|
||||
if(y < __cardheight)
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;
|
||||
}
|
||||
else //yoffset == 0
|
||||
{
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
|
||||
maxidx = cardindex;
|
||||
|
||||
//if left-right
|
||||
if(xoffset > 0)
|
||||
{
|
||||
if(x < width - __cardwidth)
|
||||
cardindex = x / xoffset;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
else if(xoffset < 0)
|
||||
{
|
||||
if(x < __cardwidth)
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
else
|
||||
cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cardindex = cardstack.NumCards() - 1;
|
||||
}
|
||||
|
||||
if(cardindex > maxidx) cardindex = maxidx;
|
||||
|
||||
if(cardindex > cardstack.NumCards())
|
||||
cardindex = 1;
|
||||
|
||||
//if are trying to drag too many cards at once
|
||||
return cardstack.NumCards() - cardindex;
|
||||
}
|
||||
|
||||
bool CardRegion::CanDragCards(int iNumCards)
|
||||
{
|
||||
if(iNumCards <= 0) return false;
|
||||
if(nThreedCount > 1 && iNumCards > 1) return false;
|
||||
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
// TRACE("Failed to gain access to card stack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ReleaseMutex(mxlock);
|
||||
|
||||
switch(uDragRule)
|
||||
{
|
||||
case CS_DRAG_ALL:
|
||||
return true;
|
||||
|
||||
case CS_DRAG_TOP:
|
||||
|
||||
if(iNumCards == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
case CS_DRAG_NONE:
|
||||
return false;
|
||||
|
||||
case CS_DRAG_CALLBACK:
|
||||
|
||||
if(CanDragCallback)
|
||||
{
|
||||
return CanDragCallback(*this, iNumCards);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::CanDropCards(CardStack &cards)
|
||||
{
|
||||
if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReleaseMutex(mxlock);
|
||||
|
||||
switch(uDropRule)
|
||||
{
|
||||
case CS_DROP_ALL:
|
||||
return true;
|
||||
|
||||
case CS_DROP_NONE:
|
||||
return false;
|
||||
|
||||
case CS_DROP_CALLBACK:
|
||||
|
||||
if(CanDropCallback)
|
||||
{
|
||||
return CanDropCallback(*this, cards);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardRegion::OnLButtonDblClk(int x, int y)
|
||||
{
|
||||
iNumDragCards = GetNumDragCards(x, y);
|
||||
|
||||
if(DblClickCallback)
|
||||
DblClickCallback(*this, iNumDragCards);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardRegion::OnLButtonDown(int x, int y)
|
||||
{
|
||||
iNumDragCards = GetNumDragCards(x, y);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(DebugStackClickProc)
|
||||
{
|
||||
if(!DebugStackClickProc(*this))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ClickCallback)
|
||||
ClickCallback(*this, iNumDragCards);
|
||||
|
||||
if(CanDragCards(iNumDragCards) != false)
|
||||
{
|
||||
|
||||
//offset of the mouse cursor relative to the top-left corner
|
||||
//of the cards that are being dragged
|
||||
mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);
|
||||
mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);
|
||||
|
||||
if(xoffset < 0)
|
||||
mousexoffset += -xoffset * (iNumDragCards - 1);
|
||||
|
||||
if(yoffset < 0)
|
||||
mouseyoffset += -yoffset * (iNumDragCards - 1);
|
||||
|
||||
//remove the cards from the source stack
|
||||
dragstack = cardstack.Pop(iNumDragCards);
|
||||
|
||||
//prepare the back buffer, and the drag image
|
||||
PrepareDragBitmaps(iNumDragCards);
|
||||
|
||||
oldx = x - mousexoffset;
|
||||
oldy = y - mouseyoffset;
|
||||
|
||||
Update(); //Update this stack's card count + size
|
||||
|
||||
SetCapture((HWND)parentWnd);
|
||||
|
||||
//set AFTER settings the dragstack...
|
||||
fMouseDragging = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
if(pDestStack && pDestStack->CanDropCards(dragstack))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, let the cards snap back onto this stack
|
||||
//
|
||||
else
|
||||
{
|
||||
|
||||
hdc = GetDC((HWND)parentWnd);
|
||||
ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);
|
||||
cardstack += dragstack;
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
|
||||
Update(); //Update this stack's card count + size
|
||||
}
|
||||
|
||||
ReleaseDragBitmaps();
|
||||
ReleaseCapture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardRegion::OnMouseMove(int x, int y)
|
||||
{
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC((HWND)parentWnd);
|
||||
|
||||
x -= mousexoffset;
|
||||
y -= mouseyoffset;
|
||||
|
||||
MoveDragCardTo(hdc, x, y);
|
||||
|
||||
//BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
|
||||
//BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);
|
||||
|
||||
ReleaseDC((HWND)parentWnd, hdc);
|
||||
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// There is a bug in BitBlt when the source x,y
|
||||
// become < 0. So this wrapper function simply adjusts
|
||||
// the coords so that we never try to blt in from this range
|
||||
//
|
||||
BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)
|
||||
{
|
||||
if(srcx < 0)
|
||||
{
|
||||
x = 0 - srcx;
|
||||
width = width + srcx;
|
||||
srcx = 0;
|
||||
}
|
||||
|
||||
if(srcy < 0)
|
||||
{
|
||||
y = 0 - srcy;
|
||||
height = height + srcy;
|
||||
srcy = 0;
|
||||
}
|
||||
|
||||
return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);
|
||||
}
|
||||
|
||||
void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)
|
||||
{
|
||||
RECT inter, rect1, rect2;
|
||||
|
||||
//mask off the new position of the drag-card, so
|
||||
//that it will not be painted over
|
||||
ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);
|
||||
|
||||
//restore the area covered by the card at its previous position
|
||||
BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
|
||||
|
||||
//remove clipping so we can draw the card at its new place
|
||||
SelectClipRgn(hdc, NULL);
|
||||
|
||||
//if the card's old and new positions overlap, then we
|
||||
//need some funky code to update the "saved background" image,
|
||||
SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);
|
||||
SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight);
|
||||
|
||||
if(IntersectRect(&inter, &rect1, &rect2))
|
||||
{
|
||||
int interwidth = inter.right-inter.left;
|
||||
int interheight = inter.bottom-inter.top;
|
||||
int destx, desty, srcx, srcy;
|
||||
|
||||
if(rect2.left > rect1.left)
|
||||
{
|
||||
destx = 0; srcx = nDragCardWidth - interwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
destx = nDragCardWidth - interwidth; srcx = 0;
|
||||
}
|
||||
|
||||
if(rect2.top > rect1.top)
|
||||
{
|
||||
desty = 0; srcy = nDragCardHeight - interheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
desty = nDragCardHeight - interheight; srcy = 0;
|
||||
}
|
||||
|
||||
//shift the bit we didn't use for the restore (due to the clipping)
|
||||
//into the opposite corner
|
||||
BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);
|
||||
|
||||
ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);
|
||||
|
||||
//this bit requires us to clip the BitBlt (from screen to background)
|
||||
//as BitBlt is a bit buggy it seems
|
||||
ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
|
||||
SelectClipRgn(hdcBackGnd, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
|
||||
}
|
||||
|
||||
//finally draw the card to the screen
|
||||
DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);
|
||||
}
|
||||
|
||||
|
||||
//extern "C" int _fltused(void) { return 0; }
|
||||
//extern "C" int _ftol(void) { return 0; }
|
||||
|
||||
//
|
||||
// Better do this in fixed-point, to stop
|
||||
// VC from linking in floatingpoint-long conversions
|
||||
//
|
||||
//#define FIXED_PREC_MOVE
|
||||
#ifdef FIXED_PREC_MOVE
|
||||
#define PRECISION 12
|
||||
void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)
|
||||
{
|
||||
long dx, dy, x , y;
|
||||
|
||||
|
||||
int apparentcards;
|
||||
x = xpos << PRECISION; y = ypos << PRECISION;
|
||||
|
||||
oldx = (int)xpos;
|
||||
oldy = (int)ypos;
|
||||
|
||||
apparentcards=dest->numcards/dest->threedcount;
|
||||
|
||||
int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards);
|
||||
int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);
|
||||
|
||||
//normalise the motion vector
|
||||
dx = (idestx<<PRECISION) - x;
|
||||
dy = (idesty<<PRECISION) - y;
|
||||
long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);
|
||||
|
||||
dx *= recip * 16;//CARDZOOMSPEED;
|
||||
dy *= recip * 16;//CARDZOOMSPEED;
|
||||
|
||||
//if(dx < 0) dxinc = 1.001; else
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int ix, iy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
ix = (int)x>>PRECISION;
|
||||
iy = (int)y>>PRECISION;
|
||||
if(dx < 0 && ix < idestx) ix = idestx;
|
||||
else if(dx > 0 && ix > idestx) ix = idestx;
|
||||
|
||||
if(dy < 0 && iy < idesty) iy = idesty;
|
||||
else if(dy > 0 && iy > idesty) iy = idesty;
|
||||
|
||||
MoveDragCardTo(hdc, ix, iy);
|
||||
|
||||
if(ix == idestx && iy == idesty)
|
||||
break;
|
||||
|
||||
oldx = (int)x >> PRECISION;
|
||||
oldy = (int)y >> PRECISION;
|
||||
|
||||
//dx *= 1.2;
|
||||
//dy *= 1.2;
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)
|
||||
{
|
||||
double dx, dy, x ,y;
|
||||
int apparentcards;
|
||||
x = (double)xpos; y = (double)ypos;
|
||||
|
||||
oldx = (int)x;
|
||||
oldy = (int)y;
|
||||
|
||||
apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;
|
||||
|
||||
int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);
|
||||
int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);
|
||||
|
||||
if(pDestStack->yoffset < 0)
|
||||
idesty += pDestStack->yoffset * (iNumDragCards-1);
|
||||
|
||||
if(pDestStack->xoffset < 0)
|
||||
idestx += pDestStack->xoffset * (iNumDragCards-1);
|
||||
|
||||
//normalise the motion vector
|
||||
dx = idestx - x;
|
||||
dy = idesty - y;
|
||||
double recip = 1.0 / sqrt(dx*dx + dy*dy);
|
||||
dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;
|
||||
|
||||
//if(dx < 0) dxinc = 1.001; else
|
||||
|
||||
for(;;)
|
||||
{
|
||||
bool attarget = true;
|
||||
int ix, iy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
ix = (int)x;
|
||||
iy = (int)y;
|
||||
if(dx < 0.0 && ix < idestx) ix = idestx;
|
||||
else if(dx > 0.0 && ix > idestx) ix = idestx;
|
||||
else attarget = false;
|
||||
|
||||
if(dy < 0.0 && iy < idesty) iy = idesty;
|
||||
else if(dy > 0.0 && iy > idesty) iy = idesty;
|
||||
else attarget = false;
|
||||
|
||||
//if the target stack wants the drag cards drawn differently
|
||||
//to how they are, then redraw the drag card image just before
|
||||
//the cards land
|
||||
/*if(attarget == true)
|
||||
{
|
||||
for(int i = 0; i < iNumDragCards; i++)
|
||||
{
|
||||
int xdraw = pDestStack->xoffset*i;
|
||||
int ydraw = pDestStack->yoffset*i;
|
||||
|
||||
if(pDestStack->yoffset < 0)
|
||||
ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);
|
||||
if(pDestStack->xoffset < 0)
|
||||
xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);
|
||||
|
||||
if(pDestStack->facedirection == CS_FACEUP &&
|
||||
pDestStack->numcards+i >= dest->numfacedown)
|
||||
{
|
||||
//cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
MoveDragCardTo(hdc, ix, iy);
|
||||
|
||||
if(attarget || ix == idestx && iy == idesty)
|
||||
break;
|
||||
|
||||
oldx = (int)x;
|
||||
oldy = (int)y;
|
||||
|
||||
//dx *= 1.2;
|
||||
//dy *= 1.2;
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
#endif
|
237
rosapps/games/solitaire/cardlib/cardstack.cpp
Normal file
237
rosapps/games/solitaire/cardlib/cardstack.cpp
Normal file
|
@ -0,0 +1,237 @@
|
|||
//
|
||||
// CardLib - CardStack class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cardstack.h"
|
||||
|
||||
Card &CardStack::operator[] (size_t index)
|
||||
{
|
||||
if(index >= (size_t)nNumCards) index = nNumCards - 1;
|
||||
return cardlist[nNumCards - index - 1];
|
||||
}
|
||||
|
||||
const Card &CardStack::operator[] (size_t index) const
|
||||
{
|
||||
if(index >= (size_t)nNumCards) index = nNumCards - 1;
|
||||
return cardlist[nNumCards - index - 1];
|
||||
}
|
||||
|
||||
// Subscripting operator for a constant sequence
|
||||
//
|
||||
/*Card CardStack::operator[] (size_t index) const
|
||||
{
|
||||
return cardlist[index];
|
||||
}*/
|
||||
|
||||
//
|
||||
// Subscripting operator for a non-const sequence
|
||||
//
|
||||
/*CardStack::ref CardStack::operator[] (size_t index)
|
||||
{
|
||||
return ref(this, index);
|
||||
}*/
|
||||
|
||||
void CardStack::Clear()
|
||||
{
|
||||
nNumCards = 0;
|
||||
}
|
||||
|
||||
void CardStack::NewDeck()
|
||||
{
|
||||
nNumCards = 52;
|
||||
|
||||
for(int i = 0; i < 52; i++)
|
||||
cardlist[i].nValue = i;
|
||||
}
|
||||
|
||||
void CardStack::Shuffle()
|
||||
{
|
||||
int src, dest;
|
||||
Card temp;
|
||||
|
||||
//shuffle 8 times..
|
||||
for(int i = 0; i < 8; i++)
|
||||
for(dest = nNumCards - 1; dest > 0; dest--)
|
||||
{
|
||||
//want to do this:
|
||||
// bad: src = rand() % (dest + 1)
|
||||
// good: src = rand() / (RAND_MAX / (dest+1) + 1)
|
||||
|
||||
//positions from 0 to dest
|
||||
src = rand() / (RAND_MAX / (dest+1) + 1);
|
||||
|
||||
//swap the cards
|
||||
temp = cardlist[src];
|
||||
cardlist[src] = cardlist[dest];
|
||||
cardlist[dest] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void CardStack::Reverse()
|
||||
{
|
||||
for(int i = 0; i < nNumCards / 2; i++)
|
||||
{
|
||||
Card temp = cardlist[i];
|
||||
cardlist[i] = cardlist[nNumCards - i - 1];
|
||||
cardlist[nNumCards - i - 1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void CardStack::Push(const Card card)
|
||||
{
|
||||
if(nNumCards < MAX_CARDSTACK_SIZE)
|
||||
cardlist[nNumCards++] = card;
|
||||
}
|
||||
|
||||
void CardStack::Push(const CardStack &cardstack)
|
||||
{
|
||||
if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE)
|
||||
{
|
||||
int num = cardstack.NumCards();
|
||||
|
||||
for(int i = 0; i < num; i++)
|
||||
cardlist[nNumCards++] = cardstack.cardlist[i];
|
||||
}
|
||||
}
|
||||
|
||||
CardStack& CardStack::operator += (Card card)
|
||||
{
|
||||
Push(card);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CardStack& CardStack::operator += (CardStack &cs)
|
||||
{
|
||||
Push(cs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CardStack CardStack::operator + (Card card)
|
||||
{
|
||||
CardStack poo = *this;
|
||||
poo.Push(card);
|
||||
return poo;
|
||||
}
|
||||
|
||||
CardStack CardStack::operator + (CardStack &cs)
|
||||
{
|
||||
CardStack poo = *this;
|
||||
poo.Push(cs);
|
||||
return poo;
|
||||
}
|
||||
|
||||
|
||||
Card CardStack::Pop()
|
||||
{
|
||||
if(nNumCards > 0)
|
||||
return cardlist[--nNumCards];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
CardStack CardStack::Pop(int items)
|
||||
{
|
||||
if(items <= nNumCards && nNumCards > 0)
|
||||
{
|
||||
CardStack cs(*this, nNumCards - items);
|
||||
|
||||
nNumCards -= items;
|
||||
|
||||
return cs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CardStack();
|
||||
}
|
||||
}
|
||||
|
||||
Card CardStack::Top()
|
||||
{
|
||||
if(nNumCards > 0)
|
||||
return cardlist[nNumCards - 1];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
CardStack CardStack::Top(int items)
|
||||
{
|
||||
if(items <= nNumCards && nNumCards > 0)
|
||||
{
|
||||
return CardStack (*this, nNumCards - items);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CardStack();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Card CardStack::RemoveCard(size_t index)
|
||||
{
|
||||
if(nNumCards == 0 || index >= (size_t)nNumCards)
|
||||
return 0;
|
||||
|
||||
//put index into reverse range..
|
||||
index = nNumCards - index - 1;
|
||||
|
||||
Card temp = cardlist[index];
|
||||
|
||||
nNumCards--;
|
||||
|
||||
for(size_t i = index; i < (size_t)nNumCards; i++)
|
||||
{
|
||||
cardlist[i] = cardlist[i+1];
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void CardStack::InsertCard(size_t index, Card card)
|
||||
{
|
||||
if(nNumCards == MAX_CARDSTACK_SIZE)
|
||||
return;
|
||||
|
||||
if(index > (size_t)nNumCards)
|
||||
return;
|
||||
|
||||
if((size_t)nNumCards == index)
|
||||
{
|
||||
cardlist[nNumCards] = card;
|
||||
nNumCards++;
|
||||
return;
|
||||
}
|
||||
|
||||
//put index into reverse range..
|
||||
index = nNumCards - index - 1;
|
||||
|
||||
nNumCards++;
|
||||
|
||||
//make room for the card
|
||||
for(size_t i = nNumCards; i > index; i--)
|
||||
{
|
||||
cardlist[i] = cardlist[i - 1];
|
||||
}
|
||||
|
||||
cardlist[index] = card;
|
||||
}
|
||||
|
||||
|
||||
void CardStack::Print()
|
||||
{
|
||||
// for(int i = 0; i < nNumCards; i++)
|
||||
// cout << cardlist[i].HiVal() << " ";
|
||||
}
|
||||
|
||||
CardStack::CardStack(CardStack ©this, size_t fromindex)
|
||||
{
|
||||
nNumCards = copythis.nNumCards - fromindex;
|
||||
|
||||
for(int i = 0; i < nNumCards; i++)
|
||||
cardlist[i] = copythis.cardlist[fromindex + i];
|
||||
}
|
||||
|
53
rosapps/games/solitaire/cardlib/cardstack.h
Normal file
53
rosapps/games/solitaire/cardlib/cardstack.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef CARDSTACK_INCLUDED
|
||||
#define CARDSTACK_INCLUDED
|
||||
|
||||
#include "card.h"
|
||||
|
||||
#define MAX_CARDSTACK_SIZE 128
|
||||
|
||||
class CardStack
|
||||
{
|
||||
friend class CardRegion;
|
||||
|
||||
public:
|
||||
CardStack() : nNumCards(0) { }
|
||||
|
||||
void NewDeck();
|
||||
int NumCards() const { return nNumCards; }
|
||||
void Shuffle();
|
||||
void Clear();
|
||||
void Reverse();
|
||||
|
||||
void Push(const Card card);
|
||||
void Push(const CardStack &cardstack);
|
||||
|
||||
Card Pop();
|
||||
CardStack Pop(int items);
|
||||
|
||||
Card Top();
|
||||
CardStack Top(int items);
|
||||
|
||||
void Print();
|
||||
|
||||
Card RemoveCard(size_t index);
|
||||
void InsertCard(size_t index, Card card);
|
||||
|
||||
//subscript capability!!
|
||||
Card & operator[] (size_t index);
|
||||
const Card & operator[] (size_t index) const;
|
||||
|
||||
CardStack &operator += (Card card);
|
||||
CardStack &operator += (CardStack &cs);
|
||||
|
||||
CardStack operator + (Card card);
|
||||
CardStack operator + (CardStack &cs);
|
||||
|
||||
private:
|
||||
|
||||
CardStack(CardStack ©this, size_t fromindex);
|
||||
|
||||
Card cardlist[MAX_CARDSTACK_SIZE];
|
||||
int nNumCards;
|
||||
};
|
||||
|
||||
#endif
|
812
rosapps/games/solitaire/cardlib/cardwindow.cpp
Normal file
812
rosapps/games/solitaire/cardlib/cardwindow.cpp
Normal file
|
@ -0,0 +1,812 @@
|
|||
//
|
||||
// CardLib - CardWindow class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "cardlib.h"
|
||||
#include "cardbutton.h"
|
||||
#include "cardregion.h"
|
||||
#include "cardwindow.h"
|
||||
#include "cardcolor.h"
|
||||
|
||||
extern HPALETTE __holdplacepal;
|
||||
|
||||
HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette)
|
||||
{
|
||||
HPALETTE hOld;
|
||||
|
||||
hOld = SelectPalette(hdc, hPalette, FALSE);
|
||||
RealizePalette(hdc);
|
||||
|
||||
return hOld;
|
||||
}
|
||||
|
||||
void RestorePalette(HDC hdc, HPALETTE hOldPal)
|
||||
{
|
||||
SelectPalette(hdc, hOldPal, TRUE);
|
||||
}
|
||||
|
||||
HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours);
|
||||
void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
|
||||
HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height);
|
||||
void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2);
|
||||
|
||||
void LoadCardBitmaps();
|
||||
void FreeCardBitmaps();
|
||||
|
||||
static TCHAR szCardName[] = _T("CardWnd32");
|
||||
static bool fRegistered = false;
|
||||
static LONG uCardBitmapRef = 0;
|
||||
|
||||
|
||||
void RegisterCardWindow()
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
|
||||
//Window class for the main application parent window
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
|
||||
wc.lpfnWndProc = CardWindow::CardWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = sizeof(CardWindow *);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||
wc.hbrBackground = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = szCardName;
|
||||
wc.hIconSm = 0;
|
||||
|
||||
RegisterClassEx(&wc);
|
||||
}
|
||||
|
||||
CardWindow::CardWindow() : m_hWnd(0)
|
||||
{
|
||||
HDC hdc = GetDC(0);
|
||||
|
||||
nNumButtons = 0;
|
||||
nNumCardRegions = 0;
|
||||
nNumDropZones = 0;
|
||||
nBackCardIdx = 53;
|
||||
|
||||
ResizeWndCallback = 0;
|
||||
hbmBackImage = 0;
|
||||
hdcBackImage = 0;
|
||||
|
||||
srand((unsigned)GetTickCount());
|
||||
|
||||
//All colours (buttons, highlights, decks)
|
||||
//are calculated off this single base colour
|
||||
crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100);
|
||||
|
||||
// If uCardBitmapRef was previously zero, then
|
||||
// load the card bitmaps
|
||||
if(1 == InterlockedIncrement(&uCardBitmapRef))
|
||||
{
|
||||
LoadCardBitmaps();
|
||||
|
||||
__hPalette = CreateCardPalette();
|
||||
|
||||
__hdcPlaceHolder = CreateCompatibleDC(hdc);
|
||||
|
||||
__holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);
|
||||
|
||||
__hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
|
||||
|
||||
}
|
||||
|
||||
ReleaseDC(0, hdc);
|
||||
|
||||
//register the window class if necessary
|
||||
if(!fRegistered)
|
||||
{
|
||||
fRegistered = true;
|
||||
RegisterCardWindow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height)
|
||||
{
|
||||
if(m_hWnd)
|
||||
return FALSE;
|
||||
|
||||
//Create the window associated with this object
|
||||
m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0,
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
0,0,100,100,
|
||||
hwndParent, 0, GetModuleHandle(0), this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CardWindow::Destroy()
|
||||
{
|
||||
DestroyWindow(m_hWnd);
|
||||
m_hWnd = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CardWindow::~CardWindow()
|
||||
{
|
||||
if(m_hWnd)
|
||||
DestroyWindow(m_hWnd);
|
||||
|
||||
DeleteAll();
|
||||
|
||||
if(0 == InterlockedDecrement(&uCardBitmapRef))
|
||||
{
|
||||
FreeCardBitmaps();
|
||||
|
||||
DeleteObject(__hbmPlaceHolder);
|
||||
DeleteDC (__hdcPlaceHolder);
|
||||
|
||||
RestorePalette(__hdcPlaceHolder, __holdplacepal);
|
||||
|
||||
if(__hPalette)
|
||||
DeleteObject(__hPalette);
|
||||
}
|
||||
}
|
||||
|
||||
bool CardWindow::DeleteAll()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
delete Regions[i];
|
||||
}
|
||||
|
||||
for(i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
delete Buttons[i];
|
||||
}
|
||||
|
||||
for(i = 0; i < nNumDropZones; i++)
|
||||
{
|
||||
delete dropzone[i];
|
||||
}
|
||||
|
||||
nNumCardRegions = nNumButtons = nNumDropZones = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CardWindow::SetBackColor(COLORREF cr)
|
||||
{
|
||||
crBackgnd = cr;
|
||||
int i;
|
||||
|
||||
//
|
||||
// Create the exact palette we need to render the buttons/stacks
|
||||
//
|
||||
RestorePalette(__hdcPlaceHolder, __holdplacepal);
|
||||
|
||||
if(__hPalette)
|
||||
DeleteObject(__hPalette);
|
||||
|
||||
__hPalette = CreateCardPalette();
|
||||
|
||||
//
|
||||
// re-create the place-holder!
|
||||
HDC hdc = GetDC(m_hWnd);
|
||||
|
||||
DeleteObject(__hbmPlaceHolder);
|
||||
|
||||
__holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);
|
||||
|
||||
__hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
|
||||
//SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);
|
||||
|
||||
//reset all buttons to same colour
|
||||
for(i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
if(Buttons[i]->GetStyle() & CB_PUSHBUTTON)
|
||||
{
|
||||
Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Buttons[i]->SetBackColor(crBackgnd);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
Regions[i]->SetBackColor(crBackgnd);
|
||||
}
|
||||
|
||||
|
||||
ReleaseDC(m_hWnd, hdc);
|
||||
}
|
||||
|
||||
COLORREF CardWindow::GetBackColor()
|
||||
{
|
||||
return crBackgnd;
|
||||
}
|
||||
|
||||
CardButton* CardWindow::CardButtonFromPoint(int x, int y)
|
||||
{
|
||||
CardButton *bptr = 0;
|
||||
|
||||
POINT pt;
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
|
||||
//Search BACKWARDS...to reflect the implicit Z-order that
|
||||
//the button creation provided
|
||||
for(int i = nNumButtons - 1; i >= 0; i--)
|
||||
{
|
||||
bptr = Buttons[i];
|
||||
if(PtInRect(&bptr->rect, pt) && bptr->fVisible)
|
||||
return bptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CardRegion* CardWindow::CardRegionFromPoint(int x, int y)
|
||||
{
|
||||
POINT pt;
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
|
||||
//Search BACKWARDS...to reflect the implicit Z-order that
|
||||
//the stack creation provided
|
||||
for(int i = nNumCardRegions - 1; i >= 0; i--)
|
||||
{
|
||||
if(Regions[i]->IsPointInStack(x, y))
|
||||
return Regions[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Forward all window messages onto the appropriate
|
||||
// class instance
|
||||
//
|
||||
LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0);
|
||||
return cw->WndProc(hwnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void CardWindow::Paint(HDC hdc)
|
||||
{
|
||||
int i;
|
||||
RECT rect;
|
||||
int xpos = 10;
|
||||
HPALETTE hOldPal;
|
||||
|
||||
hOldPal = UseNicePalette(hdc, __hPalette);
|
||||
|
||||
//
|
||||
// Clip the card stacks so that they won't
|
||||
// get painted over
|
||||
//
|
||||
for(i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
Regions[i]->Clip(hdc);
|
||||
}
|
||||
|
||||
//
|
||||
// Clip the buttons
|
||||
//
|
||||
for(i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
Buttons[i]->Clip(hdc);
|
||||
}
|
||||
|
||||
|
||||
// Now paint the whole screen with background colour,
|
||||
//
|
||||
GetClientRect(m_hWnd, &rect);
|
||||
|
||||
//PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
|
||||
PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0);
|
||||
SelectClipRgn(hdc, NULL);
|
||||
|
||||
// Don't let cards draw over buttons, so clip buttons again
|
||||
//
|
||||
for(i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
Buttons[i]->Clip(hdc);
|
||||
}
|
||||
|
||||
// Paint each card stack in turn
|
||||
//
|
||||
for(i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
Regions[i]->Render(hdc);
|
||||
}
|
||||
|
||||
// Paint each button now
|
||||
//
|
||||
SelectClipRgn(hdc, NULL);
|
||||
|
||||
for(i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
Buttons[i]->Redraw();
|
||||
}
|
||||
|
||||
RestorePalette(hdc, hOldPal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
//
|
||||
SetWindowLong(hwnd, 0, (LONG)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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
CardRegion* CardWindow::CardRegionFromId(int id)
|
||||
{
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
if(Regions[i]->id == id)
|
||||
return Regions[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CardButton* CardWindow::CardButtonFromId(int id)
|
||||
{
|
||||
for(int i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
if(Buttons[i]->id == id)
|
||||
return Buttons[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CardWindow::Redraw()
|
||||
{
|
||||
InvalidateRect(m_hWnd, 0, 0);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
bool CardWindow::DeleteButton(CardButton *pButton)
|
||||
{
|
||||
for(int i = 0; i < nNumButtons; i++)
|
||||
{
|
||||
if(Buttons[i] == pButton)
|
||||
{
|
||||
CardButton *cb = Buttons[i];
|
||||
|
||||
//shift any after this one backwards
|
||||
for(int j = i; j < nNumButtons - 1; j++)
|
||||
{
|
||||
Buttons[j] = Buttons[j + 1];
|
||||
}
|
||||
|
||||
delete cb;
|
||||
nNumButtons--;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardWindow::DeleteRegion(CardRegion *pRegion)
|
||||
{
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
if(Regions[i] == pRegion)
|
||||
{
|
||||
CardRegion *cr = Regions[i];
|
||||
|
||||
//shift any after this one backwards
|
||||
for(int j = i; j < nNumCardRegions - 1; j++)
|
||||
{
|
||||
Regions[j] = Regions[j + 1];
|
||||
}
|
||||
|
||||
delete cr;
|
||||
nNumCardRegions--;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CardWindow::EmptyStacks(void)
|
||||
{
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
Regions[i]->Clear();
|
||||
Regions[i]->Update();
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX)
|
||||
{
|
||||
int numvisiblestacks = 0;
|
||||
int curx = nStartX;
|
||||
int startindex = -1;
|
||||
int i;
|
||||
|
||||
//find the stack which starts with our ID
|
||||
for(i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
if(Regions[i]->Id() == nIdFrom)
|
||||
{
|
||||
startindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if didn't find, return
|
||||
if(i == nNumCardRegions) return false;
|
||||
|
||||
//count the stacks that are visible
|
||||
for(i = startindex; i < startindex + nNumStacks; i++)
|
||||
{
|
||||
if(Regions[i]->IsVisible())
|
||||
numvisiblestacks++;
|
||||
}
|
||||
|
||||
if(xJustify == CS_XJUST_CENTER)
|
||||
{
|
||||
//startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;
|
||||
int viswidth;
|
||||
viswidth = numvisiblestacks * __cardwidth;
|
||||
viswidth += xSpacing * (numvisiblestacks - 1);
|
||||
curx = -(viswidth - __cardwidth) / 2;
|
||||
|
||||
for(i = startindex; i < startindex + nNumStacks; i++)
|
||||
{
|
||||
if(Regions[i]->IsVisible())
|
||||
{
|
||||
Regions[i]->xadjust = curx;
|
||||
Regions[i]->xjustify = CS_XJUST_CENTER;
|
||||
curx += Regions[i]->width + xSpacing;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(xJustify == CS_XJUST_RIGHT)
|
||||
{
|
||||
nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing);
|
||||
}
|
||||
|
||||
if(xJustify == CS_XJUST_NONE)
|
||||
{
|
||||
for(i = startindex; i < startindex + nNumStacks; i++)
|
||||
{
|
||||
if(Regions[i]->IsVisible())
|
||||
{
|
||||
Regions[i]->xpos = curx;
|
||||
curx += Regions[i]->width + xSpacing;
|
||||
Regions[i]->UpdateSize();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CardWindow::Update()
|
||||
{
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
{
|
||||
Regions[i]->AdjustPosition(nWidth, nHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CardWindow::SetResizeProc(pResizeWndProc proc)
|
||||
{
|
||||
ResizeWndCallback = proc;
|
||||
}
|
||||
|
||||
|
||||
HPALETTE CardWindow::CreateCardPalette()
|
||||
{
|
||||
COLORREF cols[10];
|
||||
int nNumCols;
|
||||
|
||||
|
||||
//include button text colours
|
||||
cols[0] = RGB(0, 0, 0);
|
||||
cols[1] = RGB(255, 255, 255);
|
||||
|
||||
//include the base background colour
|
||||
cols[1] = crBackgnd;
|
||||
|
||||
//include the standard button colours...
|
||||
cols[3] = CardButton::GetHighlight(crBackgnd);
|
||||
cols[4] = CardButton::GetShadow(crBackgnd);
|
||||
cols[5] = CardButton::GetFace(crBackgnd);
|
||||
|
||||
//include the sunken image bitmap colours...
|
||||
GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]);
|
||||
|
||||
nNumCols = 10;
|
||||
|
||||
return MakePaletteFromCols(cols, nNumCols);
|
||||
}
|
||||
|
||||
void CardWindow::SetBackCardIdx(UINT uBackIdx)
|
||||
{
|
||||
if(uBackIdx >= 52 && uBackIdx <= 68)
|
||||
nBackCardIdx = uBackIdx;
|
||||
|
||||
for(int i = 0; i < nNumCardRegions; i++)
|
||||
Regions[i]->SetBackCardIdx(uBackIdx);
|
||||
|
||||
}
|
||||
|
||||
void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy)
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
//if just a solid background colour
|
||||
if(hbmBackImage == 0)
|
||||
{
|
||||
SetRect(&rect, dx, dy, dx+width, dy+height);
|
||||
|
||||
/*if(GetVersion() < 0x80000000)
|
||||
{
|
||||
PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
|
||||
}
|
||||
else*/
|
||||
{
|
||||
HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd));
|
||||
FillRect(hdc, &rect, hbr);
|
||||
DeleteObject(hbr);
|
||||
}
|
||||
}
|
||||
//otherwise, paint using the bitmap
|
||||
else
|
||||
{
|
||||
// Draw whatever part of background we can
|
||||
BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY);
|
||||
|
||||
// Now we need to paint any area outside the bitmap,
|
||||
// just in case the bitmap is too small to fill whole window
|
||||
if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight)
|
||||
{
|
||||
// Find out size of bitmap
|
||||
BITMAP bm;
|
||||
GetObject(hbmBackImage, sizeof(bm), &bm);
|
||||
|
||||
HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height);
|
||||
HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
|
||||
HRGN hr3 = CreateRectRgn(0,0, 1, 1);
|
||||
HRGN hr4 = CreateRectRgn(0,0, 1, 1);
|
||||
|
||||
CombineRgn(hr3, hr1, hr2, RGN_DIFF);
|
||||
|
||||
GetClipRgn(hdc, hr4);
|
||||
|
||||
CombineRgn(hr3, hr4, hr3, RGN_AND);
|
||||
SelectClipRgn(hdc, hr3);
|
||||
|
||||
// Fill remaining space not filled with bitmap
|
||||
HBRUSH hbr = CreateSolidBrush(crBackgnd);
|
||||
FillRgn(hdc, hr3, hbr);
|
||||
DeleteObject(hbr);
|
||||
|
||||
// Clean up
|
||||
SelectClipRgn(hdc, hr4);
|
||||
|
||||
DeleteObject(hr1);
|
||||
DeleteObject(hr2);
|
||||
DeleteObject(hr3);
|
||||
DeleteObject(hr4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardWindow::SetBackImage(HBITMAP hBitmap)
|
||||
{
|
||||
//delete current image?? NO!
|
||||
if(hdcBackImage == 0)
|
||||
{
|
||||
hdcBackImage = CreateCompatibleDC(0);
|
||||
}
|
||||
|
||||
hbmBackImage = hBitmap;
|
||||
|
||||
if(hBitmap)
|
||||
SelectObject(hdcBackImage, hBitmap);
|
||||
}
|
119
rosapps/games/solitaire/cardlib/cardwindow.h
Normal file
119
rosapps/games/solitaire/cardlib/cardwindow.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
#ifndef CARDBOARD_INCLUDED
|
||||
#define CARDBOARD_INCLUDED
|
||||
|
||||
#define MAXBUTTONS 32
|
||||
#define MAXCARDSTACKS 32
|
||||
#define MAXDROPZONES 8
|
||||
|
||||
#include "dropzone.h"
|
||||
#include "cardlib.h"
|
||||
|
||||
class CardRegion;
|
||||
class CardButton;
|
||||
|
||||
LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
class CardWindow
|
||||
{
|
||||
friend class CardRegion;
|
||||
friend class CardButton;
|
||||
|
||||
friend void RegisterCardWindow();
|
||||
|
||||
public:
|
||||
|
||||
CardWindow();
|
||||
~CardWindow();
|
||||
|
||||
//
|
||||
// Basic windowing support
|
||||
//
|
||||
BOOL Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height);
|
||||
BOOL Destroy();
|
||||
|
||||
operator HWND() { return m_hWnd; }
|
||||
|
||||
CardButton *CreateButton (int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height);
|
||||
CardRegion *CreateRegion (int id, bool fVisible, int x, int y, int xoffset, int yoffset);
|
||||
|
||||
CardButton *CardButtonFromId(int id);
|
||||
CardRegion *CardRegionFromId(int id);
|
||||
|
||||
bool DeleteButton(CardButton *pButton);
|
||||
bool DeleteRegion(CardRegion *pRegion);
|
||||
bool DeleteAll();
|
||||
|
||||
void SetBackColor(COLORREF cr);
|
||||
COLORREF GetBackColor();
|
||||
void SetBackCardIdx(UINT uBackIdx);
|
||||
void SetBackImage(HBITMAP hBitmap);
|
||||
|
||||
void EmptyStacks(void);
|
||||
void Redraw(void);
|
||||
void Update(void);
|
||||
|
||||
bool DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX);
|
||||
void SetResizeProc(pResizeWndProc proc);
|
||||
int GetWidth() { return nWidth; }
|
||||
int GetHeight() { return nHeight; }
|
||||
|
||||
//
|
||||
// Dropzone support
|
||||
//
|
||||
bool RegisterDropZone(int id, RECT *rect, pDropZoneProc proc);
|
||||
bool DeleteDropZone(int id);
|
||||
|
||||
private:
|
||||
|
||||
int GetNumDropZones() { return nNumDropZones; }
|
||||
DropZone* GetDropZoneFromRect(RECT *rect);
|
||||
|
||||
//
|
||||
// Window procedure - don't call
|
||||
//
|
||||
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
//
|
||||
// Private functions
|
||||
//
|
||||
void Paint(HDC hdc);
|
||||
void PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy);
|
||||
|
||||
HPALETTE CreateCardPalette();
|
||||
|
||||
CardButton *CardButtonFromPoint(int x, int y);
|
||||
CardRegion *CardRegionFromPoint(int x, int y);
|
||||
CardRegion *GetBestStack(int x, int y, int w, int h);
|
||||
|
||||
//
|
||||
// Private members
|
||||
//
|
||||
|
||||
HWND m_hWnd; //window handle!
|
||||
int nWidth, nHeight;
|
||||
|
||||
UINT nBackCardIdx; //all stacks share this card index by default
|
||||
|
||||
HBITMAP hbmBackImage;
|
||||
HDC hdcBackImage;
|
||||
|
||||
|
||||
CardButton * Buttons[MAXBUTTONS];
|
||||
int nNumButtons;
|
||||
|
||||
CardRegion * Regions[MAXCARDSTACKS];
|
||||
int nNumCardRegions;
|
||||
|
||||
DropZone * dropzone[MAXDROPZONES];
|
||||
int nNumDropZones;
|
||||
|
||||
COLORREF crBackgnd;
|
||||
|
||||
pResizeWndProc ResizeWndCallback;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
69
rosapps/games/solitaire/cardlib/dropzone.cpp
Normal file
69
rosapps/games/solitaire/cardlib/dropzone.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// CardLib - DropZone class
|
||||
//
|
||||
// Freeware
|
||||
// Copyright J Brown 2001
|
||||
//
|
||||
#include <windows.h>
|
||||
|
||||
#include "cardlib.h"
|
||||
#include "cardwindow.h"
|
||||
#include "dropzone.h"
|
||||
|
||||
bool CardWindow::RegisterDropZone(int id, RECT *rect, pDropZoneProc proc)
|
||||
{
|
||||
if(nNumDropZones == MAXDROPZONES)
|
||||
return false;
|
||||
|
||||
DropZone *dz = new DropZone(id, rect, proc);
|
||||
|
||||
dropzone[nNumDropZones++] = dz;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DropZone *CardWindow::GetDropZoneFromRect(RECT *rect)
|
||||
{
|
||||
for(int i = 0; i < nNumDropZones; i++)
|
||||
{
|
||||
RECT inter;
|
||||
RECT zone;
|
||||
|
||||
//if any part of the drag rectangle falls within a drop zone,
|
||||
//let that take priority over any other card stack.
|
||||
dropzone[i]->GetZone(&zone);
|
||||
|
||||
if(IntersectRect(&inter, rect, &zone))
|
||||
{
|
||||
//see if the callback wants us to drop a card on
|
||||
//a particular stack
|
||||
return dropzone[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CardWindow::DeleteDropZone(int id)
|
||||
{
|
||||
for(int i = 0; i < nNumDropZones; i++)
|
||||
{
|
||||
if(dropzone[i]->id == id)
|
||||
{
|
||||
DropZone *dz = dropzone[i];
|
||||
|
||||
//shift any after this one backwards
|
||||
for(int j = i; j < nNumDropZones - 1; j++)
|
||||
{
|
||||
dropzone[j] = dropzone[j + 1];
|
||||
}
|
||||
|
||||
delete dz;
|
||||
nNumDropZones--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
39
rosapps/games/solitaire/cardlib/dropzone.h
Normal file
39
rosapps/games/solitaire/cardlib/dropzone.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef DROPZONE_INCLUDED
|
||||
#define DROPZONE_INCLUDED
|
||||
|
||||
//
|
||||
// define a drop-zone, which can be used to over-ride
|
||||
// drop-behaviour for any card stacks which fall under it
|
||||
//
|
||||
|
||||
class CardStack;
|
||||
|
||||
class DropZone
|
||||
{
|
||||
friend class CardWindow;
|
||||
|
||||
DropZone(int Id, RECT *rect, pDropZoneProc proc) :
|
||||
id(Id), DropZoneCallback(proc) { CopyRect(&zone, rect); }
|
||||
|
||||
public:
|
||||
|
||||
void SetZone(RECT *rect) { CopyRect(&zone, rect); }
|
||||
void GetZone(RECT *rect) { CopyRect(rect, &zone); }
|
||||
void SetCallback(pDropZoneProc callback) { DropZoneCallback = callback; }
|
||||
|
||||
int DropCards(CardStack &cardstack)
|
||||
{
|
||||
if(DropZoneCallback)
|
||||
return DropZoneCallback(id, cardstack);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int id;
|
||||
RECT zone;
|
||||
pDropZoneProc DropZoneCallback;
|
||||
};
|
||||
|
||||
#endif
|
15
rosapps/games/solitaire/cardlib/globals.h
Normal file
15
rosapps/games/solitaire/cardlib/globals.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef GLOBALS_INCLUDED
|
||||
#define GLOBALS_INCLUDED
|
||||
|
||||
extern int __cardwidth;
|
||||
extern int __cardheight;
|
||||
|
||||
extern HDC __hdcCardBitmaps;
|
||||
extern HBITMAP __hbmCardBitmaps;
|
||||
|
||||
extern HDC __hdcPlaceHolder;
|
||||
extern HBITMAP __hbmPlaceHolder;
|
||||
|
||||
extern HPALETTE __hPalette;
|
||||
|
||||
#endif
|
BIN
rosapps/games/solitaire/icon1.ico
Normal file
BIN
rosapps/games/solitaire/icon1.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
42
rosapps/games/solitaire/makefile
Normal file
42
rosapps/games/solitaire/makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
PATH_TO_TOP = ../../../reactos
|
||||
|
||||
TARGET_TYPE = program
|
||||
|
||||
TARGET_APPTYPE = windows
|
||||
|
||||
TARGET_INSTALLDIR = system32
|
||||
|
||||
TARGET_NAME = sol
|
||||
|
||||
TARGET_SDKLIBS = kernel32.a user32.a gdi32.a cards.a comctl32.a
|
||||
|
||||
TARGET_GCCLIBS = stdc++
|
||||
|
||||
TARGET_OBJECTS = $(SOL_OBJECTS) $(CARDLIB_OBJECTS)
|
||||
|
||||
SOL_OBJECTS = \
|
||||
solcreate.o \
|
||||
solgame.o \
|
||||
solitaire.o
|
||||
|
||||
CARDLIB_OBJECTS = \
|
||||
cardlib/cardbitmaps.o \
|
||||
cardlib/cardbutton.o \
|
||||
cardlib/cardcolor.o \
|
||||
cardlib/cardcount.o \
|
||||
cardlib/cardlib.o \
|
||||
cardlib/cardregion.o \
|
||||
cardlib/cardrgndraw.o \
|
||||
cardlib/cardrgnmouse.o \
|
||||
cardlib/cardstack.o \
|
||||
cardlib/cardwindow.o \
|
||||
cardlib/dropzone.o
|
||||
|
||||
TARGET_CPPFLAGS = -Icardlib -Wall -D__USE_W32API -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -D__REACTOS__
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# EOF
|
25
rosapps/games/solitaire/resource.h
Normal file
25
rosapps/games/solitaire/resource.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by Solitaire.rc
|
||||
//
|
||||
#define IDD_DIALOG1 101
|
||||
#define IDR_MENU1 102
|
||||
#define IDR_ACCELERATOR1 103
|
||||
#define IDI_ICON1 104
|
||||
#define IDM_GAME_NEW 40001
|
||||
#define IDM_GAME_DECK 40002
|
||||
#define IDM_GAME_OPTIONS 40003
|
||||
#define IDM_GAME_EXIT 40004
|
||||
#define IDM_HELP_CONTENTS 40005
|
||||
#define IDM_HELP_ABOUT 40006
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 105
|
||||
#define _APS_NEXT_COMMAND_VALUE 40007
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
144
rosapps/games/solitaire/sol.rc
Normal file
144
rosapps/games/solitaire/sol.rc
Normal file
|
@ -0,0 +1,144 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
/* winemaker: #include "afxres.h" */
|
||||
/* winemaker:warning: 'afxres.h' is an MFC specific header. Replacing it with 'winres.h' */
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.K.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Dialog"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_DIALOG1, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 88
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDR_MENU1 MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "&Game"
|
||||
BEGIN
|
||||
MENUITEM "&Deal\tF2", IDM_GAME_NEW
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "De&ck...", IDM_GAME_DECK
|
||||
MENUITEM "&Options...", IDM_GAME_OPTIONS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Exit", IDM_GAME_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&Contents\tF1", IDM_HELP_CONTENTS
|
||||
MENUITEM "&About", IDM_HELP_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accelerator
|
||||
//
|
||||
|
||||
IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
|
||||
BEGIN
|
||||
VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT
|
||||
VK_F2, IDM_GAME_NEW, VIRTKEY, NOINVERT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "icon1.ico"
|
||||
#endif // English (U.K.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
87
rosapps/games/solitaire/solcreate.cpp
Normal file
87
rosapps/games/solitaire/solcreate.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <tchar.h>
|
||||
#include "resource.h"
|
||||
#include "cardlib/cardlib.h"
|
||||
|
||||
#include "solitaire.h"
|
||||
|
||||
const int yBorder = 20;
|
||||
const int xBorder = 20;
|
||||
const int yRowStacks = yBorder + 128;
|
||||
|
||||
CardRegion *pDeck;
|
||||
CardRegion *pPile;
|
||||
CardRegion *pSuitStack[4];
|
||||
CardRegion *pRowStack[NUM_ROW_STACKS];
|
||||
|
||||
extern CardStack activepile;
|
||||
|
||||
HBITMAP hbmBitmap;
|
||||
HDC hdcBitmap;
|
||||
|
||||
void CreateSol()
|
||||
{
|
||||
int i;
|
||||
|
||||
// hbmBitmap = (HBITMAP)LoadImage(0,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
|
||||
// SolWnd.SetBackImage(hbmBitmap);
|
||||
|
||||
activepile.Clear();
|
||||
|
||||
|
||||
pDeck = SolWnd.CreateRegion(DECK_ID, true, xBorder, yBorder, 2, 1);
|
||||
pDeck->SetEmptyImage(CS_EI_SUNK);
|
||||
pDeck->SetThreedCount(6);
|
||||
pDeck->SetDragRule(CS_DRAG_NONE, 0);
|
||||
pDeck->SetDropRule(CS_DROP_NONE, 0);
|
||||
pDeck->SetClickProc(DeckClickProc);
|
||||
pDeck->SetDblClickProc(DeckClickProc);
|
||||
pDeck->SetFaceDirection(CS_FACE_DOWN, 0);
|
||||
|
||||
pPile = SolWnd.CreateRegion(PILE_ID, true, 110, yBorder, CS_DEFXOFF, 1);
|
||||
pPile->SetEmptyImage(CS_EI_NONE);
|
||||
pPile->SetDragRule(CS_DRAG_TOP, 0);
|
||||
pPile->SetDropRule(CS_DROP_NONE, 0);
|
||||
pPile->SetDblClickProc(PileDblClickProc);
|
||||
pPile->SetRemoveCardProc(PileRemoveProc);
|
||||
|
||||
//
|
||||
// Create the suit stacks
|
||||
//
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
pSuitStack[i] = SolWnd.CreateRegion(SUIT_ID+i, true, 0, yBorder, 0, 0);
|
||||
pSuitStack[i]->SetEmptyImage(CS_EI_SUNK);
|
||||
//pSuitStack[i]->SetPlacement(CS_XJUST_RIGHT, 0, -i * (__cardwidth + 4) - xBorder, 0);
|
||||
pSuitStack[i]->SetPlacement(CS_XJUST_CENTER, 0, i * (__cardwidth + 10) , 0);
|
||||
|
||||
pSuitStack[i]->SetDropRule(CS_DROP_CALLBACK, SuitStackDropProc);
|
||||
pSuitStack[i]->SetDragRule(CS_DRAG_TOP);
|
||||
|
||||
pSuitStack[i]->SetAddCardProc(SuitStackAddProc);
|
||||
}
|
||||
|
||||
//
|
||||
// Create the row stacks
|
||||
//
|
||||
for(i = 0; i < NUM_ROW_STACKS; i++)
|
||||
{
|
||||
pRowStack[i] = SolWnd.CreateRegion(ROW_ID+i, true, 0, yRowStacks, 0, 14);
|
||||
pRowStack[i]->SetEmptyImage(CS_EI_SUNK);
|
||||
pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);
|
||||
|
||||
pRowStack[i]->SetPlacement(CS_XJUST_CENTER, 0,
|
||||
(i - NUM_ROW_STACKS/2) * (__cardwidth + 10), 0);
|
||||
|
||||
pRowStack[i]->SetEmptyImage(CS_EI_NONE);
|
||||
|
||||
pRowStack[i]->SetDragRule(CS_DRAG_CALLBACK, RowStackDragProc);
|
||||
pRowStack[i]->SetDropRule(CS_DROP_CALLBACK, RowStackDropProc);
|
||||
pRowStack[i]->SetClickProc(RowStackClickProc);
|
||||
pRowStack[i]->SetDblClickProc(RowStackDblClickProc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
308
rosapps/games/solitaire/solgame.cpp
Normal file
308
rosapps/games/solitaire/solgame.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <tchar.h>
|
||||
#include "resource.h"
|
||||
#include "cardlib/cardlib.h"
|
||||
//#include "../catch22lib/trace.h"
|
||||
#include "solitaire.h"
|
||||
|
||||
CardStack activepile;
|
||||
bool fGameStarted = false;
|
||||
|
||||
void NewGame(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
SolWnd.EmptyStacks();
|
||||
|
||||
//create a new card-stack
|
||||
CardStack deck;
|
||||
deck.NewDeck();
|
||||
deck.Shuffle();
|
||||
activepile.Clear();
|
||||
|
||||
//deal to each row stack..
|
||||
for(i = 0; i < NUM_ROW_STACKS; i++)
|
||||
{
|
||||
CardStack temp;
|
||||
temp.Clear();
|
||||
|
||||
pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i);
|
||||
|
||||
for(j = 0; j <= i; j++)
|
||||
{
|
||||
temp.Push(deck.Pop());
|
||||
}
|
||||
|
||||
pRowStack[i]->SetCardStack(temp);
|
||||
}
|
||||
|
||||
//put the other cards onto the deck
|
||||
pDeck->SetCardStack(deck);
|
||||
pDeck->Update();
|
||||
|
||||
SolWnd.Redraw();
|
||||
|
||||
fGameStarted = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Now follow the stack callback functions. This is where we
|
||||
// provide the game functionality and rules
|
||||
//
|
||||
|
||||
//
|
||||
// Can only drag face-up cards
|
||||
//
|
||||
bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards)
|
||||
{
|
||||
int numfacedown;
|
||||
int numcards;
|
||||
|
||||
stackobj.GetFaceDirection(&numfacedown);
|
||||
|
||||
numcards = stackobj.NumCards();
|
||||
|
||||
if(iNumDragCards <= numcards-numfacedown)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Row a row-stack, we can only drop cards
|
||||
// that are lower / different colour
|
||||
//
|
||||
bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
|
||||
{
|
||||
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)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CardStack &mystack = stackobj.GetCardStack();
|
||||
|
||||
//can only drop if card is 1 less
|
||||
if(mystack[0].LoVal() != dragcard.LoVal() + 1)
|
||||
return false;
|
||||
|
||||
//can only drop if card is different colour
|
||||
if( mystack[0].IsBlack() && !dragcard.IsRed() ||
|
||||
!mystack[0].IsBlack() && dragcard.IsRed() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
int topval;
|
||||
|
||||
const CardStack &cardstack = stackobj.GetCardStack();
|
||||
|
||||
if(cardstack.NumCards() > 0)
|
||||
{
|
||||
if(card.Suit() != cardstack[0].Suit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
topval = cardstack[0].LoVal();
|
||||
}
|
||||
else
|
||||
{
|
||||
topval = 0;
|
||||
}
|
||||
|
||||
//make sure 1 higher
|
||||
if(card.LoVal() != (topval + 1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Can only drop a card onto suit stack if it is same suit, and 1 higher
|
||||
//
|
||||
bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards)
|
||||
{
|
||||
int topval = 0;
|
||||
|
||||
//only drop 1 card at a time
|
||||
if(dragcards.NumCards() != 1)
|
||||
return false;
|
||||
|
||||
return CanDrop(stackobj, dragcards[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Find the suit-stack that can accept the specified card
|
||||
//
|
||||
CardRegion *FindSuitStackFromCard(Card card)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(CanDrop(*pSuitStack[i], card))
|
||||
return pSuitStack[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// What happens when we add a card to one of the suit stacks?
|
||||
// Well, nothing (it is already added), but we need to
|
||||
// check all four stacks (not just this one) to see if
|
||||
// the game has finished.
|
||||
//
|
||||
void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added)
|
||||
{
|
||||
bool fGameOver = true;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(pSuitStack[i]->NumCards() != 13)
|
||||
{
|
||||
fGameOver = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(fGameOver)
|
||||
{
|
||||
MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
pSuitStack[i]->Flash(11, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
//can only move 1 card at a time
|
||||
if(iNumClicked != 1)
|
||||
return;
|
||||
|
||||
//find a suit-stack to move the card to...
|
||||
const CardStack &cardstack = stackobj.GetCardStack();
|
||||
CardRegion *pDest = FindSuitStackFromCard(cardstack[0]);
|
||||
|
||||
if(pDest != 0)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Face-up pile double-click
|
||||
//
|
||||
void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked)
|
||||
{
|
||||
RowStackDblClickProc(stackobj, iNumClicked);
|
||||
}
|
||||
|
||||
//
|
||||
// What happens when a card is removed from face-up pile?
|
||||
//
|
||||
void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Double-click on the deck
|
||||
// Move 3 cards to the face-up pile
|
||||
//
|
||||
void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked)
|
||||
{
|
||||
CardStack cardstack = stackobj.GetCardStack();
|
||||
CardStack pile = pPile->GetCardStack();
|
||||
|
||||
fGameStarted = true;
|
||||
|
||||
//reset the face-up pile to represent 3 cards
|
||||
pPile->SetOffsets(CS_DEFXOFF, 1);
|
||||
|
||||
if(cardstack.NumCards() == 0)
|
||||
{
|
||||
pile.Clear();
|
||||
|
||||
activepile.Reverse();
|
||||
cardstack.Push(activepile);
|
||||
activepile.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
int numcards = min(3, cardstack.NumCards());
|
||||
|
||||
//make a "visible" copy of these cards
|
||||
CardStack temp;
|
||||
temp = cardstack.Pop(numcards);
|
||||
temp.Reverse();
|
||||
|
||||
pile.Clear();
|
||||
pile.Push(temp);
|
||||
|
||||
//remove the top 3 from deck
|
||||
activepile.Push(temp);
|
||||
}
|
||||
|
||||
activepile.Print();
|
||||
|
||||
pDeck->SetCardStack(cardstack);
|
||||
pPile->SetCardStack(pile);
|
||||
|
||||
SolWnd.Redraw();
|
||||
}
|
217
rosapps/games/solitaire/solitaire.cpp
Normal file
217
rosapps/games/solitaire/solitaire.cpp
Normal file
|
@ -0,0 +1,217 @@
|
|||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <tchar.h>
|
||||
#include "resource.h"
|
||||
#include "cardlib/cardlib.h"
|
||||
|
||||
#include "solitaire.h"
|
||||
|
||||
TCHAR szHelpPath[MAX_PATH];
|
||||
|
||||
DWORD dwAppStartTime;
|
||||
HWND hwndMain;
|
||||
HWND hwndStatus;
|
||||
HINSTANCE hInstance;
|
||||
|
||||
TCHAR szAppName[] = _T("Solitaire");
|
||||
|
||||
CardWindow SolWnd;
|
||||
|
||||
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void MakePath(TCHAR *szDest, UINT nDestLen, TCHAR *szExt)
|
||||
{
|
||||
TCHAR *ptr;
|
||||
|
||||
ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1;
|
||||
while(*ptr-- != '.');
|
||||
lstrcpy(ptr + 1, szExt);
|
||||
}
|
||||
|
||||
//
|
||||
// Main entry point
|
||||
//
|
||||
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
|
||||
{
|
||||
HWND hwnd;
|
||||
MSG msg;
|
||||
WNDCLASSEX wndclass;
|
||||
INITCOMMONCONTROLSEX ice;
|
||||
HACCEL hAccelTable;
|
||||
|
||||
hInstance = hInst;
|
||||
|
||||
//Window class for the main application parent window
|
||||
wndclass.cbSize = sizeof(wndclass);
|
||||
wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW;
|
||||
wndclass.lpfnWndProc = WndProc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = hInst;
|
||||
wndclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));
|
||||
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||
wndclass.hbrBackground = (HBRUSH)NULL;
|
||||
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
|
||||
wndclass.lpszClassName = szAppName;
|
||||
wndclass.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0);
|
||||
|
||||
RegisterClassEx(&wndclass);
|
||||
|
||||
ice.dwSize = sizeof(ice);
|
||||
ice.dwICC = ICC_BAR_CLASSES;
|
||||
InitCommonControlsEx(&ice);
|
||||
|
||||
srand((unsigned)GetTickCount());//timeGetTime());
|
||||
|
||||
// InitCardLib();
|
||||
|
||||
// LoadSettings();
|
||||
|
||||
//Construct the path to our help file
|
||||
MakePath(szHelpPath, MAX_PATH, _T(".hlp"));
|
||||
|
||||
hwnd = CreateWindow(szAppName, // window class name
|
||||
szAppName, // window caption
|
||||
WS_OVERLAPPEDWINDOW
|
||||
,//|WS_CLIPCHILDREN, // window style
|
||||
CW_USEDEFAULT, // initial x position
|
||||
CW_USEDEFAULT, // initial y position
|
||||
CW_USEDEFAULT, // initial x size
|
||||
CW_USEDEFAULT, // initial y size
|
||||
NULL, // parent window handle
|
||||
NULL, // use window class menu
|
||||
hInst, // program instance handle
|
||||
NULL); // creation parameters
|
||||
|
||||
hwndMain = hwnd;
|
||||
|
||||
ShowWindow(hwnd, iCmdShow);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
|
||||
|
||||
while(GetMessage(&msg, NULL,0,0))
|
||||
{
|
||||
if(!TranslateAccelerator(hwnd, hAccelTable, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
// SaveSettings();
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static int nWidth, nHeight;
|
||||
int nStatusHeight = 0;//20;
|
||||
int parts[] = { 100, -1 };
|
||||
UINT ret;
|
||||
|
||||
MINMAXINFO *mmi;
|
||||
|
||||
switch(iMsg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "Ready", hwnd, 0);
|
||||
|
||||
//SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0);
|
||||
|
||||
SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
|
||||
SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"");
|
||||
|
||||
ShowWindow(hwndStatus, SW_HIDE);
|
||||
|
||||
SolWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0);
|
||||
|
||||
CreateSol();
|
||||
|
||||
NewGame();
|
||||
|
||||
dwAppStartTime = GetTickCount();
|
||||
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
nWidth = LOWORD(lParam);
|
||||
nHeight = HIWORD(lParam);
|
||||
|
||||
MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE);
|
||||
//MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE);
|
||||
//parts[0] = nWidth - 256;
|
||||
//SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
|
||||
|
||||
return 0;
|
||||
|
||||
case WM_GETMINMAXINFO:
|
||||
mmi = (MINMAXINFO *)lParam;
|
||||
mmi->ptMinTrackSize.x = 600;
|
||||
mmi->ptMinTrackSize.y = 400;
|
||||
|
||||
return 0;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDM_GAME_NEW:
|
||||
//simulate a button click on the new button..
|
||||
NewGame();
|
||||
return 0;
|
||||
|
||||
case IDM_GAME_DECK:
|
||||
//ShowDeckOptionsDlg(hwnd);
|
||||
return 0;
|
||||
|
||||
case IDM_GAME_OPTIONS:
|
||||
//ShowGameOptionsDlg(hwnd);
|
||||
return 0;
|
||||
|
||||
case IDM_HELP_CONTENTS:
|
||||
|
||||
WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
|
||||
|
||||
return 0;
|
||||
|
||||
case IDM_HELP_ABOUT:
|
||||
MessageBox(hwnd, _T("Solitare by J Brown\r\n\r\nCardLib version 1.0."), szAppName, MB_OK|MB_ICONINFORMATION);
|
||||
|
||||
return 0;
|
||||
|
||||
case IDM_GAME_EXIT:
|
||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case WM_CLOSE:
|
||||
|
||||
ret = IDOK;
|
||||
|
||||
if(fGameStarted)
|
||||
{
|
||||
ret = MessageBox(hwnd, _T("Quit the current game?"), szAppName, MB_OKCANCEL|MB_ICONQUESTION);
|
||||
}
|
||||
|
||||
if(ret == IDOK)
|
||||
{
|
||||
WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc (hwnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
37
rosapps/games/solitaire/solitaire.h
Normal file
37
rosapps/games/solitaire/solitaire.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef SOLITAIRE_INCLUDED
|
||||
#define SOLITAIRE_INCLUDED
|
||||
|
||||
extern CardWindow SolWnd;
|
||||
extern TCHAR szAppName[];
|
||||
extern bool fGameStarted;
|
||||
|
||||
void CreateSol();
|
||||
void NewGame(void);
|
||||
|
||||
#define NUM_ROW_STACKS 7
|
||||
#define DECK_ID 1
|
||||
#define PILE_ID 2
|
||||
#define SUIT_ID 4
|
||||
#define ROW_ID 10
|
||||
|
||||
extern CardRegion *pDeck;
|
||||
extern CardRegion *pPile;
|
||||
extern CardRegion *pSuitStack[];
|
||||
extern CardRegion *pRowStack[];
|
||||
|
||||
|
||||
bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumCards);
|
||||
bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards);
|
||||
|
||||
bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards);
|
||||
void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added);
|
||||
|
||||
void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked);
|
||||
void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked);
|
||||
|
||||
void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked);
|
||||
void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked);
|
||||
|
||||
void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iRemoved);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue