-//\r
-// CardLib - Card class\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-\r
-#ifndef _CARD_INCLUDED\r
-#define _CARD_INCLUDED\r
-\r
-enum eSuit { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 };\r
-enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, \r
- Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 };\r
-\r
-inline int MAKE_CARD(int Value, int Suit)\r
-{\r
- if(Value < 1) Value = 1;\r
- if(Value == 14) Value = 1;\r
- if(Value > 13) Value = 13;\r
-\r
- if(Suit < 0) Suit = 0;\r
- if(Suit > 3) Suit = 3;\r
-\r
- return ((Value - 1) * 4 + Suit);\r
-}\r
-\r
-class Card\r
-{\r
- friend class CardStack;\r
-\r
-public:\r
-\r
- Card() \r
- { \r
- nValue = 0; //ace of spades by default\r
- fFaceUp = true; \r
- }\r
- \r
- Card(int value, int suit) //specify a face value [1-13] and suit [0-3]\r
- { \r
- nValue = MAKE_CARD(value, suit);\r
- fFaceUp = true; \r
- }\r
- \r
- Card(int index) //specify a 0-51 index\r
- { \r
- if(index < 0) index = 0;\r
- if(index > 51) index = 51;\r
-\r
- nValue = index; \r
- fFaceUp = true;\r
- }\r
- \r
- int Suit() const\r
- { \r
- return (nValue % 4); \r
- }\r
-\r
- int LoVal() const\r
- { \r
- return (nValue / 4) + 1; \r
- }\r
-\r
- int HiVal() const\r
- { \r
- return ((nValue < 4) ? 14 : (nValue / 4) + 1); \r
- }\r
-\r
- int Idx() const //unique value (0-51 etc)\r
- {\r
- return nValue;\r
- }\r
-\r
- bool FaceUp() const\r
- {\r
- return fFaceUp;\r
- }\r
- \r
- bool FaceDown() const\r
- {\r
- return !fFaceUp;\r
- }\r
-\r
- void SetFaceUp(bool fTrue)\r
- {\r
- fFaceUp = fTrue;\r
- }\r
-\r
- bool IsBlack() const\r
- {\r
- return Suit() == 0 || Suit() == 3;\r
- }\r
-\r
- bool IsRed() const\r
- {\r
- return !IsBlack();\r
- }\r
-\r
-private:\r
-\r
- int nValue;\r
- bool fFaceUp;\r
-};\r
-\r
-#endif\r
+//
+// 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
-//\r
-// CardLib - Card bitmap support\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include "globals.h"\r
-#include "cardcolor.h"\r
-\r
-#ifndef __REACTOS__\r
-#pragma comment( lib, "..\\CardLib\\cards16.lib" )\r
-\r
-extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR );\r
-extern "C" void WINAPI FreeLibrary16( HINSTANCE );\r
-#endif\r
-\r
-#define NUMCARDBITMAPS (52+16)\r
-\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF col);\r
-\r
-void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight)\r
-{\r
- HBITMAP hBitmap;\r
- HDC hdcCard = NULL;\r
- HANDLE hOld;\r
- int i, xpos;\r
- int width, height;\r
- BITMAP bmp;\r
-\r
- for(i = 0; i < NUMCARDBITMAPS; i++)\r
- {\r
- //convert into the range used by the cdt_xxx functions\r
- int val;\r
- \r
- if(i < 52) val = (i % 4) * 13 + (i/4);\r
- else val = i;\r
- \r
- hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1));\r
- GetObject(hBitmap, sizeof(bmp), &bmp);\r
- \r
- width = bmp.bmWidth;\r
- height = bmp.bmHeight;\r
-\r
- if(i == 0) //if first time through, create BIG bitmap..\r
- {\r
- HDC hdc = GetDC(0);\r
- __hdcCardBitmaps = CreateCompatibleDC(hdc);\r
- __hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height);\r
- SelectObject(__hdcCardBitmaps, __hbmCardBitmaps);\r
-\r
- hdcCard = CreateCompatibleDC(0);\r
-\r
- ReleaseDC(0, hdc);\r
- }\r
- \r
- hOld = SelectObject(hdcCard, hBitmap);\r
- BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY);\r
- SelectObject(hdcCard, hOld);\r
- \r
- //Now draw a black border around each card...\r
- xpos = i*width;\r
- MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0);\r
- LineTo(__hdcCardBitmaps, xpos+width - 3, 0);\r
- LineTo(__hdcCardBitmaps, xpos+width - 1, 2);\r
- LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3); //vertical\r
- LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1);\r
- LineTo(__hdcCardBitmaps, xpos+2, height - 1);\r
- LineTo(__hdcCardBitmaps, xpos+0, height - 3);\r
- LineTo(__hdcCardBitmaps, xpos+0, 2);\r
- LineTo(__hdcCardBitmaps, xpos+2, 0);\r
- \r
- DeleteObject(hBitmap);\r
- }\r
- \r
- DeleteDC(hdcCard);\r
-\r
- *pwidth = width;\r
- *pheight = height;\r
- \r
-}\r
-\r
-void LoadCardBitmaps(void)\r
-{\r
- HINSTANCE hCardDll;\r
- \r
-\r
- //If Windows NT/2000/XP\r
- if(GetVersion() < 0x80000000)\r
- {\r
- hCardDll = LoadLibrary("cards.dll");\r
-\r
- if(hCardDll == 0)\r
- {\r
- MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);\r
- PostQuitMessage(0);\r
- return;\r
- }\r
- \r
- LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);\r
- \r
- FreeLibrary(hCardDll);\r
- }\r
-#ifndef __REACTOS__\r
- //Else, Win9X\r
- else\r
- {\r
- hCardDll = LoadLibrary16("cards.dll");\r
-\r
- if(hCardDll == 0)\r
- {\r
- MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION);\r
- PostQuitMessage(0);\r
- return;\r
- }\r
-\r
- LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight);\r
-\r
- FreeLibrary16(hCardDll);\r
- }\r
-#endif\r
-}\r
-\r
-void FreeCardBitmaps()\r
-{\r
- DeleteObject (__hbmCardBitmaps);\r
- DeleteDC (__hdcCardBitmaps);\r
-}\r
-//\r
-// Paint a checkered rectangle, with each alternate\r
-// pixel being assigned a different colour\r
-//\r
-static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)\r
-{\r
- static WORD wCheckPat[8] = \r
- { \r
- 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 \r
- };\r
-\r
- HBITMAP hbmp;\r
- HBRUSH hbr, hbrold;\r
- COLORREF fgold, bgold;\r
-\r
- hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);\r
- hbr = CreatePatternBrush(hbmp);\r
-\r
- //UnrealizeObject(hbr);\r
-\r
- SetBrushOrgEx(hdc, rect->left, rect->top, 0);\r
-\r
- hbrold = (HBRUSH)SelectObject(hdc, hbr);\r
-\r
- fgold = SetTextColor(hdc, fg);\r
- bgold = SetBkColor(hdc, bg);\r
- \r
- PatBlt(hdc, rect->left, rect->top, \r
- rect->right - rect->left, \r
- rect->bottom - rect->top, \r
- PATCOPY);\r
- \r
- SetBkColor(hdc, bgold);\r
- SetTextColor(hdc, fgold);\r
- \r
- SelectObject(hdc, hbrold);\r
- DeleteObject(hbr);\r
- DeleteObject(hbmp);\r
-}\r
-\r
-void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2)\r
-{\r
- if(bg) *bg = crBase;\r
- if(fg) *fg = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140);\r
- if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4);\r
- if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2);\r
-}\r
-\r
-HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height)\r
-{\r
- HANDLE hold, hpold;\r
- HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height);\r
-\r
- HPEN hpfg, hpbg, hpsh, hpsh2;\r
-\r
- RECT rect;\r
- COLORREF fg, bg, shadow, shadow2;\r
-\r
- GetSinkCols(col, &fg, &bg, &shadow, &shadow2);\r
-\r
- hold = SelectObject(hdc, hbm);\r
-\r
- //fill with a solid base colour\r
- SetRect(&rect, 0,0,width,height);\r
- PaintRect(hdc, &rect, MAKE_PALETTERGB(bg));\r
-\r
- //draw the outline\r
- hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg));\r
- hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg));\r
- hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow));\r
- hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2)); \r
-\r
- hpold = SelectObject(hdc, hpsh);\r
- MoveToEx(hdc, 2, 0, NULL);\r
- LineTo (hdc, width-3,0);\r
- LineTo (hdc, width-1, 2);\r
- \r
- SelectObject(hdc, hpold);\r
- hpold = SelectObject(hdc, hpsh2);\r
- LineTo (hdc, width-1, height-3); //vertical\r
- LineTo (hdc, width-3, height-1);\r
- LineTo (hdc, 2, height-1);\r
- LineTo (hdc, 0, height-3);\r
- SelectObject(hdc, hpold);\r
- hpold = SelectObject(hdc, hpsh);\r
-\r
- //MoveToEx( hdc, 0, height-3,0);\r
- LineTo (hdc, 0, 2);\r
- LineTo (hdc, 2, 0);\r
-\r
- SelectObject(hdc, hpold);\r
-\r
- //draw the highlight (vertical)\r
- hpold = SelectObject(hdc, hpfg);\r
- MoveToEx(hdc, width - 2, 3, NULL);\r
- LineTo (hdc, width - 2, height - 2);\r
- \r
- //(horz)\r
- MoveToEx(hdc, width - 3, height-2, NULL);\r
- LineTo (hdc, 3, height-2);\r
- SelectObject(hdc, hpold);\r
- \r
- //draw the background\r
- InflateRect(&rect, -2, -2);\r
- DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg));\r
-\r
- //overwrite the top-left background pixel\r
- SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg));\r
-\r
- DeleteObject(hpsh);\r
- DeleteObject(hpsh2);\r
- DeleteObject(hpfg);\r
- DeleteObject(hpbg);\r
-\r
- \r
- return hbm;\r
-}\r
-\r
-\r
-\r
-void CopyColor(PALETTEENTRY *pe, COLORREF col)\r
-{\r
- pe->peBlue = GetBValue(col);\r
- pe->peGreen = GetGValue(col);\r
- pe->peRed = GetRValue(col);\r
- pe->peFlags = 0;\r
-}\r
-\r
-HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours)\r
-{\r
- LOGPALETTE *lp;\r
- HPALETTE hPalette;\r
-\r
- // Allocate memory for the logical palette\r
- lp = (LOGPALETTE *)HeapAlloc(\r
- GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours);\r
-\r
- lp->palNumEntries = nNumColours;\r
- lp->palVersion = 0x300;\r
-\r
- //copy the colours into the logical palette format\r
- for(int i = 0; i < nNumColours; i++)\r
- {\r
- CopyColor(&lp->palPalEntry[i], cols[i]);\r
- }\r
-\r
- // create palette!\r
- hPalette = CreatePalette(lp);\r
-\r
- HeapFree(GetProcessHeap(), 0, lp);\r
-\r
- return hPalette;\r
-}\r
+//
+// 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 = NULL;
+ 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;
+}
-//\r
-// CardLib - CardButton class\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include <tchar.h>\r
-\r
-#include "cardlib.h"\r
-#include "cardwindow.h"\r
-#include "cardbutton.h"\r
-#include "cardcolor.h"\r
-\r
-HPALETTE UseNicePalette(HDC, HPALETTE);\r
-void RestorePalette(HDC, HPALETTE);\r
-\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
-\r
-CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,\r
- int x, int y, int width, int height)\r
-\r
- : parentWnd(parent), id(Id), uStyle(Style), fVisible(visible), ButtonCallback(0)\r
-{\r
- crText = RGB(255,255,255);\r
- crBack = RGB(0, 128, 0);\r
- \r
- xadjust = 0;\r
- yadjust = 0;\r
- xjustify = 0;\r
- yjustify = 0;\r
-\r
- fMouseDown = false;\r
- fButtonDown = false;\r
-\r
- hIcon = 0;\r
-\r
- SetText(szText);\r
- Move(x, y, width, height);\r
-\r
- mxlock = CreateMutex(0, FALSE, 0);\r
-\r
- hFont = 0;\r
-}\r
-\r
-CardButton::~CardButton()\r
-{\r
- CloseHandle(mxlock);\r
-}\r
-\r
-void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)\r
-{\r
- RECT fill;\r
-\r
- HANDLE hOld;\r
-\r
- HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));\r
- HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));\r
- HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);\r
- \r
- int x = rect->left;\r
- int y = rect->top;\r
- int width = rect->right-rect->left - 1;\r
- int height = rect->bottom-rect->top - 1;\r
- \r
- SetRect(&fill, x+1, y+1, x+width-1, y+height-1);\r
-\r
- int one = 1;\r
- \r
- if(!fNormal)\r
- {\r
- x += width;\r
- y += height;\r
- width = -width;\r
- height = -height;\r
- one = -1;\r
- OffsetRect(&fill, 1, 1);\r
- }\r
- \r
- if(fNormal)\r
- hOld = SelectObject(hdc, hhi);\r
- else\r
- hOld = SelectObject(hdc, hhi);\r
-\r
- MoveToEx(hdc, x, y+height, 0);\r
- LineTo(hdc, x, y);\r
- LineTo(hdc, x+width, y);\r
- SelectObject(hdc, hOld);\r
-\r
- hOld = SelectObject(hdc, hbl);\r
- LineTo(hdc, x+width, y+height);\r
- LineTo(hdc, x-one, y+height);\r
- SelectObject(hdc, hOld);\r
-\r
- hOld = SelectObject(hdc, hsh);\r
- MoveToEx(hdc, x+one, y+height-one, 0);\r
- LineTo(hdc, x+width-one, y+height-one);\r
- LineTo(hdc, x+width-one, y);\r
- SelectObject(hdc, hOld);\r
-\r
- PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));\r
-\r
- DeleteObject(hhi);\r
- DeleteObject(hsh);\r
-}\r
-\r
-void CardButton::Clip(HDC hdc)\r
-{\r
- if(fVisible == false) return;\r
- \r
- ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);\r
-}\r
-\r
-void CardButton::Draw(HDC hdc, bool fNormal)\r
-{\r
- SIZE textsize;\r
- int x, y; //text x, y\r
- int ix, iy; //icon x, y\r
- int iconwidth = 0;\r
-\r
- RECT cliprect;\r
-\r
- if(fVisible == 0) return;\r
-\r
- if(hFont == 0)\r
- SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); \r
- else\r
- SelectObject(hdc, hFont); \r
- \r
- GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);\r
- \r
- if(hIcon)\r
- {\r
- x = rect.left + 32 + 8;\r
- }\r
- else\r
- {\r
- if(uStyle & CB_ALIGN_LEFT)\r
- {\r
- x = rect.left + iconwidth;\r
- }\r
- else if(uStyle & CB_ALIGN_RIGHT)\r
- {\r
- x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);\r
- }\r
- else //centered\r
- {\r
- x = rect.right - rect.left - iconwidth;\r
- x = (x - textsize.cx) / 2;\r
- x += rect.left + iconwidth;\r
- }\r
- }\r
- \r
- y = rect.bottom - rect.top;\r
- y = (y - textsize.cy) / 2;\r
- y += rect.top;\r
- \r
- //calc icon position..\r
- ix = rect.left + 4;\r
- iy = rect.top + (rect.bottom-rect.top-32) / 2;\r
-\r
- //if button is pressed, then shift text\r
- if(fNormal == false && (uStyle & CB_PUSHBUTTON))\r
- {\r
- x += 1;\r
- y += 1;\r
- ix += 1;\r
- iy += 1;\r
- }\r
-\r
- SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);\r
- ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);\r
-\r
- //\r
- // Calc icon pos\r
- //\r
- \r
- if(hIcon)\r
- {\r
- ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);\r
- }\r
- \r
- if(uStyle & CB_PUSHBUTTON)\r
- {\r
- DrawRect(hdc, &rect, fNormal);\r
-\r
- SetBkColor(hdc, MAKE_PALETTERGB(crBack));\r
- SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
- \r
- SelectClipRgn(hdc, 0); \r
-\r
- ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);\r
- }\r
- else\r
- {\r
- SetBkColor(hdc, MAKE_PALETTERGB(crBack));\r
- SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));\r
-\r
- SelectClipRgn(hdc, 0);\r
-\r
- ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);\r
- }\r
-\r
- if(hIcon)\r
- {\r
- HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));\r
- DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);\r
- DeleteObject(hbr);\r
- }\r
-\r
-}\r
-\r
-void CardButton::AdjustPosition(int winwidth, int winheight)\r
-{\r
- int width = rect.right-rect.left;\r
- int height = rect.bottom-rect.top;\r
-\r
- width = width & ~0x1;\r
-\r
- switch(xjustify)\r
- {\r
- case CS_XJUST_NONE:\r
- break;\r
-\r
- case CS_XJUST_CENTER: //centered\r
- rect.left = (winwidth - (width)) / 2;\r
- rect.left += xadjust;\r
- rect.right = rect.left+width;\r
- break;\r
-\r
- case CS_XJUST_RIGHT: //right-aligned\r
- rect.left = winwidth - width;\r
- rect.left += xadjust;\r
- rect.right = rect.left+width;\r
- break;\r
- }\r
-\r
- switch(yjustify)\r
- {\r
- case CS_YJUST_NONE:\r
- break;\r
-\r
- case CS_YJUST_CENTER: //centered\r
- rect.top = (winheight - (height)) / 2;\r
- rect.top += yadjust;\r
- rect.bottom = rect.top+height;\r
- break;\r
-\r
- case CS_YJUST_BOTTOM: //right-aligned\r
- rect.top = winheight - height;\r
- rect.top += yadjust;\r
- rect.bottom = rect.top+height;\r
- break;\r
- }\r
-\r
-}\r
-\r
-int CardButton::OnLButtonDown(HWND hwnd, int x, int y)\r
-{\r
- if((uStyle & CB_PUSHBUTTON) == 0) \r
- return 0;\r
-\r
- //make sure that the user is allowed to do something\r
- if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
- {\r
- return 0;\r
- }\r
- else\r
- {\r
- ReleaseMutex(mxlock);\r
- }\r
- \r
- fMouseDown = true;\r
- fButtonDown = true;\r
-\r
- Redraw();\r
-\r
- SetCapture(hwnd);\r
-\r
- return 1;\r
-}\r
-\r
-int CardButton::OnMouseMove(HWND hwnd, int x, int y)\r
-{\r
- if(fMouseDown)\r
- {\r
- bool fOldButtonDown = fButtonDown;\r
-\r
- POINT pt;\r
- \r
- pt.x = x;\r
- pt.y = y;\r
- \r
- if(PtInRect(&rect, pt))\r
- fButtonDown = true;\r
- else\r
- fButtonDown = false;\r
- \r
- if(fButtonDown != fOldButtonDown)\r
- Redraw();\r
- }\r
- \r
- return 0;\r
-}\r
-\r
-int CardButton::OnLButtonUp(HWND hwnd, int x, int y)\r
-{\r
- if(fMouseDown)\r
- {\r
- fMouseDown = false;\r
- fButtonDown = false;\r
- \r
- if(uStyle & CB_PUSHBUTTON)\r
- {\r
- Redraw();\r
- ReleaseCapture();\r
- }\r
- \r
- //if have clicked the button\r
- if(parentWnd.CardButtonFromPoint(x, y) == this)\r
- {\r
- if(ButtonCallback)\r
- {\r
- ButtonCallback(*this); \r
- }\r
- else\r
- {\r
- HWND hwnd = (HWND)parentWnd;\r
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);\r
- }\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-#define _countof(array) (sizeof(array)/sizeof(array[0]))\r
-\r
-CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)\r
-{\r
- CardButton *cb;\r
-\r
- if(nNumButtons == MAXBUTTONS) \r
- return 0;\r
-\r
- cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);\r
- Buttons[nNumButtons++] = cb;\r
-\r
- if(uStyle & CB_PUSHBUTTON)\r
- {\r
- cb->SetBackColor(CardButton::GetFace(crBackgnd));\r
- //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));\r
- cb->SetForeColor(RGB(255,255,255));\r
- }\r
- else\r
- {\r
- cb->SetBackColor(crBackgnd);\r
- cb->SetForeColor(RGB(255,255,255));\r
- }\r
- \r
- return cb;\r
-}\r
-\r
-void CardButton::SetText(TCHAR *lpszFormat, ...)\r
-{\r
- int count;\r
-\r
- va_list args;\r
- va_start(args, lpszFormat);\r
-\r
- count = wvsprintf(szText, lpszFormat, args);\r
- va_end(args);\r
-}\r
-\r
-int CardButton::Id()\r
-{\r
- return id;\r
-}\r
-\r
-void CardButton::Show(bool fShow)\r
-{\r
- fVisible = fShow;\r
-}\r
-\r
-void CardButton::Move(int x, int y, int width, int height)\r
-{\r
- SetRect(&rect, x, y, x+width, y+height);\r
-}\r
-\r
-void CardButton::Redraw()\r
-{\r
- HDC hdc = GetDC((HWND)parentWnd);\r
-\r
- HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);\r
-\r
- Draw(hdc, !fButtonDown);\r
- \r
- RestorePalette(hdc, hOldPal);\r
- \r
- ReleaseDC((HWND)parentWnd, hdc);\r
-}\r
-\r
-void CardButton::SetForeColor(COLORREF cr)\r
-{\r
- crText = cr;\r
-}\r
-\r
-void CardButton::SetBackColor(COLORREF cr)\r
-{\r
- crBack = cr;\r
-\r
- crHighlight = GetHighlight(cr);\r
- crShadow = GetShadow(cr);\r
- \r
- //crHighlight = ScaleLumRGB(cr, +0.25);\r
- //crShadow = ScaleLumRGB(cr, -0.25);\r
-}\r
-\r
-// Static member\r
-COLORREF CardButton::GetHighlight(COLORREF crBase)\r
-{\r
- return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);\r
-}\r
-\r
-// Static member\r
-COLORREF CardButton::GetShadow(COLORREF crBase)\r
-{\r
- return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25);\r
-}\r
-\r
-COLORREF CardButton::GetFace(COLORREF crBase)\r
-{\r
- return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);\r
-}\r
-\r
-void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)\r
-{\r
- xadjust = xAdjust;\r
- yadjust = yAdjust;\r
- xjustify = xJustify;\r
- yjustify = yJustify;\r
-}\r
-\r
-void CardButton::SetIcon(HICON hicon, bool fRedraw)\r
-{\r
- hIcon = hicon;\r
- \r
- if(fRedraw)\r
- Redraw();\r
-}\r
-\r
-void CardButton::SetFont(HFONT font)\r
-{\r
- //don't delete the existing font..\r
- hFont = font;\r
-}\r
-\r
-void CardButton::SetButtonProc(pButtonProc proc)\r
-{\r
- ButtonCallback = proc;\r
-}\r
-\r
-bool CardButton::Lock()\r
-{\r
- DWORD dw = WaitForSingleObject(mxlock, 0);\r
-\r
- if(dw == WAIT_OBJECT_0)\r
- return true; \r
- else\r
- return false;\r
-}\r
-\r
-bool CardButton::UnLock()\r
-{\r
- if(ReleaseMutex(mxlock))\r
- return true;\r
- else\r
- return false;\r
-}\r
-\r
-void CardButton::SetStyle(UINT style)\r
-{\r
- uStyle = style;\r
-}\r
-\r
-UINT CardButton::GetStyle()\r
-{\r
- return uStyle;\r
-}\r
+//
+// 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), uStyle(Style), fVisible(visible), 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;
+}
-#ifndef CARDBUTTON_INCLUDED\r
-#define CARDBUTTON_INCLUDED\r
-\r
-#define MAXBUTTONTEXT 64\r
-\r
-#include "cardlib.h"\r
-\r
-class CardButton\r
-{\r
- friend class CardWindow;\r
-\r
- //\r
- // Constructor is PRIVATE - only a\r
- // CardWindow can create buttons!\r
- //\r
- CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible,\r
- int x, int y, int width, int height);\r
-\r
- ~CardButton();\r
-\r
-public:\r
-\r
- void SetStyle(UINT uStyle);\r
- UINT GetStyle();\r
-\r
- void SetText(TCHAR *fmt, ...);\r
- void SetFont(HFONT font);\r
-\r
- void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);\r
-\r
- void SetForeColor(COLORREF cr);\r
- void SetBackColor(COLORREF cr);\r
-\r
- void Move(int x, int y, int width, int height);\r
- void Show(bool fShow);\r
- void Redraw();\r
- int Id();\r
-\r
- void SetIcon(HICON hicon, bool fRedraw);\r
-\r
- void SetButtonProc(pButtonProc proc);\r
-\r
- CardWindow &GetCardWindow() { return parentWnd; }\r
-\r
- bool Lock();\r
- bool UnLock();\r
-\r
- static COLORREF GetHighlight(COLORREF crBase);\r
- static COLORREF GetShadow(COLORREF crBase);\r
- static COLORREF GetFace(COLORREF crBase);\r
-\r
-private:\r
-\r
- //\r
- // Private member functions\r
- //\r
- void AdjustPosition(int winwidth, int winheight);\r
-\r
- void DrawRect(HDC hdc, RECT *rect, bool fNormal);\r
- void Draw(HDC hdc, bool fNormal);\r
- void Clip(HDC hdc);\r
-\r
- int OnLButtonDown(HWND hwnd, int x, int y);\r
- int OnMouseMove(HWND hwnd, int x, int y);\r
- int OnLButtonUp(HWND hwnd, int x, int y);\r
-\r
- //\r
- // Private members\r
- //\r
- CardWindow &parentWnd;\r
-\r
- RECT rect;\r
- int id;\r
- UINT uStyle;\r
- bool fVisible;\r
-\r
- int xadjust;\r
- int xjustify;\r
- int yadjust;\r
- int yjustify;\r
-\r
- HICON hIcon;\r
- HFONT hFont;\r
-\r
- TCHAR szText[MAXBUTTONTEXT];\r
-\r
- COLORREF crBack;\r
- COLORREF crText;\r
- COLORREF crHighlight;\r
- COLORREF crShadow;\r
- COLORREF crShadow2;\r
-\r
- bool fMouseDown;\r
- bool fButtonDown;\r
-\r
- HANDLE mxlock;\r
-\r
- pButtonProc ButtonCallback;\r
-};\r
-\r
-#endif\r
+#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
-//\r
-// Colour support\r
-//\r
-#include <windows.h>\r
-\r
-#define MakeRGB RGB\r
-\r
-#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )\r
-#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )\r
-\r
-inline double fMax(double a, double b)\r
-{\r
- return a < b ? b : a;\r
-}\r
-\r
-inline double fMin(double a, double b)\r
-{\r
- return a < b ? a : b;\r
-}\r
-/******************************************************************************\r
- FUNCTION: RGBtoHLS\r
- PURPOSE: Convert from RGB to HLS\r
- IN: RGB color (0xBBGGRR)\r
- OUT: Hue, Saturation, Luminance from 0 to 1\r
- COPYRIGHT:1995-1997 Robert Mashlan\r
- Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
-******************************************************************************/\r
-void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S ) \r
-{\r
- double delta;\r
- double r = (double)((rgb )&0xFF)/255;\r
- double g = (double)((rgb>> 8)&0xFF)/255;\r
- double b = (double)((rgb>>16)&0xFF)/255;\r
- double cmax = MAX3(r,g,b);\r
- double cmin = MIN3(r,g,b);\r
- *L=(cmax+cmin)/2.0;\r
- \r
- if(cmax == cmin) \r
- {\r
- *S = *H = 0; // it's really undefined\r
- }\r
- else \r
- {\r
- if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin);\r
- else *S = (cmax-cmin)/(2.0-cmax-cmin);\r
- \r
- delta = cmax - cmin;\r
- \r
- if(r == cmax) \r
- {\r
- *H = (g - b) / delta;\r
- }\r
- else\r
- {\r
- if(g == cmax) *H = 2.0 + (b-r) / delta;\r
- else *H = 4.0 + (r-g) / delta;\r
- }\r
- *H /= 6.0;\r
- if (*H < 0.0) *H += 1;\r
- }\r
-}\r
-\r
-/******************************************************************************\r
- FUNCTION: HueToRGB\r
- PURPOSE: Convert a hue (color) to RGB\r
- COPYRIGHT:1995-1997 Robert Mashlan\r
- Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
-******************************************************************************/\r
-double HueToRGB(const double m1, const double m2, double h ) \r
-{\r
- if (h<0) h+=1.0;\r
- if (h>1) h-=1.0;\r
- if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);\r
- if (2.0*h < 1 ) return m2;\r
- if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);\r
- return m1;\r
-}\r
-\r
-\r
-/******************************************************************************\r
- FUNCTION: HLStoRGB\r
- PURPOSE: Convert from HSL to RGB\r
- IN: Hue, Saturation, Luminance from 0 to 1\r
- RETURN: RGB color (0xBBGGRR)\r
- COPYRIGHT:1995-1997 Robert Mashlan\r
- Modified for LabWindows/CVI, 1999 Guillaume Dargaud\r
-******************************************************************************/\r
-\r
-COLORREF HLStoRGB(const double H, const double L, const double S ) \r
-{\r
- double r,g,b;\r
- double m1, m2;\r
-\r
- if(S == 0) \r
- {\r
- r = g = b = L;\r
- }\r
- else \r
- {\r
- if (L <= 0.5) \r
- m2 = L * (1.0 + S);\r
- else \r
- m2 = L + S - L * S;\r
-\r
- m1 = 2.0 * L - m2;\r
-\r
- r = HueToRGB(m1,m2,H+1.0/3.0);\r
- g = HueToRGB(m1,m2,H);\r
- b = HueToRGB(m1,m2,H-1.0/3.0);\r
- }\r
- \r
- return RGB(r*255, g*255, b*255);\r
-}\r
-\r
-\r
-\r
-/******************************************************************************\r
- FUNCTION: ColorScaleHSL\r
- PURPOSE: Returns the HSL linear interpolated color between 2 colors\r
- (more natural looking than RGB interpolation)\r
- For instance if the luminance is the same in Col1 and Col2, \r
- then the luminance of the result will be the same\r
- If Ratio=0, you get Col1,\r
- If Ratio=1, you get Col2\r
- IN: Col1: low color in hex 0xBBGGRR format\r
- Col2: high color in hex 0xBBGGRR format\r
- Ratio: 0 for low color, 1 for high color, or in between\r
- EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F\r
-******************************************************************************/\r
-COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio) \r
-{\r
- static double H1, H2, S1, S2, L1, L2;\r
- \r
- if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1\r
- else if (Ratio>=1) return Col2;\r
-\r
- RGBtoHLS( Col1, &H1, &L1, &S1);\r
- RGBtoHLS( Col2, &H2, &L2, &S2);\r
- return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );\r
-}\r
-\r
-\r
-/******************************************************************************\r
- FUNCTION: ColorScaleRGB\r
- PURPOSE: Returns the RGB linear interpolated color between 2 colors\r
- If Ratio=0, you get Col1,\r
- If Ratio=1, you get Col2\r
- IN: Col1: low color in hex 0xBBGGRR format\r
- Col2: high color in hex 0xBBGGRR format\r
- Ratio: 0 for low color, 1 for high color, or in between\r
- EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080\r
-******************************************************************************/\r
-COLORREF ColorScaleRGB( const COLORREF Col1, \r
- const COLORREF Col2, \r
- const double Ratio) {\r
- int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;\r
- int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;\r
-\r
- if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1\r
- else if (Ratio>=1) return Col2;\r
-\r
-/* return RGB(\r
- (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding\r
- (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),\r
- (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)\r
- );*/\r
-\r
- /*double r = Ratio;\r
- if(Col2 == 0)\r
- r = 1-Ratio;\r
- else\r
- r = 1+Ratio;\r
- R1 = (int)(double(R1) * r + 0.5);\r
- G1 = (int)(double(G1) * r + 0.5);\r
- B1 = (int)(double(B1) * r + 0.5);\r
- return RGB(R1,G1,B1);*/\r
-\r
- return RGB(\r
- (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding\r
- (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),\r
- (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)\r
- );\r
-}\r
-\r
-\r
-\r
-COLORREF ColorDarker(COLORREF col, double ratio)\r
-{\r
- return ColorScaleHSL(col, RGB(0,0,0), ratio);\r
-}\r
-\r
-COLORREF ColorLighter(COLORREF col, double ratio)\r
-{\r
- return ColorScaleHSL(col, RGB(255,255,255), ratio);\r
-}\r
-\r
-//\r
-// Experimental!!!\r
-//\r
-#if 0\r
-\r
-typedef enum { Red, Green, Blue };\r
-\r
-void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)\r
-{\r
- double mn, mx;\r
- int major;\r
-\r
- BYTE red, green, blue;\r
-\r
- red = GetRValue(rgb);\r
- green = GetGValue(rgb);\r
- blue = GetBValue(rgb);\r
-\r
- if(red < green)\r
- {\r
- mn = red; mx = green; major = Green;\r
- }\r
- else\r
- {\r
- mn = green; mx = red; major = Red;\r
- }\r
-\r
- if(blue < mn)\r
- {\r
- mn = blue;\r
- }\r
- else if(blue > mx)\r
- {\r
- mx = blue; major = Blue;\r
- }\r
-\r
- if(mn == mx)\r
- {\r
- *Lum = mn / 255;\r
- *Sat = 0;\r
- *Hue = 0;\r
- }\r
- else\r
- {\r
- *Lum = (mx + mn) / 510;\r
-\r
- if(*Lum <= 0.5)\r
- *Sat = (mx-mn) / (mn+mx);\r
- else\r
- *Sat = (mx-mn) / (510-mn-mx);\r
-\r
- switch(major)\r
- {\r
- case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;\r
- break;\r
-\r
- case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;\r
- break;\r
-\r
- case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;\r
- break;\r
-\r
- }\r
-\r
- if(*Hue > 360.0)\r
- *Hue -= 360.0;\r
- }\r
-}\r
-\r
-static BYTE Value(double m1, double m2, double hue)\r
-{\r
-\r
- if(hue > 360) hue -= 360;\r
- else if(hue < 0) hue += 360;\r
-\r
- if(hue < 60)\r
- m1 = m1 + (m2 - m1) * hue / 60;\r
- else if(hue < 180)\r
- m1 = m2;\r
- else if(hue < 240)\r
- m1 = m1 + (m2 - m1) * (240 - hue) / 60;\r
-\r
- return (BYTE)(m1 * 255);\r
-}\r
-\r
-COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)\r
-{\r
- BYTE red, green, blue;\r
-\r
- if(Sat == 0)\r
- {\r
- red = green = blue = (BYTE)(Lum * 255); \r
- }\r
- else\r
- {\r
- double m1, m2;\r
-\r
- if(Lum <= 0.5)\r
- m2 = Lum + Lum * Sat;\r
- else\r
- m2 = Lum + Sat - Lum * Sat;\r
-\r
- m1 = 2 * Lum - m2;\r
-\r
- red = Value(m1, m2, Hue + 120);\r
- green = Value(m1, m2, Hue);\r
- blue = Value(m1, m2, Hue - 120);\r
- }\r
-\r
- return RGB(red, green, blue);\r
-}\r
-\r
-COLORREF ScaleLumRGB(COLORREF col1, double ratio)\r
-{\r
- double H1, L1, S1;\r
-\r
- RGBtoHLS(col1, &H1, &L1, &S1);\r
-\r
- L1 += L1 * ratio;\r
-\r
- return HLStoRGB(H1, L1, S1);\r
-}\r
-\r
-COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio) \r
-{\r
- static double H1, H2, S1, S2, L1, L2;\r
- \r
- if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1\r
- else if(Ratio >= 1) return Col2;\r
-\r
- RGBtoHLS( Col1, &H1, &L1, &S1);\r
- RGBtoHLS( Col2, &H2, &L2, &S2);\r
-\r
- return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);\r
-}\r
-\r
-COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)\r
-{\r
- return ColorScaleHSL(Col1, Col2, Ratio);\r
-}\r
-#endif\r
+//
+// 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)
+{
+ return ColorScaleHSL(col, RGB(0,0,0), ratio);
+}
+
+COLORREF ColorLighter(COLORREF col, double ratio)
+{
+ return ColorScaleHSL(col, RGB(255,255,255), ratio);
+}
+
+//
+// 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
-\r
-COLORREF ColorScaleRGB( const COLORREF Col1, \r
- const COLORREF Col2, \r
- const double Ratio);\r
-\r
-COLORREF ColorScaleHSL( const COLORREF Col1, \r
- const COLORREF Col2, \r
- const double Ratio);\r
-\r
-\r
-COLORREF ColorDarker(COLORREF col, double ratio);\r
-COLORREF ColorLighter(COLORREF col, double ratio);\r
-\r
-COLORREF ScaleLumRGB(COLORREF col1, double ratio);\r
-\r
-#define MAKE_PALETTERGB(colref) (0x02000000 | colref)\r
+
+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)
-//\r
-// CardCount is a helper library for CardStacks.\r
-// \r
-// When you initialize a CardCount object with a \r
-// cardstack, it keeps track of the number of cards\r
-// the stack contains.\r
-//\r
-// e.g. CardCount count(cardstack);\r
-//\r
-// Then you can do:\r
-// \r
-// int num_fives = count[5]\r
-// \r
-// count.Add(cardstack2); - combine with another stack\r
-//\r
-// int num_aces = count[1] - aces low\r
-// int num_aces = count[14] - aces high\r
-//\r
-// count.Clear();\r
-//\r
-#include "cardcount.h"\r
-\r
-CardCount::CardCount()\r
-{\r
- Clear();\r
-}\r
-\r
-CardCount::CardCount(const CardStack &cs)\r
-{\r
- Init(cs);\r
-}\r
-\r
-void CardCount::Clear()\r
-{\r
- for(int i = 0; i < 13; i++)\r
- count[i] = 0;\r
-}\r
-\r
-void CardCount::Add(const CardStack &cs)\r
-{\r
- for(int i = 0; i < cs.NumCards(); i++)\r
- {\r
- Card card = cs[i];\r
-\r
- int val = card.LoVal();\r
- count[val - 1]++;\r
- }\r
-}\r
-\r
-void CardCount::Sub(const CardStack &cs)\r
-{\r
- for(int i = 0; i < cs.NumCards(); i++)\r
- {\r
- Card card = cs[i];\r
- int val = card.LoVal();\r
- \r
- if(count[val - 1] > 0)\r
- count[val - 1]--;\r
- }\r
-}\r
-\r
-void CardCount::Init(const CardStack &cs)\r
-{\r
- Clear();\r
- Add(cs);\r
-}\r
-\r
-int CardCount::operator [] (size_t index) const\r
-{\r
- if(index < 1) return 0;\r
- else if(index > 14) return 0; //if out of range\r
- else if(index == 14) index = 1; //if a "ace-high"\r
-\r
- return count[index - 1];\r
-}\r
-\r
-//\r
-// Decrement specified item by one\r
-//\r
-void CardCount::Dec(size_t index)\r
-{\r
- if(index < 1) return;\r
- else if(index > 14) return; //if out of range\r
- else if(index == 14) index = 1; //if a "ace-high"\r
-\r
- index -= 1;\r
-\r
- if(count[index] > 0) \r
- count[index]--;\r
-}\r
+//
+// 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]--;
+}
-#ifndef _CARDCOUNT_INCLUDED\r
-#define _CARDCOUNT_INCLUDED\r
-\r
-#include <windows.h>\r
-\r
-#include "cardstack.h"\r
-\r
-class CardCount\r
-{\r
-public:\r
- CardCount();\r
- CardCount(const CardStack &cs);\r
-\r
- void Init(const CardStack &cs);\r
- void Clear();\r
- void Add(const CardStack &cs);\r
- void Sub(const CardStack &cs);\r
-\r
- void Dec(size_t index);\r
-\r
- int operator[] (size_t index) const;\r
-\r
- CardCount &operator = (const CardStack &cs);\r
- CardCount &operator += (const CardStack &cs);\r
-\r
-private:\r
- int count[13]; //13 different card values \r
- //(ace,2,3,4,5,6,7,8,9,10,J,Q,K)\r
-};\r
-\r
-#endif\r
+#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
-//\r
-// CardLib - not much of interest in here\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include "cardlib.h"\r
-#include "globals.h"\r
-\r
-void LoadCardBitmaps(void);\r
-\r
-//static bool __CARDLIB_ACES_HIGH = false;\r
-extern double __CARDZOOMSPEED;\r
-\r
-//\r
-// Global variables!\r
-//\r
-HDC __hdcCardBitmaps;\r
-HBITMAP __hbmCardBitmaps;\r
-\r
-HDC __hdcPlaceHolder;\r
-HBITMAP __hbmPlaceHolder;\r
-HPALETTE __holdplacepal;\r
-\r
-int __cardwidth;\r
-int __cardheight;\r
-\r
-HPALETTE __hPalette;\r
-\r
-\r
-//\r
-// Cardlib global functions!\r
-//\r
-void CardLib_SetZoomSpeed(int speed)\r
-{\r
- __CARDZOOMSPEED = (double)speed;\r
-}\r
-\r
-/*\r
-\r
- It's dangerous to use these operators, because of all\r
- the implicit conversions that could take place, which\r
- would have unpredicted side-effects.\r
-\r
- e.g. Card card(Hearts, 4);\r
- if(card == 4) - how does 4 get converted??\r
- It uses the Card(int uval) constructor,\r
- which results in a 2 of clubs...\r
- not what was expected\r
-*/ \r
-/*\r
-void CardLib_SetAcesHigh(bool fHigh);\r
-bool operator != (const Card &lhs, const Card &rhs);\r
-bool operator == (const Card &lhs, const Card &rhs);\r
-bool operator < (const Card &lhs, const Card &rhs);\r
-bool operator <= (const Card &lhs, const Card &rhs);\r
-bool operator > (const Card &lhs, const Card &rhs);\r
-bool operator >= (const Card &lhs, const Card &rhs);\r
-*/\r
-\r
-/*\r
-void CardLib_SetAcesHigh(bool fHigh)\r
-{\r
- __CARDLIB_ACES_HIGH = fHigh;\r
-}\r
-\r
-bool operator == (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() == rhs.HiVal();\r
- else\r
- return lhs.LoVal() == rhs.LoVal();\r
-}\r
-\r
-bool operator != (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() != rhs.HiVal();\r
- else\r
- return lhs.LoVal() != rhs.LoVal();\r
-}\r
-\r
-bool operator > (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() > rhs.HiVal();\r
- else\r
- return lhs.LoVal() > rhs.LoVal();\r
-}\r
-\r
-bool operator >= (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() >= rhs.HiVal();\r
- else\r
- return lhs.LoVal() >= rhs.LoVal();\r
-}\r
-\r
-bool operator < (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() < rhs.HiVal();\r
- else\r
- return lhs.LoVal() < rhs.LoVal();\r
-}\r
-\r
-bool operator <= (const Card &lhs, const Card &rhs)\r
-{\r
- if(__CARDLIB_ACES_HIGH)\r
- return lhs.HiVal() <= rhs.HiVal();\r
- else\r
- return lhs.LoVal() <= rhs.LoVal();\r
-}\r
-*/\r
-\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF colour)\r
-{\r
- COLORREF oldcr = SetBkColor(hdc, colour);\r
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0);\r
- SetBkColor(hdc, oldcr);\r
-}\r
+//
+// 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);
+}
-#ifndef CARDLIB_INCLUDED\r
-#define CARDLIB_INCLUDED\r
-\r
-#define CARDLIBPROC __stdcall\r
-\r
-void CardBlt(HDC hdc, int x, int y, int nCardNum);\r
-void CardLib_SetZoomSpeed(int);\r
-\r
-#define CS_EI_NONE 0\r
-#define CS_EI_SUNK 1\r
-\r
-#define CS_DEFXOFF 12 //x-offset\r
-#define CS_DEFYOFF 18 //y-offset\r
-#define CS_NO3D 1 //default 3d counts (recommened)\r
-#define CS_DEF3D 10 //(best for decks)\r
-\r
-//#define CS_EI_CIRC 2\r
-//#define CS_EI_X 3\r
-\r
-#define CS_DRAG_NONE 0\r
-#define CS_DRAG_TOP 1\r
-#define CS_DRAG_ALL 2\r
-#define CS_DRAG_CALLBACK 3\r
-\r
-#define CS_DROP_NONE 0\r
-#define CS_DROP_ALL 1\r
-#define CS_DROP_CALLBACK 2\r
-\r
-#define CS_XJUST_NONE 0\r
-#define CS_XJUST_RIGHT 1\r
-#define CS_XJUST_CENTER 2\r
-\r
-#define CS_YJUST_NONE 0\r
-#define CS_YJUST_BOTTOM 1\r
-#define CS_YJUST_CENTER 2\r
-\r
-#define CB_STATIC 0 //static text label\r
-#define CB_PUSHBUTTON 1 //normal button\r
-#define CB_ALIGN_CENTER 0 //centered is default\r
-#define CB_ALIGN_LEFT 2\r
-#define CB_ALIGN_RIGHT 4\r
-\r
-#define CS_FACE_UP 0 //all cards face-up\r
-#define CS_FACE_DOWN 1 //all cards face-down\r
-#define CS_FACE_DOWNUP 2 //bottom X cards down, top-most face-up\r
-#define CS_FACE_UPDOWN 3 //bottom X cards up, top-most face-down\r
-#define CS_FACE_ANY 4 //cards can be any orientation\r
-\r
-#define CS_DROPZONE_NODROP -1\r
-\r
-//\r
-// Define the standard card-back indices\r
-//\r
-#define ecbCROSSHATCH 53\r
-#define ecbWEAVE1 54\r
-#define ecbWEAVE2 55\r
-#define ecbROBOT 56\r
-#define ecbFLOWERS 57\r
-#define ecbVINE1 58\r
-#define ecbVINE2 59\r
-#define ecbFISH1 60\r
-#define ecbFISH2 61\r
-#define ecbSHELLS 62\r
-#define ecbCASTLE 63\r
-#define ecbISLAND 64\r
-#define ecbCARDHAND 65\r
-#define ecbUNUSED 66\r
-#define ecbTHE_X 67\r
-#define ecbTHE_O 68\r
-\r
-\r
-class CardRegion;\r
-class CardButton;\r
-class CardStack;\r
-class CardWindow;\r
-\r
-typedef bool (CARDLIBPROC *pCanDragProc) (CardRegion &stackobj, int iNumDragging);\r
-typedef bool (CARDLIBPROC *pCanDropProc) (CardRegion &stackobj, const CardStack &cards);\r
-typedef void (CARDLIBPROC *pClickProc) (CardRegion &stackobj, int iNumCards);\r
-typedef void (CARDLIBPROC *pAddProc) (CardRegion &stackobj, const CardStack &cards);\r
-typedef void (CARDLIBPROC *pRemoveProc) (CardRegion &stackobj, int iNumRemoved);\r
-\r
-typedef void (CARDLIBPROC *pResizeWndProc) (int width, int height);\r
-typedef int (CARDLIBPROC *pDropZoneProc) (int dzid, const CardStack &cards);\r
-\r
-typedef void (CARDLIBPROC *pButtonProc) (CardButton &pButton);\r
-\r
-\r
-#include "card.h"\r
-#include "cardbutton.h"\r
-#include "cardstack.h"\r
-#include "cardregion.h"\r
-#include "cardcount.h"\r
-#include "cardwindow.h"\r
-\r
-#ifdef _DEBUG\r
-typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj);\r
-void CardLib_SetStackClickProc(pDebugClickProc proc);\r
-#endif\r
-\r
-\r
-#endif\r
+#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;
+class CardWindow;
+
+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
-//\r
-// CardLib - CardRegion class\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-\r
-#include "cardlib.h"\r
-#include "cardregion.h"\r
-#include "cardwindow.h"\r
-#include "cardcolor.h"\r
-\r
-HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height);\r
-\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
-\r
-CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset) \r
-: id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible)\r
-{\r
- width = __cardwidth;\r
- height = __cardheight;\r
-\r
- crBackgnd = RGB(0, 64, 100);\r
-\r
- uFaceDirType = CS_FACE_UP;\r
- nFaceDirOption = 0;\r
- uEmptyImage = CS_EI_SUNK;\r
-\r
- fVisible = visible;\r
-\r
- nThreedCount = 1;\r
- nBackCardIdx = 53;\r
-\r
- Update(); //Update this stack's size+card count\r
-\r
- hdcBackGnd = 0;\r
- hbmBackGnd = 0;\r
- hdcDragCard = 0;\r
- hbmDragCard = 0;\r
-\r
- nDragCardWidth = 0;\r
- nDragCardHeight = 0;\r
- \r
- CanDragCallback = 0;\r
- CanDropCallback = 0;\r
- AddCallback = 0;\r
- RemoveCallback = 0;\r
- ClickCallback = 0;\r
- DblClickCallback = 0;\r
-\r
- uDragRule = CS_DRAG_ALL;\r
- uDropRule = CS_DROP_ALL;\r
-\r
- xjustify = yjustify = xadjust = yadjust = 0;\r
-\r
- nFlashCount = 0;\r
- fFlashVisible = false;\r
- uFlashTimer = (UINT)-1;\r
-\r
- fMouseDragging = false;\r
-\r
- mxlock = CreateMutex(0, FALSE, 0);\r
-}\r
-\r
-CardRegion::~CardRegion()\r
-{\r
- CloseHandle(mxlock);\r
-}\r
-\r
-void CardRegion::SetBackColor(COLORREF cr)\r
-{\r
- crBackgnd = cr;\r
-}\r
-\r
-int CardRegion::CalcApparentCards(int realnum)\r
-{\r
- return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount;\r
-}\r
-\r
-void CardRegion::CalcApparentCards()\r
-{\r
- nNumApparentCards = CalcApparentCards(cardstack.NumCards());\r
-}\r
-\r
-\r
-void CardRegion::UpdateSize(void)\r
-{\r
- if(cardstack.NumCards() > 0)\r
- {\r
- if(xoffset > 0)\r
- width = (nNumApparentCards - 1) * xoffset + __cardwidth;\r
- else\r
- width = (nNumApparentCards - 1) * -xoffset + __cardwidth;\r
-\r
- if(yoffset > 0)\r
- height = (nNumApparentCards - 1) * yoffset + __cardheight;\r
- else\r
- height = (nNumApparentCards - 1) * -yoffset + __cardheight;\r
- }\r
- else\r
- {\r
- width = __cardwidth;\r
- height = __cardheight;\r
- }\r
-}\r
-\r
-CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset)\r
-{\r
- CardRegion *cr;\r
-\r
- if(nNumCardRegions == MAXCARDSTACKS)\r
- return FALSE;\r
-\r
- cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset);\r
- cr->SetBackColor(crBackgnd);\r
- cr->SetBackCardIdx(nBackCardIdx);\r
-\r
- Regions[nNumCardRegions++] = cr;\r
- \r
- return cr;\r
-}\r
-\r
-int CardRegion::GetOverlapRatio(int x, int y, int w, int h)\r
-{\r
- RECT me, him;\r
- RECT inter;\r
- SetRect(&him, x, y, x+w, y+h);\r
- SetRect(&me, xpos, ypos, xpos+width, ypos+height);\r
-\r
- //see if the specified rectangle overlaps us\r
- if(IntersectRect(&inter, &me, &him))\r
- {\r
- int wi = inter.right - inter.left;\r
- int hi = inter.bottom - inter.top;\r
-\r
- int overlap = wi * hi;\r
- int total = width * height;\r
-\r
- int percent = (overlap << 16) / total;\r
- return (percent * 100) >> 16;\r
- }\r
- //do not overlap\r
- else\r
- {\r
- return 0;\r
- }\r
-}\r
-\r
-bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc)\r
-{ \r
- switch(uDragType)\r
- {\r
- case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP:\r
- uDragRule = uDragType;\r
- return true;\r
-\r
- case CS_DRAG_CALLBACK:\r
- uDragRule = uDragType;\r
- CanDragCallback = proc;\r
- return true;\r
-\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc)\r
-{ \r
- switch(uDropType)\r
- {\r
- case CS_DROP_NONE: case CS_DROP_ALL: \r
- uDropRule = uDropType;\r
- return true;\r
-\r
- case CS_DROP_CALLBACK:\r
- uDropRule = uDropType;\r
- CanDropCallback = proc;\r
- return true;\r
-\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-void CardRegion::SetClickProc(pClickProc proc)\r
-{\r
- ClickCallback = proc;\r
-}\r
-\r
-void CardRegion::SetDblClickProc(pClickProc proc)\r
-{\r
- DblClickCallback = proc;\r
-}\r
-\r
-void CardRegion::SetAddCardProc(pAddProc proc)\r
-{\r
- AddCallback = proc;\r
-}\r
-\r
-void CardRegion::SetRemoveCardProc(pRemoveProc proc)\r
-{\r
- RemoveCallback = proc;\r
-}\r
-\r
-void CardRegion::Update()\r
-{\r
- CalcApparentCards();\r
- UpdateSize(); \r
- UpdateFaceDir(cardstack);\r
-}\r
-\r
-\r
-bool CardRegion::SetThreedCount(int count)\r
-{\r
- if(count < 1) \r
- {\r
- return false;\r
- }\r
- else\r
- {\r
- nThreedCount = count;\r
- return true;\r
- }\r
-}\r
-\r
-void CardRegion::SetOffsets(int x, int y)\r
-{\r
- xoffset = x;\r
- yoffset = y;\r
-}\r
-\r
-void CardRegion::SetPos(int x, int y)\r
-{\r
- xpos = x;\r
- ypos = y;\r
-}\r
-\r
-void CardRegion::Show(bool fShow)\r
-{\r
- fVisible = fShow;\r
-}\r
-\r
-bool CardRegion::IsVisible()\r
-{ \r
- return fVisible;\r
-}\r
-\r
-void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)\r
-{\r
- xjustify = xJustify;\r
- yjustify = yJustify;\r
- xadjust = xAdjust;\r
- yadjust = yAdjust;\r
-}\r
-\r
-void CardRegion::SetFaceDirection(UINT uDirType, int nOption)\r
-{\r
- switch(uDirType)\r
- {\r
- case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP:\r
- case CS_FACE_UPDOWN: case CS_FACE_ANY:\r
- uFaceDirType = uDirType;\r
- nFaceDirOption = nOption;\r
-\r
- UpdateFaceDir(cardstack);\r
-\r
- break;\r
- }\r
-}\r
-\r
-UINT CardRegion::GetFaceDirection(int *pnOption)\r
-{\r
- if(pnOption)\r
- *pnOption = nFaceDirOption;\r
-\r
- return uFaceDirType;\r
-}\r
-\r
-void CardRegion::AdjustPosition(int winwidth, int winheight)\r
-{\r
- Update(); //Update this stack's card count + size\r
-\r
- switch(xjustify)\r
- {\r
- default: case CS_XJUST_NONE: break;\r
- \r
- case CS_XJUST_CENTER: //centered\r
- xpos = (winwidth - (width & ~0x1)) / 2;\r
- xpos += xadjust;\r
-\r
- if(xoffset < 0) xpos += (width - __cardwidth);\r
- \r
- break;\r
-\r
- case CS_XJUST_RIGHT: //right-aligned\r
- xpos = winwidth - __cardwidth;//width - 20;\r
- xpos += xadjust;\r
- break;\r
- }\r
-\r
- switch(yjustify)\r
- {\r
- default: case CS_YJUST_NONE: break;\r
- \r
- case CS_YJUST_CENTER: //centered\r
- ypos = (winheight - height) / 2;\r
- ypos += yadjust;\r
- if(yoffset < 0) ypos += (height - __cardheight);\r
- break;\r
-\r
- case CS_YJUST_BOTTOM: //bottom-aligned\r
- ypos = winheight - __cardheight;//height - 20;\r
- ypos += yadjust;\r
- break;\r
- }\r
-\r
-}\r
-\r
-\r
-void CardRegion::Flash(int count, int milliseconds)\r
-{\r
- if(count <= 0) return;\r
-\r
- nFlashCount = count;\r
- fFlashVisible = false;\r
- uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0);\r
- \r
- parentWnd.Redraw();\r
-}\r
-\r
-void CardRegion::StopFlash()\r
-{\r
- if(uFlashTimer != (UINT)-1)\r
- {\r
- KillTimer((HWND)parentWnd, uFlashTimer);\r
- nFlashCount = 0;\r
- uFlashTimer = (UINT)-1;\r
- fFlashVisible = true;\r
- }\r
-}\r
-\r
-void CardRegion::DoFlash()\r
-{\r
- if(uFlashTimer != (UINT)-1)\r
- {\r
- fFlashVisible = !fFlashVisible;\r
-\r
- if(--nFlashCount == 0)\r
- {\r
- KillTimer((HWND)parentWnd, uFlashTimer);\r
- uFlashTimer = (UINT)-1;\r
- fFlashVisible = true;\r
- }\r
- \r
- parentWnd.Redraw();\r
- }\r
-}\r
-\r
-int CardRegion::Id()\r
-{\r
- return id;\r
-}\r
-\r
-void CardRegion::SetEmptyImage(UINT uImage)\r
-{\r
- switch(uImage)\r
- {\r
- case CS_EI_NONE: case CS_EI_SUNK:\r
- uEmptyImage = uImage;\r
- break;\r
-\r
- default:\r
- uEmptyImage = CS_EI_NONE;\r
- break;\r
- }\r
- \r
-}\r
-\r
-void CardRegion::SetBackCardIdx(UINT uBackIdx)\r
-{\r
- if(uBackIdx >= 52 && uBackIdx <= 68)\r
- nBackCardIdx = uBackIdx;\r
-}\r
-\r
-void CardRegion::SetCardStack(const CardStack &cs)\r
-{ \r
- //make a complete copy of the specified stack..\r
- cardstack = cs; \r
-\r
- // Update the face-direction and stack-size\r
- Update();\r
-}\r
-\r
-const CardStack & CardRegion::GetCardStack()\r
-{ \r
- //return reference to our internal stack\r
- return cardstack; \r
-}\r
-\r
-//\r
-// Update specified card-stack using THIS stack's\r
-// face direction rules!\r
-//\r
-void CardRegion::UpdateFaceDir(CardStack &cards)\r
-{\r
- int i, n, num;\r
-\r
- num = cards.NumCards();\r
-\r
- //Now apply the face direction rules..\r
- switch(uFaceDirType)\r
- {\r
- case CS_FACE_UP:\r
-\r
- for(i = 0; i < num; i++)\r
- {\r
- cards[i].SetFaceUp(true);\r
- }\r
-\r
- break;\r
-\r
- case CS_FACE_DOWN:\r
-\r
- for(i = 0; i < num; i++)\r
- {\r
- cards[i].SetFaceUp(false);\r
- }\r
-\r
- break;\r
-\r
- case CS_FACE_DOWNUP:\r
-\r
- num = cardstack.NumCards();\r
- n = min(nFaceDirOption, num);\r
-\r
- //bottom n cards..\r
- for(i = 0; i < n; i++)\r
- {\r
- cards[num - i - 1].SetFaceUp(false);\r
- }\r
-\r
- for(i = n; i < num; i++)\r
- {\r
- cards[num - i - 1].SetFaceUp(true);\r
- }\r
-\r
- break;\r
-\r
- case CS_FACE_UPDOWN:\r
-\r
- num = cardstack.NumCards();\r
- n = min(nFaceDirOption, num);\r
-\r
- for(i = 0; i < n; i++)\r
- {\r
- cards[num - i - 1].SetFaceUp(true);\r
- }\r
-\r
- for(i = n; i < num; i++)\r
- {\r
- cards[num - i - 1].SetFaceUp(false);\r
- }\r
-\r
- break;\r
-\r
- case CS_FACE_ANY: //cards can be any orientation\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate)\r
-{\r
- HDC hdc;\r
-\r
- int x, y;\r
-\r
- if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; }\r
-\r
- if(nNumCards < 0 || nNumCards > cardstack.NumCards())\r
- return false;\r
-\r
- x = xpos + xoffset * (nNumApparentCards - nNumCards);\r
- y = ypos + yoffset * (nNumApparentCards - nNumCards);\r
-\r
- oldx = x;\r
- oldy = y;\r
- \r
- dragstack = cardstack.Pop(nNumCards);\r
-\r
- //Alter the drag-stack so that it's cards are the same way up\r
- //as the destination. Use the destination's drag-rules\r
- //instead of this ones!!\r
- CardStack temp;\r
- temp.Push(pDestStack->GetCardStack());\r
- temp.Push(dragstack);\r
-\r
- pDestStack->UpdateFaceDir(temp);\r
-\r
- dragstack = temp.Pop(nNumCards);\r
-\r
- if(fAnimate)\r
- {\r
- iNumDragCards = nNumCards;\r
- PrepareDragBitmaps(nNumCards);\r
- }\r
-\r
- Update(); //Update this stack's size+card count\r
-\r
- if(fAnimate)\r
- {\r
- hdc = GetDC((HWND)parentWnd);\r
-\r
- ZoomCard(hdc, x, y, pDestStack);\r
- \r
- ReleaseDC((HWND)parentWnd, hdc);\r
- ReleaseDragBitmaps();\r
- }\r
-\r
- // Get a copy of the cardstack\r
- CardStack cs = pDestStack->GetCardStack();\r
- cs.Push(dragstack);\r
- \r
- pDestStack->SetCardStack(cs);\r
- \r
- //cs = pDestStack->GetCardStack();\r
- //pDestStack->Update();\r
- //pDestStack->UpdateFaceDir(cs);\r
-\r
- RedrawIfNotDim(pDestStack, false);\r
-\r
- //forcedfacedir = -1;\r
- return true;\r
-}\r
-\r
-//\r
-// Simple wrappers\r
-//\r
-int CardRegion::NumCards() const\r
-{\r
- if(fMouseDragging)\r
- return cardstack.NumCards() + dragstack.NumCards();\r
- else\r
- return cardstack.NumCards(); \r
-}\r
-\r
-bool CardRegion::Lock()\r
-{\r
- DWORD dw = WaitForSingleObject(mxlock, 0);\r
-\r
- if(dw == WAIT_OBJECT_0)\r
- {\r
- //TRACE("LockStack succeeded\n");\r
- return true; \r
- }\r
- else\r
- {\r
- //TRACE("LockStack failed\n");\r
- return false;\r
- }\r
- return false;\r
-}\r
-\r
-bool CardRegion::UnLock()\r
-{\r
- if(ReleaseMutex(mxlock))\r
- {\r
- //TRACE("Unlocking stack\n");\r
- return true;\r
- }\r
- else\r
- {\r
- //TRACE("Unlocking stack failed\n"); \r
- return false;\r
- }\r
-}\r
-\r
-bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num)\r
-{\r
- //search the stack for the specified card value...\r
- while(num--)\r
- {\r
- for(int i = 0; i < cardstack.NumCards(); i++)\r
- {\r
- if(cardstack[i].HiVal() == value)\r
- {\r
- //swap the card with one at top pos...\r
- Card card = cardstack.RemoveCard(i);\r
- cardstack.Push(card);\r
-\r
- Redraw();\r
-\r
- MoveCard(pDestStack, 1, true);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- return true;\r
-}\r
-\r
-//\r
-// Redraw the current stack if it has a different\r
-// layout than the comparison stack.\r
-//\r
-void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw)\r
-{\r
- //\r
- //\r
- //\r
- if( pCompare->xoffset != xoffset || \r
- pCompare->yoffset != yoffset || \r
- pCompare->nThreedCount != nThreedCount ||\r
- pCompare->uFaceDirType != uFaceDirType ||\r
- pCompare->uFaceDirType != CS_FACE_ANY\r
- )\r
- {\r
- if(fFullRedraw)\r
- parentWnd.Redraw();\r
- else\r
- pCompare->Redraw();\r
- }\r
- \r
-}\r
-\r
-//\r
-// SimulateDrag mimicks the complete drag+drop process.\r
-// It basically just a MoveCard(..), but it calls the\r
-// event callbacks as well.\r
-//\r
-bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate)\r
-{\r
- if(pDestStack == 0)\r
- return false;\r
-\r
- if(CanDragCards(iNumDragCards) != false)\r
- {\r
- //make a list of the cards that would be in the drag list\r
- CardStack tempstack = cardstack.Top(iNumDragCards);\r
-\r
- if(pDestStack->CanDropCards(tempstack)) \r
- {\r
- MoveCard(pDestStack, iNumDragCards, fAnimate); \r
- \r
- if(RemoveCallback)\r
- RemoveCallback(*this, iNumDragCards);\r
-\r
- if(pDestStack->AddCallback)\r
- pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);\r
- \r
- RedrawIfNotDim(pDestStack, true);\r
- } \r
-\r
- }\r
-\r
- return true;\r
-}\r
+//
+// 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)
+: id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible)
+{
+ 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 = (UINT)-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 != (UINT)-1)
+ {
+ KillTimer((HWND)parentWnd, uFlashTimer);
+ nFlashCount = 0;
+ uFlashTimer = (UINT)-1;
+ fFlashVisible = true;
+ }
+}
+
+void CardRegion::DoFlash()
+{
+ if(uFlashTimer != (UINT)-1)
+ {
+ fFlashVisible = !fFlashVisible;
+
+ if(--nFlashCount == 0)
+ {
+ KillTimer((HWND)parentWnd, uFlashTimer);
+ uFlashTimer = (UINT)-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;
+}
-#ifndef CARDREGION_INCLUDED\r
-#define CARDREGION_INCLUDED\r
-\r
-#include "globals.h"\r
-#include "cardstack.h"\r
-#include "cardlib.h"\r
-\r
-class CardWindow;\r
-\r
-//\r
-// This class defines a physical card-stack,\r
-// which draws the cards, supports\r
-//\r
-\r
-class CardRegion\r
-{\r
- friend class CardWindow;\r
- friend class CardStack;\r
-\r
- //\r
- // Constructor is PRIVATE - only\r
- // a CardWindow can create cardstacks!\r
- //\r
- CardRegion(CardWindow &parent, int id, bool fVisible, \r
- int x, int y, int xOffset, int yOffset);\r
-\r
- ~CardRegion();\r
-\r
-public:\r
-\r
- void SetBackColor(COLORREF cr);\r
- \r
- void SetCardStack(const CardStack &cs);\r
- const CardStack & GetCardStack();\r
-\r
- //\r
- // Event-callback support\r
- //\r
- bool SetDragRule(UINT uDragType, pCanDragProc proc = 0);\r
- bool SetDropRule(UINT uDropType, pCanDropProc proc = 0);\r
- \r
- void SetClickProc (pClickProc proc);\r
- void SetDblClickProc (pClickProc proc);\r
-\r
- void SetAddCardProc (pAddProc proc);\r
- void SetRemoveCardProc (pRemoveProc proc);\r
-\r
- //\r
- // Physical attribute support\r
- //\r
- bool SetThreedCount (int count);\r
- void SetOffsets (int x, int y);\r
- void SetPos (int x, int y);\r
- void Show (bool fShow);\r
- bool IsVisible ();\r
-\r
- void SetEmptyImage (UINT uImage);\r
- void SetBackCardIdx (UINT uBackIdx);\r
- void SetPlacement (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust);\r
-\r
- void Update();\r
- void Redraw();\r
-\r
- void SetFaceDirection(UINT uDirType, int nOption);\r
- UINT GetFaceDirection(int *pnOption);\r
-\r
- void Flash(int count, int timeout);\r
- void StopFlash();\r
-\r
- int Id();\r
-\r
- CardWindow &GetCardWindow() { return parentWnd; }\r
-\r
- bool PlayCard(CardRegion *pDestStack, int value, int num);\r
- bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate);\r
- bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate);\r
-\r
- bool Lock();\r
- bool UnLock();\r
-\r
- //\r
- // Common wrappers for the CardStack object\r
- //\r
- int NumCards() const;\r
- void NewDeck() { cardstack.NewDeck(); }\r
- void Shuffle() { cardstack.Shuffle(); }\r
- void Clear() { cardstack.Clear(); }\r
-\r
- void Reverse() { cardstack.Reverse(); }\r
- \r
- void Push(const Card card) { cardstack.Push(card); }\r
- void Push(const CardStack &cs) { cardstack.Push(cs); }\r
-\r
- Card Pop() { return cardstack.Pop(); }\r
- CardStack Pop(int items) { return cardstack.Pop(items); }\r
-\r
- Card Top() { return cardstack.Top(); }\r
- CardStack Top(int items) { return cardstack.Top(items); }\r
-\r
-\r
-private:\r
-\r
- void DoFlash();\r
- void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw);\r
-\r
- void UpdateFaceDir(CardStack &cards);\r
- void Clip(HDC hdc);\r
- void Render(HDC hdc);\r
- int GetOverlapRatio(int x, int y, int width, int height);\r
-\r
- void MoveDragCardTo(HDC hdc, int x, int y);\r
- void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest);\r
-\r
- void RenderBottomMost(HDC hdc, int minustopmost = 0);\r
- void PrepareDragBitmaps(int numtodrag);\r
- void PrepareDragBitmapsThreed(int numtodrag);\r
- void ReleaseDragBitmaps(void);\r
-\r
- bool CanDragCards(int iNumCards);\r
- bool CanDropCards(CardStack &cards);\r
- \r
- void CalcApparentCards();\r
- int CalcApparentCards(int realnum);\r
-\r
- void UpdateSize();\r
- void AdjustPosition(int winwidth, int winheight);\r
-\r
- bool IsPointInStack(int x, int y);\r
-\r
- int GetNumDragCards(int x, int y);\r
- bool OnLButtonDown(int x, int y);\r
- bool OnLButtonDblClk(int x, int y);\r
- bool OnMouseMove(int x, int y);\r
- bool OnLButtonUp(int x, int y);\r
-\r
- \r
- //\r
- // Private data members\r
- //\r
-\r
- int id;\r
- \r
- CardWindow &parentWnd;\r
- \r
- CardStack cardstack; //cards in this stack\r
- CardStack dragstack; //cards which we might be dragging\r
-\r
- bool fMouseDragging;\r
-\r
- int xpos; //coordinates of stack\r
- int ypos;\r
-\r
- int xoffset; //direction that cards take\r
- int yoffset;\r
-\r
- int width; //stack-size of all cards\r
- int height;\r
-\r
- //\r
- // justify / placement vars\r
- int xjustify;\r
- int yjustify;\r
- int xadjust;\r
- int yadjust;\r
-\r
- //\r
- // Used for mouse-dragging / moving cards\r
- //\r
- int iNumDragCards;\r
- int mousexoffset; \r
- int mouseyoffset;\r
- int oldx;\r
- int oldy;\r
- \r
- int nDragCardWidth;\r
- int nDragCardHeight;\r
- \r
- HDC hdcBackGnd;\r
- HBITMAP hbmBackGnd;\r
- HDC hdcDragCard;\r
- HBITMAP hbmDragCard;\r
-\r
- int nNumApparentCards;\r
- int nThreedCount;\r
- bool fVisible;\r
- \r
- int nFlashCount;\r
- bool fFlashVisible;\r
- UINT uFlashTimer;\r
-\r
- COLORREF crBackgnd;\r
-\r
- UINT uEmptyImage;\r
- UINT uFaceDirType;\r
- int nFaceDirOption;\r
- int nBackCardIdx;\r
-\r
- UINT uDragRule;\r
- UINT uDropRule;\r
- \r
- //\r
- // Stack callback support\r
- // \r
- pCanDragProc CanDragCallback;\r
- pCanDropProc CanDropCallback;\r
- pClickProc ClickCallback;\r
- pClickProc DblClickCallback;\r
- pAddProc AddCallback;\r
- pRemoveProc RemoveCallback;\r
-\r
- //locking mechanism to prevent user dragging etc\r
- HANDLE mxlock; \r
-};\r
-\r
-#endif\r
-\r
+#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 xpos; //coordinates of stack
+ int ypos;
+
+ int xoffset; //direction that cards take
+ int yoffset;
+
+ 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
+
-//\r
-// CardLib - CardRegion drawing support\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include "cardlib.h"\r
-#include "cardregion.h"\r
-#include "cardcolor.h"\r
-\r
-HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette);\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
-void CardBlt(HDC hdc, int x, int y, int nCardNum);\r
-void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);\r
-\r
-//\r
-// Draw specified card at position x, y\r
-// xoff - source offset from left of card\r
-// yoff - source offset from top of card\r
-// width - width to draw\r
-// height - height to draw\r
-//\r
-void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height)\r
-{\r
- int sx = nCardNum * __cardwidth;\r
- int sy = 0;\r
- int width = __cardwidth;\r
- int height = __cardheight;\r
-\r
- //draw main center band\r
- BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY);\r
-\r
- //draw the two bits to the left\r
- BitBlt(hdc, x, y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY);\r
- BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY);\r
-\r
- //draw the two bits to the right\r
- BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY);\r
- BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY);\r
-}\r
-\r
-//\r
-// Draw a shape this this:\r
-//\r
-// ++++++++++++\r
-// ++++++++++++++\r
-// ++ ++\r
-//\r
-void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips)\r
-{\r
- int sx = nCardNum * __cardwidth;\r
- int sy = 0;\r
- int one = 1;\r
- int two = 2;\r
- BOOL tips = fDrawTips ? FALSE : TRUE;\r
-\r
- if(height == 0) return;\r
-\r
- if(height < 0)\r
- {\r
- sy = sy + __cardheight;\r
- y -= height;\r
- one = -one;\r
- two = -two;\r
- }\r
-\r
- // draw the main vertical band\r
- //\r
- BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY);\r
-\r
- //if(height <= 1) return;\r
-\r
- // draw the "lips" at the left and right\r
- BitBlt(hdc, x+1, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1, sy+one, SRCCOPY);\r
- BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY);\r
-\r
- //if(height <= 2) return;\r
-\r
- // draw the outer-most lips\r
- BitBlt(hdc, x, y+two, 1, height-two*tips, __hdcCardBitmaps, sx, sy+two, SRCCOPY);\r
- BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY); \r
-}\r
-\r
-//\r
-// Draw a shape like this:\r
-//\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-// +++\r
-//\r
-//\r
-void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips)\r
-{\r
- int sx = nCardNum * __cardwidth;\r
- int sy = 0;\r
- int one = 1;\r
- int two = 2;\r
- BOOL tips = fDrawTips ? FALSE : TRUE;\r
-\r
- if(width == 0) return;\r
- \r
-\r
- if(width < 0)\r
- {\r
- sx = sx + __cardwidth;\r
- x -= width;\r
- one = -1;\r
- two = -2;\r
- }\r
-\r
- // draw the main vertical band\r
- //\r
- BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY);\r
-\r
- //if(width <= 1) return;\r
-\r
- // draw the "lips" at the top and bottom\r
- BitBlt(hdc, x+one, y+1, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1, SRCCOPY);\r
- BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY);\r
-\r
- //if(width <= 2) return;\r
-\r
- // draw the outer-most lips\r
- BitBlt(hdc, x+two, y, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy, SRCCOPY);\r
- BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY);\r
-}\r
-\r
-//\r
-// xdir - <0 or >0\r
-// ydir - <0 or >0\r
-//\r
-void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir)\r
-{\r
- int sx = cardval * __cardwidth;\r
- int sy = 0;\r
-\r
- HDC hdcSource = __hdcCardBitmaps;\r
-\r
- if(xdir < 0) \r
- {\r
- x += __cardwidth + xdir - 1;\r
- sx += __cardwidth + xdir - 1;\r
- }\r
- else\r
- {\r
- x += xdir;\r
- sx += xdir;\r
- }\r
-\r
- if(ydir < 0) \r
- {\r
- y += __cardheight + ydir - 1;\r
- sy += __cardheight + ydir - 1;\r
- }\r
- else\r
- {\r
- y += ydir;\r
- sy += ydir;\r
- }\r
-\r
- //convert x,y directions to -1, +1\r
- xdir = xdir < 0 ? -1 : 1;\r
- ydir = ydir < 0 ? -1 : 1;\r
-\r
- SetPixel(hdc, x+xdir, y , GetPixel(hdcSource, sx+xdir, sy));\r
- SetPixel(hdc, x, y, GetPixel(hdcSource, sx, sy));\r
- SetPixel(hdc, x, y+ydir, GetPixel(hdcSource, sx, sy+ydir));\r
-\r
-}\r
-\r
-//\r
-// Draw a card (i.e. miss out the corners)\r
-//\r
-void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height)\r
-{\r
- //draw main center band\r
- BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY);\r
-\r
- //draw the two bits to the left\r
- BitBlt(hdc, x, y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY);\r
- BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY);\r
-\r
- //draw the two bits to the right\r
- BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY);\r
- BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY);\r
-}\r
-\r
-//\r
-// Clip a card SHAPE - basically any rectangle\r
-// with rounded corners\r
-//\r
-int ClipCard(HDC hdc, int x, int y, int width, int height)\r
-{\r
- ExcludeClipRect(hdc, x+2, y, x+2+width-4, y+ height);\r
- ExcludeClipRect(hdc, x, y+2, x+1, y+2+height-4);\r
- ExcludeClipRect(hdc, x+1, y+1, x+2, y+1+height-2);\r
- ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2);\r
- ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4);\r
- return 0;\r
-}\r
-\r
-void CardRegion::Clip(HDC hdc)\r
-{\r
- int numtoclip;\r
-\r
- if(fVisible == false) \r
- return;\r
-\r
- Update(); //Update this stack's size+card count\r
- numtoclip = nNumApparentCards;\r
-\r
- //if we are making this stack flash on/off, then only \r
- //clip the stack for drawing if the flash is in its ON state\r
- if(nFlashCount != 0)\r
- {\r
- if(fFlashVisible == FALSE)\r
- numtoclip = 0;\r
- }\r
-\r
- //if offset along a diagonal\r
- if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0)\r
- {\r
- for(int j = 0; j < numtoclip; j ++)\r
- { \r
- ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight);\r
- } \r
- }\r
- //otherwise if just offset along a horizontal/vertical axis\r
- else\r
- {\r
- if(yoffset < 0 && numtoclip > 0)\r
- {\r
- ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height);\r
- }\r
- else if(xoffset < 0 && numtoclip > 0)\r
- {\r
- ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height);\r
- }\r
- else\r
- {\r
- ClipCard(hdc, xpos, ypos, width, height);\r
- }\r
- }\r
-\r
-}\r
-\r
-void CardRegion::Render(HDC hdc)\r
-{\r
- int cardnum = 0;\r
- int numtodraw;\r
- BOOL fDrawTips;\r
- \r
- Update(); //Update this stack's card count + size\r
-\r
- numtodraw = nNumApparentCards;\r
-\r
- if(nFlashCount != 0)\r
- {\r
- if(fFlashVisible == false)\r
- numtodraw = 0;\r
- }\r
-\r
- if(fVisible == 0) return;\r
- \r
- cardnum = cardstack.NumCards() - numtodraw;\r
- int counter;\r
-\r
- for(counter = 0; counter < numtodraw; counter++)\r
- {\r
- int cardval;\r
- \r
- int x = xoffset * counter + xpos;\r
- int y = yoffset * counter + ypos;\r
-\r
- //if about to draw last card, then actually draw the top card\r
- if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1;\r
- \r
- Card card = cardstack.cardlist[cardnum];\r
- cardval = card.Idx();\r
- \r
- if(card.FaceDown())\r
- cardval = nBackCardIdx; //card-back\r
- \r
- //only draw the visible part of the card\r
- if(counter < numtodraw - 1)\r
- {\r
- if(yoffset != 0 && xoffset != 0)\r
- fDrawTips = FALSE;\r
- else\r
- fDrawTips = TRUE;\r
-\r
- if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1)\r
- fDrawTips = TRUE;\r
-\r
- //draw horizontal strips\r
- if(yoffset > 0) \r
- {\r
- DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips);\r
- }\r
- else if(yoffset < 0)\r
- {\r
- DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips);\r
- }\r
-\r
- //draw some vertical bars\r
- if(xoffset > 0)\r
- {\r
- DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips);\r
- }\r
- else if(xoffset < 0)\r
- {\r
- DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips);\r
- }\r
-\r
- if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE)\r
- {\r
- //if we didn't draw any tips, then this is a 2-dim stack\r
- //(i.e, it goes at a diagonal).\r
- //in this case, we need to fill in the small triangle in\r
- //each corner!\r
- DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset);\r
- }\r
- }\r
- //if the top card, draw the whole thing\r
- else\r
- {\r
- CardBlt(hdc, x, y, cardval);\r
- }\r
-\r
- cardnum ++;\r
-\r
- } //end of index\r
- \r
- if(counter == 0) //if the cardstack is empty, then draw it that way\r
- {\r
- int x = xpos;\r
- int y = ypos;\r
- \r
- switch(uEmptyImage)\r
- {\r
- default: case CS_EI_NONE:\r
- //this wipes the RECT variable, so watch out!\r
- //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);\r
- //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));\r
- parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y);\r
- break;\r
- \r
- case CS_EI_SUNK: //case CS_EI_CIRC: case CS_EI_X:\r
- DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight);\r
- break;\r
- }\r
- \r
- }\r
-\r
- return;\r
-}\r
-\r
-int calc_offset(int offset, int numcards, int numtodrag, int realvisible)\r
-{\r
- if(offset >= 0)\r
- return -offset * numcards;\r
- else\r
- return -offset * (numtodrag) + \r
- -offset * (realvisible - 1);\r
-}\r
-\r
-void CardRegion::PrepareDragBitmaps(int numtodrag)\r
-{\r
- RECT rect;\r
- HDC hdc;\r
- int icard;\r
- int numcards = cardstack.NumCards();\r
- int xoff, yoff;\r
-\r
- if(nThreedCount > 1)\r
- {\r
- PrepareDragBitmapsThreed(numtodrag);\r
- return;\r
- }\r
-\r
- //work out how big the bitmaps need to be\r
- nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;\r
- nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;\r
-\r
- //Create bitmap for the back-buffer\r
- hdc = GetDC(NULL);\r
- hdcBackGnd = CreateCompatibleDC(hdc);\r
- hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
- SelectObject(hdcBackGnd, hbmBackGnd);\r
-\r
- //Create bitmap for the drag-image\r
- hdcDragCard = CreateCompatibleDC(hdc);\r
- hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
- SelectObject(hdcDragCard, hbmDragCard);\r
- ReleaseDC(NULL, hdc);\r
-\r
- UseNicePalette(hdcBackGnd, __hPalette);\r
- UseNicePalette(hdcDragCard, __hPalette);\r
-\r
- int realvisible = numcards / nThreedCount;\r
-\r
- //if(numcards > 0 && realvisible == 0) realvisible = 1;\r
- int iwhichcard = numcards - 1;\r
- if(nThreedCount == 1) iwhichcard = 0;\r
-\r
- //grab the first bit of background so we can prep the back buffer; do this by\r
- //rendering the card stack (minus the card we are dragging) to the temporary\r
- //background buffer, so it appears if we have lifted the card from the stack\r
- //PaintRect(hdcBackGnd, &rect, crBackgnd);\r
- SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);\r
- \r
- xoff = calc_offset(xoffset, numcards, numtodrag, realvisible);\r
- yoff = calc_offset(yoffset, numcards, numtodrag, realvisible);\r
- \r
- parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff, ypos - yoff);\r
-\r
- //\r
- // Render the cardstack into the back-buffer. The stack\r
- // has already had the dragcards removed, so just draw\r
- // what is left\r
- //\r
- for(icard = 0; icard < realvisible; icard++)\r
- {\r
- Card card = cardstack.cardlist[iwhichcard];\r
- int nCardVal;\r
- \r
- nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
-\r
- xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);\r
- yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);\r
-\r
- CardBlt(hdcBackGnd, xoff, yoff, nCardVal);\r
- iwhichcard++;\r
- }\r
- \r
- //\r
- // If there are no cards under this one, just draw the place holder\r
- //\r
- if(numcards == 0) \r
- {\r
- int xoff = 0, yoff = 0;\r
-\r
- if(xoffset < 0) xoff = nDragCardWidth - __cardwidth;\r
- if(yoffset < 0) yoff = nDragCardHeight - __cardheight;\r
-\r
- switch(uEmptyImage)\r
- {\r
- case CS_EI_NONE:\r
- //No need to draw anything: We already cleared the\r
- //back-buffer before the main loop..\r
-\r
- //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);\r
- //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));\r
- //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);\r
- break;\r
-\r
- case CS_EI_SUNK:\r
- DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight);\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // now render the drag-cards into the dragcard image\r
- //\r
- PaintRect(hdcDragCard, &rect, crBackgnd);\r
-\r
- for(icard = 0; icard < numtodrag; icard++)\r
- {\r
- int nCardVal;\r
-\r
- if(xoffset >= 0) xoff = xoffset * icard;\r
- else xoff = -xoffset * (numtodrag - icard - 1);\r
- \r
- if(yoffset >= 0) yoff = yoffset * icard;\r
- else yoff = -yoffset * (numtodrag - icard - 1);\r
-\r
- Card card = dragstack.cardlist[icard];\r
- \r
- nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
-\r
- CardBlt(hdcDragCard, xoff, yoff, nCardVal);\r
- }\r
-}\r
-\r
-void CardRegion::PrepareDragBitmapsThreed(int numtodrag)\r
-{\r
- RECT rect;\r
- HDC hdc;\r
- int icard;\r
- int numunder = 0;\r
- int iwhichcard;\r
-\r
- int numcards = cardstack.NumCards();\r
-\r
- //work out how big the bitmaps need to be\r
- nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth;\r
- nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight;\r
-\r
- //Create bitmap for the back-buffer\r
- hdc = GetDC(NULL);\r
- hdcBackGnd = CreateCompatibleDC(hdc);\r
- hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
- SelectObject(hdcBackGnd, hbmBackGnd);\r
-\r
- //create bitmap for the drag-image\r
- hdcDragCard = CreateCompatibleDC(hdc);\r
- hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight);\r
- SelectObject(hdcDragCard, hbmDragCard);\r
- ReleaseDC(NULL, hdc);\r
-\r
- UseNicePalette(hdcBackGnd, __hPalette);\r
- UseNicePalette(hdcDragCard, __hPalette);\r
-\r
- //grab the first bit of background so we can prep the back buffer; do this by\r
- //rendering the card stack (minus the card we are dragging) to the temporary\r
- //background buffer, so it appears if we have lifted the card from the stack\r
- //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);\r
- //--PaintRect(hdcBackGnd, &rect, crBackgnd);\r
-\r
- int threedadjust = numcards % nThreedCount == 0;\r
- \r
- numunder = CalcApparentCards(numcards);\r
- iwhichcard = (numcards+numtodrag) - numunder - 1;\r
- if(nThreedCount == 1) iwhichcard = 0;\r
- \r
- int xoff = calc_offset(xoffset, numunder, numtodrag, numunder);\r
- int yoff = calc_offset(yoffset, numunder, numtodrag, numunder);\r
-\r
- parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff);\r
-\r
- //\r
- // Render the cardstack into the back-buffer. The stack\r
- // has already had the dragcards removed, so just draw\r
- // what is left\r
- //\r
- for(icard = 0; icard < numunder; icard++)\r
- {\r
- Card card = cardstack.cardlist[iwhichcard];\r
- int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
-\r
- CardBlt(hdcBackGnd, \r
- xoffset * icard - xoffset*(numunder-numtodrag+threedadjust),\r
- yoffset * icard - yoffset*(numunder-numtodrag+threedadjust),\r
- nCardVal);\r
-\r
- iwhichcard++;\r
- }\r
- \r
- //\r
- // If there are no cards under this one, just draw the place holder\r
- //\r
- if(numcards == 0) \r
- {\r
- switch(uEmptyImage)\r
- {\r
- case CS_EI_NONE:\r
- //no need! we've already cleared the whole\r
- //back-buffer before the main loop!\r
- //SetRect(&rect, 0, 0, __cardwidth, __cardheight);\r
- //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));\r
- break;\r
-\r
- case CS_EI_SUNK:\r
- DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight);\r
- break;\r
- \r
- }\r
- }\r
-\r
- //\r
- // now render the drag-cards into the dragcard image\r
- //\r
- PaintRect(hdcDragCard, &rect, crBackgnd);\r
- \r
- for(icard = 0; icard < numtodrag; icard++)\r
- {\r
- Card card = dragstack.cardlist[icard];\r
- int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx;\r
-\r
- CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal);\r
- }\r
-}\r
-\r
-void CardRegion::ReleaseDragBitmaps(void)\r
-{\r
- //SelectObject(hdcBackGnd, hOld1);\r
- DeleteObject(hbmBackGnd);\r
- DeleteDC(hdcBackGnd);\r
-\r
- //SelectObject(hdcDragCard, hOld2);\r
- DeleteObject(hbmDragCard);\r
- DeleteDC(hdcDragCard);\r
-}\r
-\r
-\r
-void CardRegion::Redraw()\r
-{\r
- HDC hdc = GetDC((HWND)parentWnd);\r
-\r
- Update();\r
- Render(hdc);\r
-\r
- ReleaseDC((HWND)parentWnd, hdc);\r
-}\r
+//
+// 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);
+}
-//\r
-// CardLib - CardRegion mouse-related stuff\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include <math.h>\r
-#include <stdio.h>\r
-\r
-#include "cardlib.h"\r
-#include "cardwindow.h"\r
-#include "cardregion.h"\r
-\r
-#if 1\r
-#define TRACE(s)\r
-#else\r
-#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)\r
-#endif\r
-\r
-double __CARDZOOMSPEED = 32;\r
-\r
-int ClipCard(HDC hdc, int x, int y, int width, int height);\r
-void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);\r
-\r
-#ifdef _DEBUG\r
-\r
-static pDebugClickProc DebugStackClickProc = 0;\r
-\r
-void CardLib_SetStackClickProc(pDebugClickProc proc)\r
-{\r
- DebugStackClickProc = proc;\r
-}\r
-\r
-#endif\r
-\r
-CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)\r
-{\r
- int maxoverlap = 0;\r
- int maxoverlapidx = -1;\r
-\r
- //find the stack which is most covered by the dropped\r
- //cards. Only include those which allow drops.\r
- //\r
- for(int i = 0; i < nNumCardRegions; i++)\r
- {\r
- int percent = Regions[i]->GetOverlapRatio(x, y, w, h);\r
-\r
- //if this stack has the biggest coverage yet\r
- if(percent > maxoverlap && Regions[i]->IsVisible())\r
- {\r
- maxoverlap = percent;\r
- maxoverlapidx = i;\r
- }\r
- }\r
- \r
- //if we found a stack to drop onto\r
- if(maxoverlapidx != -1)\r
- {\r
- return Regions[maxoverlapidx];\r
- }\r
- else\r
- {\r
- return 0;\r
- }\r
-}\r
-\r
-bool CardRegion::IsPointInStack(int x, int y)\r
-{\r
- int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;\r
- int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;\r
- \r
- if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)\r
- return true;\r
- else\r
- return false;\r
-}\r
-\r
-int CardRegion::GetNumDragCards(int x, int y)\r
-{\r
- int cardindex = 0; //index from stack start\r
- int maxidx;\r
-\r
- //make x,y relative to the stack's upper left corner\r
- x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);\r
- y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);\r
- \r
- //if stack is empty, cannot drag any cards from it\r
- if(cardstack.NumCards() <= 0)\r
- return 0;\r
-\r
- //see which card in the stack has been clicked on\r
- //top-bottom ordering\r
- if(yoffset > 0)\r
- {\r
- if(y < height - __cardheight)\r
- cardindex = y / yoffset;\r
- else\r
- cardindex = cardstack.NumCards() - 1;\r
- }\r
- else if(yoffset < 0)\r
- {\r
- if(y < __cardheight)\r
- cardindex = cardstack.NumCards() - 1;\r
- else\r
- cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;\r
- }\r
- else //yoffset == 0\r
- {\r
- cardindex = cardstack.NumCards() - 1;\r
- }\r
-\r
- maxidx = cardindex;\r
-\r
- //if left-right\r
- if(xoffset > 0)\r
- {\r
- if(x < width - __cardwidth)\r
- cardindex = x / xoffset;\r
- else\r
- cardindex = cardstack.NumCards() - 1;\r
- }\r
- else if(xoffset < 0)\r
- {\r
- if(x < __cardwidth)\r
- cardindex = cardstack.NumCards() - 1;\r
- else\r
- cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;\r
- }\r
- else\r
- {\r
- cardindex = cardstack.NumCards() - 1;\r
- }\r
-\r
- if(cardindex > maxidx) cardindex = maxidx;\r
-\r
- if(cardindex > cardstack.NumCards())\r
- cardindex = 1;\r
-\r
- //if are trying to drag too many cards at once\r
- return cardstack.NumCards() - cardindex;\r
-}\r
-\r
-bool CardRegion::CanDragCards(int iNumCards)\r
-{\r
- if(iNumCards <= 0) return false;\r
- if(nThreedCount > 1 && iNumCards > 1) return false;\r
-\r
- if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
- {\r
-// TRACE("Failed to gain access to card stack\n");\r
- return false;\r
- }\r
-\r
- ReleaseMutex(mxlock);\r
-\r
- switch(uDragRule)\r
- {\r
- case CS_DRAG_ALL:\r
- return true;\r
- \r
- case CS_DRAG_TOP:\r
-\r
- if(iNumCards == 1)\r
- return true;\r
- else\r
- return false;\r
- \r
- case CS_DRAG_NONE:\r
- return false;\r
- \r
- case CS_DRAG_CALLBACK:\r
- \r
- if(CanDragCallback)\r
- {\r
- return CanDragCallback(*this, iNumCards);\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
- \r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-bool CardRegion::CanDropCards(CardStack &cards)\r
-{\r
- if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)\r
- {\r
- return false;\r
- }\r
-\r
- ReleaseMutex(mxlock);\r
-\r
- switch(uDropRule)\r
- {\r
- case CS_DROP_ALL:\r
- return true;\r
-\r
- case CS_DROP_NONE:\r
- return false;\r
-\r
- case CS_DROP_CALLBACK:\r
- \r
- if(CanDropCallback)\r
- {\r
- return CanDropCallback(*this, cards);\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
-\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-bool CardRegion::OnLButtonDblClk(int x, int y)\r
-{\r
- iNumDragCards = GetNumDragCards(x, y); \r
-\r
- if(DblClickCallback)\r
- DblClickCallback(*this, iNumDragCards);\r
-\r
- return true;\r
-}\r
-\r
-bool CardRegion::OnLButtonDown(int x, int y)\r
-{\r
- iNumDragCards = GetNumDragCards(x, y); \r
-\r
-#ifdef _DEBUG\r
- if(DebugStackClickProc)\r
- {\r
- if(!DebugStackClickProc(*this))\r
- return false;\r
- }\r
-#endif\r
-\r
- if(ClickCallback)\r
- ClickCallback(*this, iNumDragCards);\r
-\r
- if(CanDragCards(iNumDragCards) != false)\r
- {\r
-\r
- //offset of the mouse cursor relative to the top-left corner\r
- //of the cards that are being dragged\r
- mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);\r
- mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);\r
- \r
- if(xoffset < 0)\r
- mousexoffset += -xoffset * (iNumDragCards - 1);\r
-\r
- if(yoffset < 0)\r
- mouseyoffset += -yoffset * (iNumDragCards - 1);\r
- \r
- //remove the cards from the source stack\r
- dragstack = cardstack.Pop(iNumDragCards);\r
-\r
- //prepare the back buffer, and the drag image\r
- PrepareDragBitmaps(iNumDragCards);\r
-\r
- oldx = x - mousexoffset;\r
- oldy = y - mouseyoffset;\r
- \r
- Update(); //Update this stack's card count + size\r
-\r
- SetCapture((HWND)parentWnd);\r
-\r
- //set AFTER settings the dragstack...\r
- fMouseDragging = true;\r
-\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool CardRegion::OnLButtonUp(int x, int y)\r
-{\r
- CardRegion *pDestStack = 0;\r
- HDC hdc;\r
- int dropstackid = CS_DROPZONE_NODROP;\r
- \r
- RECT dragrect;\r
- DropZone *dropzone;\r
-\r
- fMouseDragging = false;\r
-\r
- //first of all, see if any drop zones have been registered\r
- SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);\r
-\r
- dropzone = parentWnd.GetDropZoneFromRect(&dragrect);\r
-\r
- if(dropzone)\r
- {\r
- dropstackid = dropzone->DropCards(dragstack);\r
- \r
- if(dropstackid != CS_DROPZONE_NODROP)\r
- pDestStack = parentWnd.CardRegionFromId(dropstackid);\r
- else\r
- pDestStack = 0;\r
- }\r
- else\r
- {\r
- pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);\r
- }\r
- \r
- // If have found a stack to drop onto\r
- //\r
- TRACE ( "can I drop card?\n" );\r
- if(pDestStack && pDestStack->CanDropCards(dragstack)) \r
- {\r
- TRACE ( "yes, dropping card\n" );\r
- hdc = GetDC((HWND)parentWnd);\r
- // UseNicePalette(hdc);\r
- ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack);\r
- ReleaseDC((HWND)parentWnd, hdc);\r
- \r
- //\r
- //add the cards to the destination stack\r
- //\r
- CardStack temp = pDestStack->GetCardStack();\r
- temp.Push(dragstack);\r
- \r
- pDestStack->SetCardStack(temp);\r
-// pDestStack->Update(); //Update this stack's card count + size\r
-// pDestStack->UpdateFaceDir(temp);\r
- \r
- // Call the remove callback on THIS stack, if one is specified\r
- //\r
- if(RemoveCallback)\r
- RemoveCallback(*this, iNumDragCards);\r
-\r
- // Call the add callback, if one is specified\r
- //\r
- if(pDestStack->AddCallback)\r
- pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);\r
- \r
- RedrawIfNotDim(pDestStack, true);\r
- TRACE ( "done dropping card\n" );\r
- }\r
-\r
- //\r
- // Otherwise, let the cards snap back onto this stack\r
- //\r
- else\r
- {\r
- TRACE ( "no, putting card back\n" );\r
- hdc = GetDC((HWND)parentWnd);\r
- TRACE ( "calling ZoomCard()\n" );\r
- ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);\r
- TRACE ( "cardstack += dragstack\n" );\r
- cardstack += dragstack;\r
- TRACE ( "calling ReleaseDC()\n" );\r
- ReleaseDC((HWND)parentWnd, hdc);\r
-\r
- TRACE ( "calling Update()\n" );\r
- Update(); //Update this stack's card count + size\r
- TRACE ( "done putting card back\n" );\r
- }\r
- \r
- ReleaseDragBitmaps();\r
- ReleaseCapture();\r
- \r
- TRACE ( "OnLButtonUp() done\n" );\r
- return true;\r
-}\r
-\r
-bool CardRegion::OnMouseMove(int x, int y)\r
-{\r
- HDC hdc;\r
-\r
- hdc = GetDC((HWND)parentWnd);\r
- \r
- x -= mousexoffset;\r
- y -= mouseyoffset;\r
- \r
- MoveDragCardTo(hdc, x, y);\r
-\r
- //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
- //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);\r
- \r
- ReleaseDC((HWND)parentWnd, hdc);\r
- \r
- oldx = x;\r
- oldy = y;\r
- \r
- return true;\r
-}\r
-\r
-//\r
-// There is a bug in BitBlt when the source x,y\r
-// become < 0. So this wrapper function simply adjusts\r
-// the coords so that we never try to blt in from this range\r
-//\r
-BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)\r
-{\r
- if(srcx < 0)\r
- {\r
- x = 0 - srcx;\r
- width = width + srcx;\r
- srcx = 0;\r
- }\r
-\r
- if(srcy < 0)\r
- {\r
- y = 0 - srcy;\r
- height = height + srcy;\r
- srcy = 0;\r
- }\r
-\r
- return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);\r
-}\r
-\r
-void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)\r
-{\r
- RECT inter, rect1, rect2;\r
-\r
- //mask off the new position of the drag-card, so\r
- //that it will not be painted over\r
- ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);\r
- \r
- //restore the area covered by the card at its previous position\r
- BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);\r
-\r
- //remove clipping so we can draw the card at its new place\r
- SelectClipRgn(hdc, NULL);\r
- \r
- //if the card's old and new positions overlap, then we\r
- //need some funky code to update the "saved background" image,\r
- SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);\r
- SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight);\r
- \r
- if(IntersectRect(&inter, &rect1, &rect2))\r
- {\r
- int interwidth = inter.right-inter.left;\r
- int interheight = inter.bottom-inter.top;\r
- int destx, desty, srcx, srcy;\r
- \r
- if(rect2.left > rect1.left) \r
- { \r
- destx = 0; srcx = nDragCardWidth - interwidth; \r
- }\r
- else\r
- {\r
- destx = nDragCardWidth - interwidth; srcx = 0;\r
- }\r
- \r
- if(rect2.top > rect1.top) \r
- {\r
- desty = 0; srcy = nDragCardHeight - interheight;\r
- }\r
- else \r
- {\r
- desty = nDragCardHeight - interheight; srcy = 0;\r
- }\r
- \r
- //shift the bit we didn't use for the restore (due to the clipping)\r
- //into the opposite corner\r
- BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);\r
- \r
- ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);\r
- \r
- //this bit requires us to clip the BitBlt (from screen to background)\r
- //as BitBlt is a bit buggy it seems\r
- ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
- SelectClipRgn(hdcBackGnd, NULL);\r
- }\r
- else\r
- {\r
- BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);\r
- }\r
- \r
- //finally draw the card to the screen\r
- DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);\r
-}\r
-\r
-\r
-//extern "C" int _fltused(void) { return 0; }\r
-//extern "C" int _ftol(void) { return 0; }\r
-\r
-//\r
-// Better do this in fixed-point, to stop\r
-// VC from linking in floatingpoint-long conversions\r
-//\r
-//#define FIXED_PREC_MOVE\r
-#ifdef FIXED_PREC_MOVE\r
-#define PRECISION 12\r
-void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)\r
-{\r
- long dx, dy, x , y;\r
-\r
- \r
- int apparentcards;\r
- x = xpos << PRECISION; y = ypos << PRECISION;\r
-\r
- oldx = (int)xpos;\r
- oldy = (int)ypos;\r
-\r
- apparentcards=dest->numcards/dest->threedcount;\r
-\r
- int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards); \r
- int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);\r
-\r
- //normalise the motion vector\r
- dx = (idestx<<PRECISION) - x;\r
- dy = (idesty<<PRECISION) - y;\r
- long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);\r
-\r
- dx *= recip * 16;//CARDZOOMSPEED; \r
- dy *= recip * 16;//CARDZOOMSPEED;\r
-\r
- //if(dx < 0) dxinc = 1.001; else\r
-\r
- for(;;)\r
- {\r
- int ix, iy;\r
- x += dx;\r
- y += dy;\r
-\r
- ix = (int)x>>PRECISION;\r
- iy = (int)y>>PRECISION;\r
- if(dx < 0 && ix < idestx) ix = idestx;\r
- else if(dx > 0 && ix > idestx) ix = idestx;\r
-\r
- if(dy < 0 && iy < idesty) iy = idesty;\r
- else if(dy > 0 && iy > idesty) iy = idesty;\r
-\r
- MoveDragCardTo(hdc, ix, iy);\r
-\r
- if(ix == idestx && iy == idesty)\r
- break;\r
-\r
- oldx = (int)x >> PRECISION;\r
- oldy = (int)y >> PRECISION;\r
-\r
- //dx *= 1.2;\r
- //dy *= 1.2;\r
-\r
- Sleep(10);\r
- }\r
-}\r
-#else\r
-void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)\r
-{\r
- TRACE ( "ENTER ZoomCard()\n" );\r
- double dx, dy, x ,y;\r
- int apparentcards;\r
- x = (double)xpos; y = (double)ypos;\r
-\r
- oldx = (int)x;\r
- oldy = (int)y;\r
-\r
- apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;\r
-\r
- int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);\r
- int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);\r
-\r
- if(pDestStack->yoffset < 0)\r
- idesty += pDestStack->yoffset * (iNumDragCards-1);\r
-\r
- if(pDestStack->xoffset < 0)\r
- idestx += pDestStack->xoffset * (iNumDragCards-1);\r
-\r
- //normalise the motion vector\r
- dx = idestx - x;\r
- dy = idesty - y;\r
- if ( fabs(dx) + fabs(dy) < 0.001f )\r
- {\r
- MoveDragCardTo(hdc, idestx, idesty);\r
- return;\r
- }\r
- double recip = 1.0 / sqrt(dx*dx + dy*dy);\r
- dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;\r
-\r
- //if(dx < 0) dxinc = 1.001; else\r
-\r
- for(;;)\r
- {\r
- bool attarget = true;\r
- int ix, iy;\r
- x += dx;\r
- y += dy;\r
-\r
- ix = (int)x;\r
- iy = (int)y;\r
-\r
- if(dx < 0.0 && ix < idestx) ix = idestx;\r
- else if(dx > 0.0 && ix > idestx) ix = idestx;\r
- else attarget = false;\r
-\r
- if(dy < 0.0 && iy < idesty) iy = idesty;\r
- else if(dy > 0.0 && iy > idesty) iy = idesty;\r
- else attarget = false;\r
-\r
- //if the target stack wants the drag cards drawn differently\r
- //to how they are, then redraw the drag card image just before\r
- //the cards land\r
- /*if(attarget == true)\r
- {\r
- for(int i = 0; i < iNumDragCards; i++)\r
- {\r
- int xdraw = pDestStack->xoffset*i;\r
- int ydraw = pDestStack->yoffset*i;\r
-\r
- if(pDestStack->yoffset < 0)\r
- ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);\r
- if(pDestStack->xoffset < 0)\r
- xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);\r
-\r
- if(pDestStack->facedirection == CS_FACEUP && \r
- pDestStack->numcards+i >= dest->numfacedown)\r
- {\r
- //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);\r
- }\r
- else\r
- {\r
- //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);\r
- }\r
- }\r
- }*/\r
-\r
- MoveDragCardTo(hdc, ix, iy);\r
-\r
- if(attarget || ix == idestx && iy == idesty)\r
- break;\r
-\r
- oldx = (int)x;\r
- oldy = (int)y;\r
-\r
- //dx *= 1.2;\r
- //dy *= 1.2;\r
-\r
- Sleep(10);\r
- }\r
- TRACE ( "EXIT ZoomCard()\n" );\r
-}\r
-#endif\r
+//
+// CardLib - CardRegion mouse-related stuff
+//
+// Freeware
+// Copyright J Brown 2001
+//
+#include <windows.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "cardlib.h"
+#include "cardwindow.h"
+#include "cardregion.h"
+
+#if 1
+#define TRACE(s)
+#else
+#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
+#endif
+
+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
+ //
+ TRACE ( "can I drop card?\n" );
+ if(pDestStack && pDestStack->CanDropCards(dragstack))
+ {
+ TRACE ( "yes, dropping card\n" );
+ hdc = GetDC((HWND)parentWnd);
+ // UseNicePalette(hdc);
+ ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack);
+ ReleaseDC((HWND)parentWnd, hdc);
+
+ //
+ //add the cards to the destination stack
+ //
+ CardStack temp = pDestStack->GetCardStack();
+ temp.Push(dragstack);
+
+ pDestStack->SetCardStack(temp);
+// pDestStack->Update(); //Update this stack's card count + size
+// pDestStack->UpdateFaceDir(temp);
+
+ // Call the remove callback on THIS stack, if one is specified
+ //
+ if(RemoveCallback)
+ RemoveCallback(*this, iNumDragCards);
+
+ // Call the add callback, if one is specified
+ //
+ if(pDestStack->AddCallback)
+ pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);
+
+ RedrawIfNotDim(pDestStack, true);
+ TRACE ( "done dropping card\n" );
+ }
+
+ //
+ // Otherwise, let the cards snap back onto this stack
+ //
+ else
+ {
+ TRACE ( "no, putting card back\n" );
+ hdc = GetDC((HWND)parentWnd);
+ TRACE ( "calling ZoomCard()\n" );
+ ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);
+ TRACE ( "cardstack += dragstack\n" );
+ cardstack += dragstack;
+ TRACE ( "calling ReleaseDC()\n" );
+ ReleaseDC((HWND)parentWnd, hdc);
+
+ TRACE ( "calling Update()\n" );
+ Update(); //Update this stack's card count + size
+ TRACE ( "done putting card back\n" );
+ }
+
+ ReleaseDragBitmaps();
+ ReleaseCapture();
+
+ TRACE ( "OnLButtonUp() done\n" );
+ return true;
+}
+
+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)
+{
+ TRACE ( "ENTER ZoomCard()\n" );
+ 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;
+ if ( fabs(dx) + fabs(dy) < 0.001f )
+ {
+ MoveDragCardTo(hdc, idestx, idesty);
+ return;
+ }
+ 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);
+ }
+ TRACE ( "EXIT ZoomCard()\n" );
+}
+#endif
-//\r
-// CardLib - CardStack class\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include <stdlib.h>\r
-\r
-#include "cardstack.h"\r
-\r
-Card &CardStack::operator[] (size_t index)\r
-{\r
- if(index >= (size_t)nNumCards) index = nNumCards - 1;\r
- return cardlist[nNumCards - index - 1];\r
-}\r
-\r
-const Card &CardStack::operator[] (size_t index) const\r
-{\r
- if(index >= (size_t)nNumCards) index = nNumCards - 1;\r
- return cardlist[nNumCards - index - 1];\r
-}\r
-\r
-// Subscripting operator for a constant sequence\r
-//\r
-/*Card CardStack::operator[] (size_t index) const\r
-{\r
- return cardlist[index];\r
-}*/\r
-\r
-//\r
-// Subscripting operator for a non-const sequence\r
-//\r
-/*CardStack::ref CardStack::operator[] (size_t index)\r
-{\r
- return ref(this, index);\r
-}*/\r
-\r
-void CardStack::Clear()\r
-{\r
- nNumCards = 0;\r
-}\r
-\r
-void CardStack::NewDeck()\r
-{\r
- nNumCards = 52;\r
-\r
- for(int i = 0; i < 52; i++)\r
- cardlist[i].nValue = i;\r
-}\r
-\r
-void CardStack::Shuffle()\r
-{\r
- int src, dest;\r
- Card temp;\r
-\r
- //shuffle 8 times..\r
- for(int i = 0; i < 8; i++)\r
- for(dest = nNumCards - 1; dest > 0; dest--)\r
- {\r
- //want to do this:\r
- // bad: src = rand() % (dest + 1)\r
- // good: src = rand() / (RAND_MAX / (dest+1) + 1)\r
- \r
- //positions from 0 to dest\r
- src = rand() / (RAND_MAX / (dest+1) + 1);\r
- \r
- //swap the cards\r
- temp = cardlist[src];\r
- cardlist[src] = cardlist[dest];\r
- cardlist[dest] = temp;\r
- }\r
-}\r
-\r
-void CardStack::Reverse()\r
-{\r
- for(int i = 0; i < nNumCards / 2; i++)\r
- {\r
- Card temp = cardlist[i];\r
- cardlist[i] = cardlist[nNumCards - i - 1];\r
- cardlist[nNumCards - i - 1] = temp;\r
- }\r
-}\r
-\r
-void CardStack::Push(const Card card)\r
-{\r
- if(nNumCards < MAX_CARDSTACK_SIZE)\r
- cardlist[nNumCards++] = card;\r
-}\r
-\r
-void CardStack::Push(const CardStack &cardstack)\r
-{\r
- if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE)\r
- {\r
- int num = cardstack.NumCards();\r
- \r
- for(int i = 0; i < num; i++)\r
- cardlist[nNumCards++] = cardstack.cardlist[i];\r
- }\r
-}\r
-\r
-CardStack& CardStack::operator += (Card card)\r
-{\r
- Push(card);\r
- return *this;\r
-}\r
-\r
-CardStack& CardStack::operator += (CardStack &cs)\r
-{\r
- Push(cs);\r
- return *this;\r
-}\r
-\r
-CardStack CardStack::operator + (Card card)\r
-{\r
- CardStack poo = *this;\r
- poo.Push(card);\r
- return poo;\r
-}\r
-\r
-CardStack CardStack::operator + (CardStack &cs)\r
-{\r
- CardStack poo = *this;\r
- poo.Push(cs);\r
- return poo;\r
-}\r
-\r
-\r
-Card CardStack::Pop()\r
-{\r
- if(nNumCards > 0)\r
- return cardlist[--nNumCards];\r
- else\r
- return 0;\r
-}\r
-\r
-CardStack CardStack::Pop(int items)\r
-{\r
- if(items <= nNumCards && nNumCards > 0)\r
- {\r
- CardStack cs(*this, nNumCards - items);\r
-\r
- nNumCards -= items;\r
-\r
- return cs;\r
- }\r
- else\r
- {\r
- return CardStack();\r
- }\r
-}\r
-\r
-Card CardStack::Top()\r
-{\r
- if(nNumCards > 0)\r
- return cardlist[nNumCards - 1];\r
- else\r
- return 0;\r
-}\r
-\r
-CardStack CardStack::Top(int items)\r
-{\r
- if(items <= nNumCards && nNumCards > 0)\r
- {\r
- return CardStack (*this, nNumCards - items);\r
- }\r
- else\r
- {\r
- return CardStack();\r
- }\r
-\r
-}\r
-\r
-Card CardStack::RemoveCard(size_t index)\r
-{\r
- if(nNumCards == 0 || index >= (size_t)nNumCards)\r
- return 0;\r
-\r
- //put index into reverse range..\r
- index = nNumCards - index - 1;\r
-\r
- Card temp = cardlist[index];\r
-\r
- nNumCards--;\r
-\r
- for(size_t i = index; i < (size_t)nNumCards; i++)\r
- {\r
- cardlist[i] = cardlist[i+1];\r
- }\r
-\r
- return temp;\r
-}\r
-\r
-void CardStack::InsertCard(size_t index, Card card)\r
-{\r
- if(nNumCards == MAX_CARDSTACK_SIZE)\r
- return;\r
-\r
- if(index > (size_t)nNumCards)\r
- return;\r
-\r
- if((size_t)nNumCards == index)\r
- {\r
- cardlist[nNumCards] = card;\r
- nNumCards++;\r
- return;\r
- }\r
-\r
- //put index into reverse range..\r
- index = nNumCards - index - 1;\r
-\r
- nNumCards++;\r
-\r
- //make room for the card\r
- for(size_t i = nNumCards; i > index; i--)\r
- {\r
- cardlist[i] = cardlist[i - 1];\r
- }\r
-\r
- cardlist[index] = card;\r
-}\r
-\r
-\r
-void CardStack::Print()\r
-{\r
-// for(int i = 0; i < nNumCards; i++)\r
-// cout << cardlist[i].HiVal() << " ";\r
-}\r
-\r
-CardStack::CardStack(CardStack ©this, size_t fromindex)\r
-{\r
- nNumCards = copythis.nNumCards - fromindex;\r
-\r
- for(int i = 0; i < nNumCards; i++)\r
- cardlist[i] = copythis.cardlist[fromindex + i];\r
-}\r
-\r
+//
+// 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];
+}
+
-#ifndef CARDSTACK_INCLUDED\r
-#define CARDSTACK_INCLUDED\r
-\r
-#include "card.h"\r
-\r
-#define MAX_CARDSTACK_SIZE 128\r
-\r
-class CardStack\r
-{\r
- friend class CardRegion;\r
-\r
-public:\r
- CardStack() : nNumCards(0) { }\r
-\r
- void NewDeck();\r
- int NumCards() const { return nNumCards; }\r
- void Shuffle();\r
- void Clear();\r
- void Reverse();\r
- \r
- void Push(const Card card);\r
- void Push(const CardStack &cardstack);\r
-\r
- Card Pop();\r
- CardStack Pop(int items);\r
-\r
- Card Top();\r
- CardStack Top(int items);\r
-\r
- void Print();\r
-\r
- Card RemoveCard(size_t index);\r
- void InsertCard(size_t index, Card card);\r
-\r
- //subscript capability!!\r
- Card & operator[] (size_t index);\r
- const Card & operator[] (size_t index) const;\r
-\r
- CardStack &operator += (Card card);\r
- CardStack &operator += (CardStack &cs);\r
-\r
- CardStack operator + (Card card);\r
- CardStack operator + (CardStack &cs);\r
- \r
-private: \r
-\r
- CardStack(CardStack ©this, size_t fromindex);\r
-\r
- Card cardlist[MAX_CARDSTACK_SIZE];\r
- int nNumCards;\r
-};\r
-\r
-#endif\r
+#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
-//\r
-// CardLib - CardWindow class\r
-//\r
-// Freeware\r
-// Copyright J Brown 2001\r
-//\r
-#include <windows.h>\r
-#include <tchar.h>\r
-\r
-#include "globals.h"\r
-#include "cardlib.h"\r
-#include "cardbutton.h"\r
-#include "cardregion.h"\r
-#include "cardwindow.h"\r
-#include "cardcolor.h"\r
-\r
-extern HPALETTE __holdplacepal;\r
-\r
-HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette)\r
-{\r
- HPALETTE hOld;\r
-\r
- hOld = SelectPalette(hdc, hPalette, FALSE);\r
- RealizePalette(hdc);\r
-\r
- return hOld;\r
-}\r
-\r
-void RestorePalette(HDC hdc, HPALETTE hOldPal)\r
-{\r
- SelectPalette(hdc, hOldPal, TRUE);\r
-}\r
-\r
-HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours);\r
-void PaintRect(HDC hdc, RECT *rect, COLORREF colour);\r
-HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height);\r
-void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2);\r
-\r
-void LoadCardBitmaps();\r
-void FreeCardBitmaps();\r
-\r
-static TCHAR szCardName[] = _T("CardWnd32");\r
-static bool fRegistered = false;\r
-static LONG uCardBitmapRef = 0;\r
-\r
-\r
-void RegisterCardWindow()\r
-{\r
- WNDCLASSEX wc;\r
-\r
- //Window class for the main application parent window\r
- wc.cbSize = sizeof(wc);\r
- wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;\r
- wc.lpfnWndProc = CardWindow::CardWndProc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = sizeof(CardWindow *);\r
- wc.hInstance = GetModuleHandle(0);\r
- wc.hIcon = 0;\r
- wc.hCursor = LoadCursor (NULL, IDC_ARROW);\r
- wc.hbrBackground = 0;\r
- wc.lpszMenuName = 0;\r
- wc.lpszClassName = szCardName;\r
- wc.hIconSm = 0;\r
-\r
- RegisterClassEx(&wc);\r
-}\r
-\r
-CardWindow::CardWindow() : m_hWnd(0)\r
-{\r
- HDC hdc = GetDC(0);\r
-\r
- nNumButtons = 0;\r
- nNumCardRegions = 0;\r
- nNumDropZones = 0;\r
- nBackCardIdx = 53;\r
-\r
- ResizeWndCallback = 0;\r
- hbmBackImage = 0;\r
- hdcBackImage = 0;\r
-\r
- srand((unsigned)GetTickCount());\r
-\r
- //All colours (buttons, highlights, decks)\r
- //are calculated off this single base colour\r
- crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100);\r
-\r
- // If uCardBitmapRef was previously zero, then\r
- // load the card bitmaps\r
- if(1 == InterlockedIncrement(&uCardBitmapRef))\r
- {\r
- LoadCardBitmaps();\r
-\r
- __hPalette = CreateCardPalette();\r
-\r
- __hdcPlaceHolder = CreateCompatibleDC(hdc);\r
- \r
- __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);\r
-\r
- __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);\r
-\r
- }\r
-\r
- ReleaseDC(0, hdc);\r
-\r
- //register the window class if necessary\r
- if(!fRegistered)\r
- {\r
- fRegistered = true;\r
- RegisterCardWindow();\r
- }\r
-\r
-}\r
-\r
-BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height)\r
-{\r
- if(m_hWnd)\r
- return FALSE;\r
-\r
- //Create the window associated with this object\r
- m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0, \r
- WS_CHILD | WS_VISIBLE,\r
- 0,0,100,100, \r
- hwndParent, 0, GetModuleHandle(0), this);\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOL CardWindow::Destroy()\r
-{\r
- DestroyWindow(m_hWnd);\r
- m_hWnd = 0;\r
-\r
- return TRUE;\r
-}\r
-\r
-CardWindow::~CardWindow()\r
-{\r
- if(m_hWnd)\r
- DestroyWindow(m_hWnd);\r
-\r
- DeleteAll();\r
-\r
- if(0 == InterlockedDecrement(&uCardBitmapRef))\r
- {\r
- FreeCardBitmaps();\r
-\r
- DeleteObject(__hbmPlaceHolder);\r
- DeleteDC (__hdcPlaceHolder);\r
-\r
- RestorePalette(__hdcPlaceHolder, __holdplacepal);\r
-\r
- if(__hPalette)\r
- DeleteObject(__hPalette);\r
- }\r
-}\r
-\r
-bool CardWindow::DeleteAll()\r
-{\r
- int i;\r
-\r
- for(i = 0; i < nNumCardRegions; i++)\r
- {\r
- delete Regions[i];\r
- }\r
-\r
- for(i = 0; i < nNumButtons; i++)\r
- {\r
- delete Buttons[i];\r
- }\r
-\r
- for(i = 0; i < nNumDropZones; i++)\r
- {\r
- delete dropzone[i];\r
- }\r
-\r
- nNumCardRegions = nNumButtons = nNumDropZones = 0;\r
-\r
- return true;\r
-}\r
-\r
-void CardWindow::SetBackColor(COLORREF cr)\r
-{\r
- crBackgnd = cr;\r
- int i;\r
- \r
- //\r
- // Create the exact palette we need to render the buttons/stacks\r
- //\r
- RestorePalette(__hdcPlaceHolder, __holdplacepal);\r
-\r
- if(__hPalette)\r
- DeleteObject(__hPalette);\r
-\r
- __hPalette = CreateCardPalette();\r
-\r
- //\r
- // re-create the place-holder!\r
- HDC hdc = GetDC(m_hWnd);\r
-\r
- DeleteObject(__hbmPlaceHolder);\r
-\r
- __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);\r
-\r
- __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);\r
- //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);\r
-\r
- //reset all buttons to same colour\r
- for(i = 0; i < nNumButtons; i++)\r
- {\r
- if(Buttons[i]->GetStyle() & CB_PUSHBUTTON)\r
- {\r
- Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1));\r
- }\r
- else\r
- {\r
- Buttons[i]->SetBackColor(crBackgnd);\r
- }\r
- }\r
-\r
- for(i = 0; i < nNumCardRegions; i++)\r
- {\r
- Regions[i]->SetBackColor(crBackgnd);\r
- }\r
-\r
-\r
- ReleaseDC(m_hWnd, hdc);\r
-}\r
-\r
-COLORREF CardWindow::GetBackColor()\r
-{\r
- return crBackgnd;\r
-}\r
-\r
-CardButton* CardWindow::CardButtonFromPoint(int x, int y)\r
-{\r
- CardButton *bptr = 0;\r
-\r
- POINT pt;\r
- pt.x = x;\r
- pt.y = y;\r
-\r
- //Search BACKWARDS...to reflect the implicit Z-order that\r
- //the button creation provided\r
- for(int i = nNumButtons - 1; i >= 0; i--)\r
- {\r
- bptr = Buttons[i];\r
- if(PtInRect(&bptr->rect, pt) && bptr->fVisible)\r
- return bptr;\r
- }\r
-\r
- return 0; \r
-}\r
-\r
-CardRegion* CardWindow::CardRegionFromPoint(int x, int y)\r
-{\r
- POINT pt;\r
- pt.x = x;\r
- pt.y = y;\r
-\r
- //Search BACKWARDS...to reflect the implicit Z-order that\r
- //the stack creation provided\r
- for(int i = nNumCardRegions - 1; i >= 0; i--)\r
- {\r
- if(Regions[i]->IsPointInStack(x, y))\r
- return Regions[i];\r
- }\r
-\r
- return 0; \r
-}\r
-\r
-//\r
-// Forward all window messages onto the appropriate\r
-// class instance\r
-//\r
-LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0);\r
- return cw->WndProc(hwnd, iMsg, wParam, lParam);\r
-}\r
-\r
-void CardWindow::Paint(HDC hdc)\r
-{\r
- int i;\r
- RECT rect;\r
- HPALETTE hOldPal;\r
-\r
- hOldPal = UseNicePalette(hdc, __hPalette);\r
-\r
- //\r
- // Clip the card stacks so that they won't\r
- // get painted over\r
- //\r
- for(i = 0; i < nNumCardRegions; i++)\r
- {\r
- Regions[i]->Clip(hdc);\r
- }\r
-\r
- //\r
- // Clip the buttons \r
- //\r
- for(i = 0; i < nNumButtons; i++)\r
- {\r
- Buttons[i]->Clip(hdc);\r
- }\r
-\r
-\r
- // Now paint the whole screen with background colour, \r
- //\r
- GetClientRect(m_hWnd, &rect);\r
- \r
- //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));\r
- PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0);\r
- SelectClipRgn(hdc, NULL);\r
-\r
- // Don't let cards draw over buttons, so clip buttons again\r
- //\r
- for(i = 0; i < nNumButtons; i++)\r
- {\r
- But