2 // CardLib - CardWindow class
5 // Copyright J Brown 2001
12 #include "cardbutton.h"
13 #include "cardregion.h"
14 #include "cardwindow.h"
15 #include "cardcolor.h"
17 extern HPALETTE __holdplacepal
;
19 HPALETTE
UseNicePalette(HDC hdc
, HPALETTE hPalette
)
23 hOld
= SelectPalette(hdc
, hPalette
, FALSE
);
29 void RestorePalette(HDC hdc
, HPALETTE hOldPal
)
31 SelectPalette(hdc
, hOldPal
, TRUE
);
34 HPALETTE
MakePaletteFromCols(COLORREF cols
[], int nNumColours
);
35 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
36 HBITMAP
CreateSinkBmp(HDC hdcCompat
, HDC hdc
, COLORREF col
, int width
, int height
);
37 void GetSinkCols(COLORREF crBase
, COLORREF
*fg
, COLORREF
*bg
, COLORREF
*sh1
, COLORREF
*sh2
);
39 void LoadCardBitmaps();
40 void FreeCardBitmaps();
42 static TCHAR szCardName
[] = _T("CardWnd32");
43 static bool fRegistered
= false;
44 static LONG uCardBitmapRef
= 0;
47 void RegisterCardWindow()
51 //Window class for the main application parent window
52 wc
.cbSize
= sizeof(wc
);
53 wc
.style
= CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
;
54 wc
.lpfnWndProc
= CardWindow::CardWndProc
;
56 wc
.cbWndExtra
= sizeof(CardWindow
*);
57 wc
.hInstance
= GetModuleHandle(0);
59 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
62 wc
.lpszClassName
= szCardName
;
68 CardWindow::CardWindow() : m_hWnd(0)
77 ResizeWndCallback
= 0;
81 srand((unsigned)GetTickCount());
83 //All colours (buttons, highlights, decks)
84 //are calculated off this single base colour
85 crBackgnd
= PALETTERGB(0,80,0);//PALETTERGB(0,64,100);
87 // If uCardBitmapRef was previously zero, then
88 // load the card bitmaps
89 if(1 == InterlockedIncrement(&uCardBitmapRef
))
93 __hPalette
= CreateCardPalette();
95 __hdcPlaceHolder
= CreateCompatibleDC(hdc
);
97 __holdplacepal
= UseNicePalette(__hdcPlaceHolder
, __hPalette
);
99 __hbmPlaceHolder
= CreateSinkBmp(hdc
, __hdcPlaceHolder
, crBackgnd
, __cardwidth
, __cardheight
);
105 //register the window class if necessary
109 RegisterCardWindow();
114 BOOL
CardWindow::Create(HWND hwndParent
, DWORD dwExStyle
, DWORD dwStyle
, int x
, int y
, int width
, int height
)
119 //Create the window associated with this object
120 m_hWnd
= CreateWindowEx(WS_EX_CLIENTEDGE
, szCardName
, 0,
121 WS_CHILD
| WS_VISIBLE
,
123 hwndParent
, 0, GetModuleHandle(0), this);
128 BOOL
CardWindow::Destroy()
130 DestroyWindow(m_hWnd
);
136 CardWindow::~CardWindow()
139 DestroyWindow(m_hWnd
);
143 if(0 == InterlockedDecrement(&uCardBitmapRef
))
147 DeleteObject(__hbmPlaceHolder
);
148 DeleteDC (__hdcPlaceHolder
);
150 RestorePalette(__hdcPlaceHolder
, __holdplacepal
);
153 DeleteObject(__hPalette
);
157 bool CardWindow::DeleteAll()
161 for(i
= 0; i
< nNumCardRegions
; i
++)
166 for(i
= 0; i
< nNumButtons
; i
++)
171 for(i
= 0; i
< nNumDropZones
; i
++)
176 nNumCardRegions
= nNumButtons
= nNumDropZones
= 0;
181 void CardWindow::SetBackColor(COLORREF cr
)
187 // Create the exact palette we need to render the buttons/stacks
189 RestorePalette(__hdcPlaceHolder
, __holdplacepal
);
192 DeleteObject(__hPalette
);
194 __hPalette
= CreateCardPalette();
197 // re-create the place-holder!
198 HDC hdc
= GetDC(m_hWnd
);
200 DeleteObject(__hbmPlaceHolder
);
202 __holdplacepal
= UseNicePalette(__hdcPlaceHolder
, __hPalette
);
204 __hbmPlaceHolder
= CreateSinkBmp(hdc
, __hdcPlaceHolder
, crBackgnd
, __cardwidth
, __cardheight
);
205 //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);
207 //reset all buttons to same colour
208 for(i
= 0; i
< nNumButtons
; i
++)
210 if(Buttons
[i
]->GetStyle() & CB_PUSHBUTTON
)
212 Buttons
[i
]->SetBackColor(ColorScaleRGB(crBackgnd
, RGB(255,255,255), 0.1));
216 Buttons
[i
]->SetBackColor(crBackgnd
);
220 for(i
= 0; i
< nNumCardRegions
; i
++)
222 Regions
[i
]->SetBackColor(crBackgnd
);
226 ReleaseDC(m_hWnd
, hdc
);
229 COLORREF
CardWindow::GetBackColor()
234 CardButton
* CardWindow::CardButtonFromPoint(int x
, int y
)
236 CardButton
*bptr
= 0;
242 //Search BACKWARDS...to reflect the implicit Z-order that
243 //the button creation provided
244 for(int i
= nNumButtons
- 1; i
>= 0; i
--)
247 if(PtInRect(&bptr
->rect
, pt
) && bptr
->fVisible
)
254 CardRegion
* CardWindow::CardRegionFromPoint(int x
, int y
)
260 //Search BACKWARDS...to reflect the implicit Z-order that
261 //the stack creation provided
262 for(int i
= nNumCardRegions
- 1; i
>= 0; i
--)
264 if(Regions
[i
]->IsPointInStack(x
, y
))
272 // Forward all window messages onto the appropriate
275 LRESULT CALLBACK
CardWindow::CardWndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
277 CardWindow
*cw
= (CardWindow
*)GetWindowLong(hwnd
, 0);
278 return cw
->WndProc(hwnd
, iMsg
, wParam
, lParam
);
281 void CardWindow::Paint(HDC hdc
)
287 hOldPal
= UseNicePalette(hdc
, __hPalette
);
290 // Clip the card stacks so that they won't
293 for(i
= 0; i
< nNumCardRegions
; i
++)
295 Regions
[i
]->Clip(hdc
);
301 for(i
= 0; i
< nNumButtons
; i
++)
303 Buttons
[i
]->Clip(hdc
);
307 // Now paint the whole screen with background colour,
309 GetClientRect(m_hWnd
, &rect
);
311 //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
312 PaintCardRgn(hdc
, 0, 0, rect
.right
, rect
.bottom
, 0, 0);
313 SelectClipRgn(hdc
, NULL
);
315 // Don't let cards draw over buttons, so clip buttons again
317 for(i
= 0; i
< nNumButtons
; i
++)
319 Buttons
[i
]->Clip(hdc
);
322 // Paint each card stack in turn
324 for(i
= 0; i
< nNumCardRegions
; i
++)
326 Regions
[i
]->Render(hdc
);
329 // Paint each button now
331 SelectClipRgn(hdc
, NULL
);
333 for(i
= 0; i
< nNumButtons
; i
++)
335 Buttons
[i
]->Redraw();
338 RestorePalette(hdc
, hOldPal
);
344 LRESULT CALLBACK
CardWindow::WndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
351 static CardButton
*buttonptr
= 0;
352 static CardRegion
*stackptr
= 0;
360 // When we created this window, we passed in the
361 // pointer to the class object (CardWindow *) in the
362 // call to CreateWindow.
363 cs
= (CREATESTRUCT
*)lParam
;
366 // associate this class with the window
368 SetWindowLong(hwnd
, 0, (LONG
)cs
->lpCreateParams
);
373 // Don't delete anything here..
377 nWidth
= LOWORD(lParam
);
378 nHeight
= HIWORD(lParam
);
381 // reposition all the stacks and buttons
382 // in case any of them are centered, right-justified etc
384 for(i
= 0; i
< nNumCardRegions
; i
++)
386 Regions
[i
]->AdjustPosition(nWidth
, nHeight
);
389 for(i
= 0; i
< nNumButtons
; i
++)
391 Buttons
[i
]->AdjustPosition(nWidth
, nHeight
);
395 // Call the user-defined resize proc AFTER all the stacks
396 // have been positioned
398 if(ResizeWndCallback
)
399 ResizeWndCallback(nWidth
, nHeight
);
405 hdc
= BeginPaint(hwnd
, &ps
);
414 //find the timer object in the registered funcs
415 /*if(wParam >= 0x10000)
417 for(i = 0; i < nRegFuncs; i++)
419 if(RegFuncs[i].id == wParam)
421 KillTimer(hwnd, wParam);
423 //call the registered function!!
424 RegFuncs[i].func(RegFuncs[i].dwParam);
426 RegFuncs[i] = RegFuncs[nRegFuncs-1];
434 CardRegion
*stackobj
= (CardRegion
*)wParam
;//CardStackFromId(wParam);
440 case WM_LBUTTONDBLCLK
:
442 x
= (short)LOWORD(lParam
);
443 y
= (short)HIWORD(lParam
);
445 if((buttonptr
= CardButtonFromPoint(x
, y
)) != 0)
447 buttonptr
->OnLButtonDown(hwnd
, x
, y
);
451 if((stackptr
= CardRegionFromPoint(x
, y
)) != 0)
453 stackptr
->OnLButtonDblClk(x
, y
);
461 x
= (short)LOWORD(lParam
);
462 y
= (short)HIWORD(lParam
);
464 //if clicked on a button
465 if((buttonptr
= CardButtonFromPoint(x
, y
)) != 0)
467 if(buttonptr
->OnLButtonDown(hwnd
, x
, y
) == 0)
473 if((stackptr
= CardRegionFromPoint(x
, y
)) != 0)
475 if(!stackptr
->OnLButtonDown(x
, y
))
483 x
= (short)LOWORD(lParam
);
484 y
= (short)HIWORD(lParam
);
487 // if we were clicking a button
491 buttonptr
->OnLButtonUp(hwnd
, x
, y
);
498 stackptr
->OnLButtonUp(x
, y
);
507 x
= (short)LOWORD(lParam
);
508 y
= (short)HIWORD(lParam
);
510 // if we were clicking a button
513 buttonptr
->OnMouseMove(hwnd
, x
, y
);
519 return stackptr
->OnMouseMove(x
, y
);
526 return DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
530 CardRegion
* CardWindow::CardRegionFromId(int id
)
532 for(int i
= 0; i
< nNumCardRegions
; i
++)
534 if(Regions
[i
]->id
== id
)
541 CardButton
* CardWindow::CardButtonFromId(int id
)
543 for(int i
= 0; i
< nNumButtons
; i
++)
545 if(Buttons
[i
]->id
== id
)
552 void CardWindow::Redraw()
554 InvalidateRect(m_hWnd
, 0, 0);
555 UpdateWindow(m_hWnd
);
558 bool CardWindow::DeleteButton(CardButton
*pButton
)
560 for(int i
= 0; i
< nNumButtons
; i
++)
562 if(Buttons
[i
] == pButton
)
564 CardButton
*cb
= Buttons
[i
];
566 //shift any after this one backwards
567 for(int j
= i
; j
< nNumButtons
- 1; j
++)
569 Buttons
[j
] = Buttons
[j
+ 1];
582 bool CardWindow::DeleteRegion(CardRegion
*pRegion
)
584 for(int i
= 0; i
< nNumCardRegions
; i
++)
586 if(Regions
[i
] == pRegion
)
588 CardRegion
*cr
= Regions
[i
];
590 //shift any after this one backwards
591 for(int j
= i
; j
< nNumCardRegions
- 1; j
++)
593 Regions
[j
] = Regions
[j
+ 1];
606 void CardWindow::EmptyStacks(void)
608 for(int i
= 0; i
< nNumCardRegions
; i
++)
611 Regions
[i
]->Update();
617 bool CardWindow::DistributeStacks(int nIdFrom
, int nNumStacks
, UINT xJustify
, int xSpacing
, int nStartX
)
619 int numvisiblestacks
= 0;
624 //find the stack which starts with our ID
625 for(i
= 0; i
< nNumCardRegions
; i
++)
627 if(Regions
[i
]->Id() == nIdFrom
)
634 //if didn't find, return
635 if(i
== nNumCardRegions
) return false;
637 //count the stacks that are visible
638 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
640 if(Regions
[i
]->IsVisible())
644 if(xJustify
== CS_XJUST_CENTER
)
646 //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;
648 viswidth
= numvisiblestacks
* __cardwidth
;
649 viswidth
+= xSpacing
* (numvisiblestacks
- 1);
650 curx
= -(viswidth
- __cardwidth
) / 2;
652 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
654 if(Regions
[i
]->IsVisible())
656 Regions
[i
]->xadjust
= curx
;
657 Regions
[i
]->xjustify
= CS_XJUST_CENTER
;
658 curx
+= Regions
[i
]->width
+ xSpacing
;
664 if(xJustify
== CS_XJUST_RIGHT
)
666 nStartX
-= ((numvisiblestacks
+ xSpacing
) * __cardwidth
- xSpacing
);
669 if(xJustify
== CS_XJUST_NONE
)
671 for(i
= startindex
; i
< startindex
+ nNumStacks
; i
++)
673 if(Regions
[i
]->IsVisible())
675 Regions
[i
]->xpos
= curx
;
676 curx
+= Regions
[i
]->width
+ xSpacing
;
677 Regions
[i
]->UpdateSize();
686 void CardWindow::Update()
688 for(int i
= 0; i
< nNumCardRegions
; i
++)
690 Regions
[i
]->AdjustPosition(nWidth
, nHeight
);
695 void CardWindow::SetResizeProc(pResizeWndProc proc
)
697 ResizeWndCallback
= proc
;
701 HPALETTE
CardWindow::CreateCardPalette()
707 //include button text colours
708 cols
[0] = RGB(0, 0, 0);
709 cols
[1] = RGB(255, 255, 255);
711 //include the base background colour
714 //include the standard button colours...
715 cols
[3] = CardButton::GetHighlight(crBackgnd
);
716 cols
[4] = CardButton::GetShadow(crBackgnd
);
717 cols
[5] = CardButton::GetFace(crBackgnd
);
719 //include the sunken image bitmap colours...
720 GetSinkCols(crBackgnd
, &cols
[6], &cols
[7], &cols
[8], &cols
[9]);
724 return MakePaletteFromCols(cols
, nNumCols
);
727 void CardWindow::SetBackCardIdx(UINT uBackIdx
)
729 if(uBackIdx
>= 52 && uBackIdx
<= 68)
730 nBackCardIdx
= uBackIdx
;
732 for(int i
= 0; i
< nNumCardRegions
; i
++)
733 Regions
[i
]->SetBackCardIdx(uBackIdx
);
737 void CardWindow::PaintCardRgn(HDC hdc
, int dx
, int dy
, int width
, int height
, int sx
, int sy
)
741 //if just a solid background colour
742 if(hbmBackImage
== 0)
744 SetRect(&rect
, dx
, dy
, dx
+width
, dy
+height
);
746 /*if(GetVersion() < 0x80000000)
748 PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
752 HBRUSH hbr
= CreateSolidBrush(MAKE_PALETTERGB(crBackgnd
));
753 FillRect(hdc
, &rect
, hbr
);
757 //otherwise, paint using the bitmap
760 // Draw whatever part of background we can
761 BitBlt(hdc
, dx
, dy
, width
, height
, hdcBackImage
, sx
, sy
, SRCCOPY
);
763 // Now we need to paint any area outside the bitmap,
764 // just in case the bitmap is too small to fill whole window
765 if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight)
767 // Find out size of bitmap
769 GetObject(hbmBackImage
, sizeof(bm
), &bm
);
771 HRGN hr1
= CreateRectRgn(sx
, sy
, sx
+width
, sy
+height
);
772 HRGN hr2
= CreateRectRgn(0, 0, bm
.bmWidth
, bm
.bmHeight
);
773 HRGN hr3
= CreateRectRgn(0,0, 1, 1);
774 HRGN hr4
= CreateRectRgn(0,0, 1, 1);
776 CombineRgn(hr3
, hr1
, hr2
, RGN_DIFF
);
778 GetClipRgn(hdc
, hr4
);
780 CombineRgn(hr3
, hr4
, hr3
, RGN_AND
);
781 SelectClipRgn(hdc
, hr3
);
783 // Fill remaining space not filled with bitmap
784 HBRUSH hbr
= CreateSolidBrush(crBackgnd
);
785 FillRgn(hdc
, hr3
, hbr
);
789 SelectClipRgn(hdc
, hr4
);
799 void CardWindow::SetBackImage(HBITMAP hBitmap
)
801 //delete current image?? NO!
802 if(hdcBackImage
== 0)
804 hdcBackImage
= CreateCompatibleDC(0);
807 hbmBackImage
= hBitmap
;
810 SelectObject(hdcBackImage
, hBitmap
);