2 // CardLib - CardWindow class
5 // Copyright J Brown 2001
13 #include "cardbutton.h"
14 #include "cardregion.h"
15 #include "cardwindow.h"
16 #include "cardcolor.h"
18 extern HPALETTE __holdplacepal
;
20 HPALETTE
UseNicePalette(HDC hdc
, HPALETTE hPalette
)
24 hOld
= SelectPalette(hdc
, hPalette
, FALSE
);
30 void RestorePalette(HDC hdc
, HPALETTE hOldPal
)
32 SelectPalette(hdc
, hOldPal
, TRUE
);
35 HPALETTE
MakePaletteFromCols(COLORREF cols
[], int nNumColours
);
36 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
37 HBITMAP
CreateSinkBmp(HDC hdcCompat
, HDC hdc
, COLORREF col
, int width
, int height
);
38 void GetSinkCols(COLORREF crBase
, COLORREF
*fg
, COLORREF
*bg
, COLORREF
*sh1
, COLORREF
*sh2
);
40 void LoadCardBitmaps();
41 void FreeCardBitmaps();
43 static TCHAR szCardName
[] = _T("CardWnd32");
44 static bool fRegistered
= false;
45 static LONG uCardBitmapRef
= 0;
48 void RegisterCardWindow()
52 //Window class for the main application parent window
53 wc
.cbSize
= sizeof(wc
);
54 wc
.style
= CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
;
55 wc
.lpfnWndProc
= CardWindow::CardWndProc
;
57 wc
.cbWndExtra
= sizeof(CardWindow
*);
58 wc
.hInstance
= GetModuleHandle(0);
60 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
63 wc
.lpszClassName
= szCardName
;
69 CardWindow::CardWindow() : m_hWnd(0)
78 ResizeWndCallback
= 0;
82 srand((unsigned)GetTickCount());
84 //All colours (buttons, highlights, decks)
85 //are calculated off this single base colour
86 crBackgnd
= PALETTERGB(0,80,0);//PALETTERGB(0,64,100);
88 // If uCardBitmapRef was previously zero, then
89 // load the card bitmaps
90 if(1 == InterlockedIncrement(&uCardBitmapRef
))
94 __hPalette
= CreateCardPalette();
96 __hdcPlaceHolder
= CreateCompatibleDC(hdc
);
98 __holdplacepal
= UseNicePalette(__hdcPlaceHolder
, __hPalette
);
100 __hbmPlaceHolder
= CreateSinkBmp(hdc
, __hdcPlaceHolder
, crBackgnd
, __cardwidth
, __cardheight
);
106 //register the window class if necessary
110 RegisterCardWindow();
115 BOOL
CardWindow::Create(HWND hwndParent
, DWORD dwExStyle
, DWORD dwStyle
, int x
, int y
, int width
, int height
)
120 //Create the window associated with this object
121 m_hWnd
= CreateWindowEx(WS_EX_CLIENTEDGE
, szCardName
, 0,
122 WS_CHILD
| WS_VISIBLE
,
124 hwndParent
, 0, GetModuleHandle(0), this);
129 BOOL
CardWindow::Destroy()
131 DestroyWindow(m_hWnd
);
137 CardWindow::~CardWindow()
140 DestroyWindow(m_hWnd
);
144 if(0 == InterlockedDecrement(&uCardBitmapRef
))
148 DeleteObject(__hbmPlaceHolder
);
149 DeleteDC (__hdcPlaceHolder
);
151 RestorePalette(__hdcPlaceHolder
, __holdplacepal
);
154 DeleteObject(__hPalette
);
158 bool CardWindow::DeleteAll()
162 for(i
= 0; i
< nNumCardRegions
; i
++)
167 for(i
= 0; i
< nNumButtons
; i
++)
172 for(i
= 0; i
< nNumDropZones
; i
++)
177 nNumCardRegions
= nNumButtons
= nNumDropZones
= 0;
182 void CardWindow::SetBackColor(COLORREF cr
)
188 // Create the exact palette we need to render the buttons/stacks
190 RestorePalette(__hdcPlaceHolder
, __holdplacepal
);
193 DeleteObject(__hPalette
);
195 __hPalette
= CreateCardPalette();
198 // re-create the place-holder!
199 HDC hdc
= GetDC(m_hWnd
);
201 DeleteObject(__hbmPlaceHolder
);
203 __holdplacepal
= UseNicePalette(__hdcPlaceHolder
, __hPalette
);
205 __hbmPlaceHolder
= CreateSinkBmp(hdc
, __hdcPlaceHolder
, crBackgnd
, __cardwidth
, __cardheight
);
206 //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);
208 //reset all buttons to same colour
209 for(i
= 0; i
< nNumButtons
; i
++)
211 if(Buttons
[i
]->GetStyle() & CB_PUSHBUTTON
)
213 Buttons
[i
]->SetBackColor(ColorScaleRGB(crBackgnd
, RGB(255,255,255), 0.1));
217 Buttons
[i
]->SetBackColor(crBackgnd
);
221 for(i
= 0; i
< nNumCardRegions
; i
++)
223 Regions
[i
]->SetBackColor(crBackgnd
);
227 ReleaseDC(m_hWnd
, hdc
);
230 COLORREF
CardWindow::GetBackColor()
235 CardButton
* CardWindow::CardButtonFromPoint(int x
, int y
)
237 CardButton
*bptr
= 0;
243 //Search BACKWARDS...to reflect the implicit Z-order that
244 //the button creation provided
245 for(int i
= nNumButtons
- 1; i
>= 0; i
--)
248 if(PtInRect(&bptr
->rect
, pt
) && bptr
->fVisible
)
255 CardRegion
* CardWindow::CardRegionFromPoint(int x
, int y
)
261 //Search BACKWARDS...to reflect the implicit Z-order that
262 //the stack creation provided
263 for(int i
= nNumCardRegions
- 1; i
>= 0; i
--)
265 if(Regions
[i
]->IsPointInStack(x
, y
))
273 // Forward all window messages onto the appropriate
276 LRESULT CALLBACK
CardWindow::CardWndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
278 CardWindow
*cw
= (CardWindow
*)GetWindowLong(hwnd
, 0);
279 return cw
->WndProc(hwnd
, iMsg
, wParam
, lParam
);
282 void CardWindow::Paint(HDC hdc
)
288 hOldPal
= UseNicePalette(hdc
, __hPalette
);
291 // Clip the card stacks so that they won't
294 for(i
= 0; i
< nNumCardRegions
; i
++)
296 Regions
[i
]->Clip(hdc
);
302 for(i
= 0; i
< nNumButtons
; i
++)
304 Buttons
[i
]->Clip(hdc
);
308 // Now paint the whole screen with background colour,
310 GetClientRect(m_hWnd
, &rect
);
312 //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
313 PaintCardRgn(hdc
, 0, 0, rect
.right
, rect
.bottom
, 0, 0);
314 SelectClipRgn(hdc
, NULL
);
316 // Don't let cards draw over buttons, so clip buttons again
318 for(i
= 0; i
< nNumButtons
; i
++)
320 Buttons
[i
]->Clip(hdc
);
323 // Paint each card stack in turn
325 for(i
= 0; i
< nNumCardRegions
; i
++)
327 Regions
[i
]->Render(hdc
);
330 // Paint each button now
332 SelectClipRgn(hdc
, NULL
);
334 for(i
= 0; i
< nNumButtons
; i
++)
336 Buttons
[i
]->Redraw();
339 RestorePalette(hdc
, hOldPal
);
345 LRESULT CALLBACK
CardWindow::WndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
352 static CardButton
*buttonptr
= 0;
353 static CardRegion
*stackptr
= 0;
361 // When we created this window, we passed in the
362 // pointer to the class object (CardWindow *) in the
363 // call to CreateWindow.
364 cs
= (CREATESTRUCT
*)lParam
;
367 // associate this class with the window
369 SetWindowLong(hwnd
, 0, (LONG
)cs
->lpCreateParams
);
374 // Don't delete anything here..
378 nWidth
= LOWORD(lParam
);
379 nHeight
= HIWORD(lParam
);
382 // reposition all the stacks and buttons
383 // in case any of them are centered, right-justified etc
385 for(i
= 0; i
< nNumCardRegions
; i
++)
387 Regions
[i
]->AdjustPosition(nWidth
, nHeight
);
390 for(i
= 0; i
< nNumButtons
; i
++)
392 Buttons
[i
]->AdjustPosition(nWidth
, nHeight
);
396 // Call the user-defined resize proc AFTER all the stacks
397 // have been positioned
399 if(ResizeWndCallback
)
400 ResizeWndCallback(nWidth
, nHeight
);
406 hdc
= BeginPaint(hwnd
, &ps
);
415 //find the timer object in the registered funcs
416 /*if(wParam >= 0x10000)
418 for(i = 0; i < nRegFuncs; i++)
420 if(RegFuncs[i].id == wParam)
422 KillTimer(hwnd, wParam);
424 //call the registered function!!
425 RegFuncs[i].func(RegFuncs[i].dwParam);
427 RegFuncs[i] = RegFuncs[nRegFuncs-1];
435 CardRegion
*stackobj
= (CardRegion
*)wParam
;//CardStackFromId(wParam);
441 case WM_LBUTTONDBLCLK
:
443 x
= (short)LOWORD(lParam
);
444 y
= (short)HIWORD(lParam
);
446 if((buttonptr
= CardButtonFromPoint(x
, y
)) != 0)
448 buttonptr
->OnLButtonDown(hwnd
, x
, y
);
452 if((stackptr
= CardRegionFromPoint(x
, y
)) != 0)
454 stackptr
->OnLButtonDblClk(x
, y
);
462 x
= (short)LOWORD(lParam
);
463 y
= (short)HIWORD(lParam
);
465 //if clicked on a button
466 if((buttonptr
= CardButtonFromPoint(x
, y
)) != 0)
468 if(buttonptr
->OnLButtonDown(hwnd
, x
, y
) == 0)
474 if((stackptr
= CardRegionFromPoint(x
, y
)) != 0)
476 if(!stackptr
->OnLButtonDown(x
, y
))
484 x
= (short)LOWORD(lParam
);
485 y
= (short)HIWORD(lParam
);
488 // if we were clicking a button
492 buttonptr
->OnLButtonUp(hwnd
, x
, y
);
499 stackptr
->OnLButtonUp(x
, y
);
508 x
= (short)LOWORD(lParam
);
509 y
= (short)HIWORD(lParam
);
511 // if we were clicking a button
514 buttonptr
->OnMouseMove(hwnd
, x
, y
);
520 return stackptr
->OnMouseMove(x
, y
);
527 return DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
531 CardRegion
* CardWindow::CardRegionFromId(int id
)
533 for(int i
= 0; i
< nNumCardRegions
; i
++)
535 if(Regions
[i
]->id
== id
)
542 CardButton
* CardWindow::CardButtonFromId(int id
)
544 for(int i
= 0; i
< nNumButtons
; i
++)
546 if(Buttons
[i
]->id
== id
)
553 void CardWindow::Redraw()
555 InvalidateRect(m_hWnd
, 0, 0);
556 UpdateWindow(m_hWnd
);
559 bool CardWindow::DeleteButton(CardButton
*pButton
)
561 for(int i
= 0; i
< nNumButtons
; i
++)
563 if(Buttons
[i
] == pButton
)
565 CardButton
*cb
= Buttons
[i
];
567 //shift any after this one backwards
568 for(int j
= i
; j
< nNumButtons
- 1; j
++)
570 Buttons
[j
] = Buttons
[j
+ 1];
583 bool CardWindow::DeleteRegion(CardRegion
*pRegion
)
585 for(int i
= 0; i
< nNumCardRegions
; i
++)
587 if(Regions
[i
] == pRegion
)
589 CardRegion
*cr
= Regions
[i
];
591 //shift any after this one backwards
592 for(int j
= i
; j
< nNumCardRegions
- 1; j
++)
594 Regions
[j
] = Regions
[j
+ 1];
607 void CardWindow::EmptyStacks(void)
609 for(int i
= 0; i
< nNumCardRegions
; i
++)
612 Regions
[i
]->Update();
618 bool CardWindow::DistributeStacks(int nIdFrom
, int nNumStacks
, UINT xJustify
, int xSpacing
, int nStartX
)
620 int numvisiblestacks
= 0;
625 //find the stack which starts with our ID
626 for(i
= 0; i
< nNumCardRegions
; i
++)
628 if(Regions
[i
]->Id() == nIdFrom
)
635 //if didn't find, return
636 if(i
== nNumCardRegions
) return false;
638 //count the stacks that are visible
639 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
641 if(Regions
[i
]->IsVisible())
645 if(xJustify
== CS_XJUST_CENTER
)
647 //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;
649 viswidth
= numvisiblestacks
* __cardwidth
;
650 viswidth
+= xSpacing
* (numvisiblestacks
- 1);
651 curx
= -(viswidth
- __cardwidth
) / 2;
653 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
655 if(Regions
[i
]->IsVisible())
657 Regions
[i
]->xadjust
= curx
;
658 Regions
[i
]->xjustify
= CS_XJUST_CENTER
;
659 curx
+= Regions
[i
]->width
+ xSpacing
;
665 if(xJustify
== CS_XJUST_RIGHT
)
667 nStartX
-= ((numvisiblestacks
+ xSpacing
) * __cardwidth
- xSpacing
);
670 if(xJustify
== CS_XJUST_NONE
)
672 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
674 if(Regions
[i
]->IsVisible())
676 Regions
[i
]->xpos
= curx
;
677 curx
+= Regions
[i
]->width
+ xSpacing
;
678 Regions
[i
]->UpdateSize();
687 void CardWindow::Update()
689 for(int i
= 0; i
< nNumCardRegions
; i
++)
691 Regions
[i
]->AdjustPosition(nWidth
, nHeight
);
696 void CardWindow::SetResizeProc(pResizeWndProc proc
)
698 ResizeWndCallback
= proc
;
702 HPALETTE
CardWindow::CreateCardPalette()
708 //include button text colours
709 cols
[0] = RGB(0, 0, 0);
710 cols
[1] = RGB(255, 255, 255);
712 //include the base background colour
715 //include the standard button colours...
716 cols
[3] = CardButton::GetHighlight(crBackgnd
);
717 cols
[4] = CardButton::GetShadow(crBackgnd
);
718 cols
[5] = CardButton::GetFace(crBackgnd
);
720 //include the sunken image bitmap colours...
721 GetSinkCols(crBackgnd
, &cols
[6], &cols
[7], &cols
[8], &cols
[9]);
725 return MakePaletteFromCols(cols
, nNumCols
);
728 void CardWindow::SetBackCardIdx(UINT uBackIdx
)
730 if(uBackIdx
>= 52 && uBackIdx
<= 68)
731 nBackCardIdx
= uBackIdx
;
733 for(int i
= 0; i
< nNumCardRegions
; i
++)
734 Regions
[i
]->SetBackCardIdx(uBackIdx
);
738 UINT
CardWindow::GetBackCardIdx()
743 void CardWindow::PaintCardRgn(HDC hdc
, int dx
, int dy
, int width
, int height
, int sx
, int sy
)
747 //if just a solid background colour
748 if(hbmBackImage
== 0)
750 SetRect(&rect
, dx
, dy
, dx
+width
, dy
+height
);
752 /*if(GetVersion() < 0x80000000)
754 PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
758 HBRUSH hbr
= CreateSolidBrush(MAKE_PALETTERGB(crBackgnd
));
759 FillRect(hdc
, &rect
, hbr
);
763 //otherwise, paint using the bitmap
766 // Draw whatever part of background we can
767 BitBlt(hdc
, dx
, dy
, width
, height
, hdcBackImage
, sx
, sy
, SRCCOPY
);
769 // Now we need to paint any area outside the bitmap,
770 // just in case the bitmap is too small to fill whole window
771 if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight)
773 // Find out size of bitmap
775 GetObject(hbmBackImage
, sizeof(bm
), &bm
);
777 HRGN hr1
= CreateRectRgn(sx
, sy
, sx
+width
, sy
+height
);
778 HRGN hr2
= CreateRectRgn(0, 0, bm
.bmWidth
, bm
.bmHeight
);
779 HRGN hr3
= CreateRectRgn(0,0, 1, 1);
780 HRGN hr4
= CreateRectRgn(0,0, 1, 1);
782 CombineRgn(hr3
, hr1
, hr2
, RGN_DIFF
);
784 GetClipRgn(hdc
, hr4
);
786 CombineRgn(hr3
, hr4
, hr3
, RGN_AND
);
787 SelectClipRgn(hdc
, hr3
);
789 // Fill remaining space not filled with bitmap
790 HBRUSH hbr
= CreateSolidBrush(crBackgnd
);
791 FillRgn(hdc
, hr3
, hbr
);
795 SelectClipRgn(hdc
, hr4
);
805 void CardWindow::SetBackImage(HBITMAP hBitmap
)
807 //delete current image?? NO!
808 if(hdcBackImage
== 0)
810 hdcBackImage
= CreateCompatibleDC(0);
813 hbmBackImage
= hBitmap
;
816 SelectObject(hdcBackImage
, hBitmap
);