1 //
2 //    CardLib - CardWindow class
3 //
4 //    Freeware
5 //    Copyright J Brown 2001
6 //
7 
8 #include "cardlib.h"
9 
10 #include <tchar.h>
11 
12 extern HPALETTE __holdplacepal;
13 
UseNicePalette(HDC hdc,HPALETTE hPalette)14 HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette)
15 {
16     HPALETTE hOld;
17 
18     hOld = SelectPalette(hdc, hPalette, FALSE);
19     RealizePalette(hdc);
20 
21     return hOld;
22 }
23 
RestorePalette(HDC hdc,HPALETTE hOldPal)24 void RestorePalette(HDC hdc, HPALETTE hOldPal)
25 {
26     SelectPalette(hdc, hOldPal, TRUE);
27 }
28 
29 HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours);
30 void     PaintRect(HDC hdc, RECT *rect, COLORREF colour);
31 HBITMAP  CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height);
32 void     GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2);
33 
34 void     LoadCardBitmaps();
35 void     FreeCardBitmaps();
36 
37 static TCHAR szCardName[]   = _T("CardWnd32");
38 static bool  fRegistered    = false;
39 static LONG  uCardBitmapRef = 0;
40 
41 
RegisterCardWindow()42 void RegisterCardWindow()
43 {
44     WNDCLASSEX wc;
45 
46     //Window class for the main application parent window
47     wc.cbSize            = sizeof(wc);
48     wc.style            = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
49     wc.lpfnWndProc        = CardWindow::CardWndProc;
50     wc.cbClsExtra        = 0;
51     wc.cbWndExtra        = sizeof(CardWindow *);
52     wc.hInstance        = GetModuleHandle(0);
53     wc.hIcon            = 0;
54     wc.hCursor            = LoadCursor (NULL, IDC_ARROW);
55     wc.hbrBackground    = 0;
56     wc.lpszMenuName        = 0;
57     wc.lpszClassName    = szCardName;
58     wc.hIconSm            = 0;
59 
60     RegisterClassEx(&wc);
61 }
62 
CardWindow()63 CardWindow::CardWindow() : m_hWnd(0)
64 {
65     HDC hdc = GetDC(0);
66 
67     nNumButtons       = 0;
68     nNumCardRegions   = 0;
69     nNumDropZones     = 0;
70     nBackCardIdx      = 53;
71 
72     ResizeWndCallback = 0;
73     hbmBackImage      = 0;
74     hdcBackImage      = 0;
75 
76     srand((unsigned)GetTickCount());
77 
78     //All colours (buttons, highlights, decks)
79     //are calculated off this single base colour
80     crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100);
81 
82     // If uCardBitmapRef was previously zero, then
83     // load the card bitmaps
84     if(1 == InterlockedIncrement(&uCardBitmapRef))
85     {
86         LoadCardBitmaps();
87 
88         __hPalette  = CreateCardPalette();
89 
90         __hdcPlaceHolder  = CreateCompatibleDC(hdc);
91 
92         __holdplacepal  = UseNicePalette(__hdcPlaceHolder, __hPalette);
93 
94         __hbmPlaceHolder  = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
95 
96     }
97 
98     ReleaseDC(0, hdc);
99 
100     //register the window class if necessary
101     if(!fRegistered)
102     {
103         fRegistered = true;
104         RegisterCardWindow();
105     }
106 
107 }
108 
Create(HWND hwndParent,DWORD dwExStyle,DWORD dwStyle,int x,int y,int width,int height)109 BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height)
110 {
111     if(m_hWnd)
112         return FALSE;
113 
114     //Create the window associated with this object
115     m_hWnd = CreateWindowEx(dwExStyle, szCardName, NULL,
116                             dwStyle,
117                             x, y, width, height,
118                             hwndParent, NULL, GetModuleHandle(NULL), this);
119 
120     return TRUE;
121 }
122 
Destroy()123 BOOL CardWindow::Destroy()
124 {
125     DestroyWindow(m_hWnd);
126     m_hWnd = 0;
127 
128     return TRUE;
129 }
130 
~CardWindow()131 CardWindow::~CardWindow()
132 {
133     if(m_hWnd)
134         DestroyWindow(m_hWnd);
135 
136     DeleteAll();
137 
138     if(0 == InterlockedDecrement(&uCardBitmapRef))
139     {
140         FreeCardBitmaps();
141 
142         DeleteObject(__hbmPlaceHolder);
143         DeleteDC    (__hdcPlaceHolder);
144 
145         RestorePalette(__hdcPlaceHolder, __holdplacepal);
146 
147         if(__hPalette)
148             DeleteObject(__hPalette);
149     }
150 }
151 
DeleteAll()152 bool CardWindow::DeleteAll()
153 {
154     int i;
155 
156     for(i = 0; i < nNumCardRegions; i++)
157     {
158         delete Regions[i];
159     }
160 
161     for(i = 0; i < nNumButtons; i++)
162     {
163         delete Buttons[i];
164     }
165 
166     for(i = 0; i < nNumDropZones; i++)
167     {
168         delete dropzone[i];
169     }
170 
171     nNumCardRegions = nNumButtons = nNumDropZones = 0;
172 
173     return true;
174 }
175 
SetBackColor(COLORREF cr)176 void CardWindow::SetBackColor(COLORREF cr)
177 {
178     crBackgnd = cr;
179     int i;
180 
181     //
182     // Create the exact palette we need to render the buttons/stacks
183     //
184     RestorePalette(__hdcPlaceHolder, __holdplacepal);
185 
186     if(__hPalette)
187         DeleteObject(__hPalette);
188 
189     __hPalette = CreateCardPalette();
190 
191     //
192     // re-create the place-holder!
193     HDC hdc = GetDC(m_hWnd);
194 
195     DeleteObject(__hbmPlaceHolder);
196 
197     __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette);
198 
199     __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight);
200     //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder);
201 
202     //reset all buttons to same colour
203     for(i = 0; i < nNumButtons; i++)
204     {
205         if(Buttons[i]->GetStyle() & CB_PUSHBUTTON)
206         {
207             Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1));
208         }
209         else
210         {
211             Buttons[i]->SetBackColor(crBackgnd);
212         }
213     }
214 
215     for(i = 0; i < nNumCardRegions; i++)
216     {
217         Regions[i]->SetBackColor(crBackgnd);
218     }
219 
220 
221     ReleaseDC(m_hWnd, hdc);
222 }
223 
GetBackColor()224 COLORREF CardWindow::GetBackColor()
225 {
226     return crBackgnd;
227 }
228 
CardButtonFromPoint(int x,int y)229 CardButton* CardWindow::CardButtonFromPoint(int x, int y)
230 {
231     CardButton *bptr = 0;
232 
233     POINT pt;
234     pt.x = x;
235     pt.y = y;
236 
237     //Search BACKWARDS...to reflect the implicit Z-order that
238     //the button creation provided
239     for(int i = nNumButtons - 1; i >= 0; i--)
240     {
241         bptr = Buttons[i];
242         if(PtInRect(&bptr->rect, pt) && bptr->fVisible)
243             return bptr;
244     }
245 
246     return 0;
247 }
248 
CardRegionFromPoint(int x,int y)249 CardRegion* CardWindow::CardRegionFromPoint(int x, int y)
250 {
251     POINT pt;
252     pt.x = x;
253     pt.y = y;
254 
255     //Search BACKWARDS...to reflect the implicit Z-order that
256     //the stack creation provided
257     for(int i = nNumCardRegions - 1; i >= 0; i--)
258     {
259         if(Regions[i]->IsPointInStack(x, y))
260             return Regions[i];
261     }
262 
263     return 0;
264 }
265 
266 //
267 //    Forward all window messages onto the appropriate
268 //  class instance
269 //
CardWndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)270 LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
271 {
272     CardWindow *cw = (CardWindow *)GetWindowLongPtr(hwnd, 0);
273     return cw->WndProc(hwnd, iMsg, wParam, lParam);
274 }
275 
Paint(HDC hdc)276 void CardWindow::Paint(HDC hdc)
277 {
278     int i;
279     RECT rect;
280     HPALETTE hOldPal;
281 
282     hOldPal = UseNicePalette(hdc, __hPalette);
283 
284     //
285     //    Clip the card stacks so that they won't
286     //    get painted over
287     //
288     for(i = 0; i < nNumCardRegions; i++)
289     {
290         Regions[i]->Clip(hdc);
291     }
292 
293     //
294     //    Clip the buttons
295     //
296     for(i = 0; i < nNumButtons; i++)
297     {
298         Buttons[i]->Clip(hdc);
299     }
300 
301 
302     //    Now paint the whole screen with background colour,
303     //
304     GetClientRect(m_hWnd, &rect);
305 
306     //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
307     PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0);
308     SelectClipRgn(hdc, NULL);
309 
310     //    Don't let cards draw over buttons, so clip buttons again
311     //
312     for(i = 0; i < nNumButtons; i++)
313     {
314         Buttons[i]->Clip(hdc);
315     }
316 
317     //    Paint each card stack in turn
318     //
319     for(i = 0; i < nNumCardRegions; i++)
320     {
321         Regions[i]->Render(hdc);
322     }
323 
324     //    Paint each button now
325     //
326     SelectClipRgn(hdc, NULL);
327 
328     for(i = 0; i < nNumButtons; i++)
329     {
330         Buttons[i]->Redraw();
331     }
332 
333     RestorePalette(hdc, hOldPal);
334 }
335 
336 
337 
338 
WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)339 LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
340 {
341     HDC hdc;
342     PAINTSTRUCT ps;
343 
344     CREATESTRUCT *cs;
345 
346     static CardButton *buttonptr   = 0;
347     static CardRegion *stackptr    = 0;
348 
349     int x, y, i;
350 
351     switch(iMsg)
352     {
353     case WM_NCCREATE:
354 
355         // When we created this window, we passed in the
356         // pointer to the class object (CardWindow *) in the
357         // call to CreateWindow.
358         cs = (CREATESTRUCT *)lParam;
359 
360         //
361         // associate this class with the window
362         //
363         SetWindowLongPtr(hwnd, 0, (LONG_PTR)cs->lpCreateParams);
364 
365         return 1;
366 
367     case WM_NCDESTROY:
368         // Don't delete anything here..
369         break;
370 
371     case WM_SIZE:
372         nWidth = LOWORD(lParam);
373         nHeight = HIWORD(lParam);
374 
375         //
376         // reposition all the stacks and buttons
377         // in case any of them are centered, right-justified etc
378         //
379         for(i = 0; i < nNumCardRegions; i++)
380         {
381             Regions[i]->AdjustPosition(nWidth, nHeight);
382         }
383 
384         for(i = 0; i < nNumButtons; i++)
385         {
386             Buttons[i]->AdjustPosition(nWidth, nHeight);
387         }
388 
389         //
390         // Call the user-defined resize proc AFTER all the stacks
391         // have been positioned
392         //
393         if(ResizeWndCallback)
394             ResizeWndCallback(nWidth, nHeight);
395 
396         return 0;
397 
398     case WM_PAINT:
399 
400         hdc = BeginPaint(hwnd, &ps);
401 
402         Paint(hdc);
403 
404         EndPaint(hwnd, &ps);
405         return 0;
406 
407     case WM_TIMER:
408 
409         //find the timer object in the registered funcs
410         /*if(wParam >= 0x10000)
411         {
412             for(i = 0; i < nRegFuncs; i++)
413             {
414                 if(RegFuncs[i].id == wParam)
415                 {
416                     KillTimer(hwnd, wParam);
417 
418                     //call the registered function!!
419                     RegFuncs[i].func(RegFuncs[i].dwParam);
420 
421                     RegFuncs[i] = RegFuncs[nRegFuncs-1];
422                     nRegFuncs--;
423                 }
424             }
425         }
426         else*/
427         {
428             //find the cardstack
429             CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam);
430             stackobj->DoFlash();
431         }
432 
433         return 0;
434 
435     case WM_LBUTTONDBLCLK:
436 
437         x = (short)LOWORD(lParam);
438         y = (short)HIWORD(lParam);
439 
440         if((buttonptr = CardButtonFromPoint(x, y)) != 0)
441         {
442             buttonptr->OnLButtonDown(hwnd, x, y);
443             return 0;
444         }
445 
446         if((stackptr = CardRegionFromPoint(x, y)) != 0)
447         {
448             stackptr->OnLButtonDblClk(x, y);
449             stackptr = 0;
450         }
451 
452         return 0;
453 
454     case WM_LBUTTONDOWN:
455 
456         x = (short)LOWORD(lParam);
457         y = (short)HIWORD(lParam);
458 
459         //if clicked on a button
460         if((buttonptr = CardButtonFromPoint(x, y)) != 0)
461         {
462             if(buttonptr->OnLButtonDown(hwnd, x, y) == 0)
463                 buttonptr = 0;
464 
465             return 0;
466         }
467 
468         if((stackptr = CardRegionFromPoint(x, y)) != 0)
469         {
470             if(!stackptr->OnLButtonDown(x, y))
471                 stackptr = 0;
472         }
473 
474         return 0;
475 
476     case WM_LBUTTONUP:
477 
478         x = (short)LOWORD(lParam);
479         y = (short)HIWORD(lParam);
480 
481         //
482         // if we were clicking a button
483         //
484         if(buttonptr != 0)
485         {
486             buttonptr->OnLButtonUp(hwnd, x, y);
487             buttonptr = 0;
488             return 0;
489         }
490 
491         if(stackptr != 0)
492         {
493             stackptr->OnLButtonUp(x, y);
494             stackptr = 0;
495             return 0;
496         }
497 
498         if ((stackptr = CardRegionFromPoint(x, y)) != 0)
499         {
500             stackptr->ClickRelease(x, y);
501             stackptr = 0;
502         }
503 
504         return 0;
505 
506     case WM_MOUSEMOVE:
507 
508         x = (short)LOWORD(lParam);
509         y = (short)HIWORD(lParam);
510 
511         // if we were clicking a button
512         if(buttonptr != 0)
513         {
514             buttonptr->OnMouseMove(hwnd, x, y);
515             return 0;
516         }
517 
518         if(stackptr != 0)
519         {
520             return stackptr->OnMouseMove(x, y);
521         }
522 
523         return 0;
524 
525     }
526 
527       return DefWindowProc (hwnd, iMsg, wParam, lParam);
528 }
529 
530 
CardRegionFromId(int id)531 CardRegion* CardWindow::CardRegionFromId(int id)
532 {
533     for(int i = 0; i < nNumCardRegions; i++)
534     {
535         if(Regions[i]->id == id)
536             return Regions[i];
537     }
538 
539     return 0;
540 }
541 
CardButtonFromId(int id)542 CardButton* CardWindow::CardButtonFromId(int id)
543 {
544     for(int i = 0; i < nNumButtons; i++)
545     {
546         if(Buttons[i]->id == id)
547             return Buttons[i];
548     }
549 
550     return 0;
551 }
552 
Redraw()553 void CardWindow::Redraw()
554 {
555     InvalidateRect(m_hWnd, 0, 0);
556     UpdateWindow(m_hWnd);
557 }
558 
DeleteButton(CardButton * pButton)559 bool CardWindow::DeleteButton(CardButton *pButton)
560 {
561     for(int i = 0; i < nNumButtons; i++)
562     {
563         if(Buttons[i] == pButton)
564         {
565             CardButton *cb = Buttons[i];
566 
567             //shift any after this one backwards
568             for(int j = i; j < nNumButtons - 1; j++)
569             {
570                 Buttons[j] = Buttons[j + 1];
571             }
572 
573             delete cb;
574             nNumButtons--;
575 
576             return true;
577         }
578     }
579 
580     return false;
581 }
582 
DeleteRegion(CardRegion * pRegion)583 bool CardWindow::DeleteRegion(CardRegion *pRegion)
584 {
585     for(int i = 0; i < nNumCardRegions; i++)
586     {
587         if(Regions[i] == pRegion)
588         {
589             CardRegion *cr = Regions[i];
590 
591             //shift any after this one backwards
592             for(int j = i; j < nNumCardRegions - 1; j++)
593             {
594                 Regions[j] = Regions[j + 1];
595             }
596 
597             delete cr;
598             nNumCardRegions--;
599 
600             return true;
601         }
602     }
603 
604     return false;
605 }
606 
EmptyStacks(void)607 void CardWindow::EmptyStacks(void)
608 {
609     for(int i = 0; i < nNumCardRegions; i++)
610     {
611         Regions[i]->Clear();
612         Regions[i]->Update();
613     }
614 
615     Redraw();
616 }
617 
DistributeStacks(int nIdFrom,int nNumStacks,UINT xJustify,int xSpacing,int nStartX)618 bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX)
619 {
620     int numvisiblestacks = 0;
621     int curx = nStartX;
622     int startindex = -1;
623     int i;
624 
625     //find the stack which starts with our ID
626     for(i = 0; i < nNumCardRegions; i++)
627     {
628         if(Regions[i]->Id() == nIdFrom)
629         {
630             startindex = i;
631             break;
632         }
633     }
634 
635     //if didn't find, return
636     if(i == nNumCardRegions) return false;
637 
638     //count the stacks that are visible
639     for(i = startindex; i < startindex + nNumStacks; i++)
640     {
641         if(Regions[i]->IsVisible())
642             numvisiblestacks++;
643     }
644 
645     if(xJustify == CS_XJUST_CENTER)
646     {
647         //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2;
648         int viswidth;
649         viswidth = numvisiblestacks * __cardwidth;
650         viswidth += xSpacing * (numvisiblestacks - 1);
651         curx = -(viswidth  - __cardwidth) / 2;
652 
653         for(i = startindex; i < startindex + nNumStacks; i++)
654         {
655             if(Regions[i]->IsVisible())
656             {
657                 Regions[i]->xadjust = curx;
658                 Regions[i]->xjustify = CS_XJUST_CENTER;
659                 curx += Regions[i]->width + xSpacing;
660             }
661 
662         }
663     }
664 
665     if(xJustify == CS_XJUST_RIGHT)
666     {
667         nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing);
668     }
669 
670     if(xJustify == CS_XJUST_NONE)
671     {
672         for(i = startindex; i < startindex + nNumStacks; i++)
673         {
674             if(Regions[i]->IsVisible())
675             {
676                 Regions[i]->xpos = curx;
677                 curx += Regions[i]->width + xSpacing;
678                 Regions[i]->UpdateSize();
679             }
680 
681         }
682     }
683 
684     return 0;
685 }
686 
Update()687 void CardWindow::Update()
688 {
689     for(int i = 0; i < nNumCardRegions; i++)
690     {
691         Regions[i]->AdjustPosition(nWidth, nHeight);
692     }
693 }
694 
695 
SetResizeProc(pResizeWndProc proc)696 void CardWindow::SetResizeProc(pResizeWndProc proc)
697 {
698     ResizeWndCallback = proc;
699 }
700 
701 
CreateCardPalette()702 HPALETTE CardWindow::CreateCardPalette()
703 {
704     COLORREF cols[10];
705     int nNumCols;
706 
707 
708     //include button text colours
709     cols[0] = RGB(0, 0, 0);
710     cols[1] = RGB(255, 255, 255);
711 
712     //include the base background colour
713     cols[2] = crBackgnd;
714 
715     //include the standard button colours...
716     cols[3] = CardButton::GetHighlight(crBackgnd);
717     cols[4] = CardButton::GetShadow(crBackgnd);
718     cols[5] = CardButton::GetFace(crBackgnd);
719 
720     //include the sunken image bitmap colours...
721     GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]);
722 
723     nNumCols = 10;
724 
725     return MakePaletteFromCols(cols, nNumCols);
726 }
727 
SetBackCardIdx(UINT uBackIdx)728 void CardWindow::SetBackCardIdx(UINT uBackIdx)
729 {
730     if(uBackIdx >= 52 && uBackIdx <= 68)
731         nBackCardIdx = uBackIdx;
732 
733     for(int i = 0; i < nNumCardRegions; i++)
734         Regions[i]->SetBackCardIdx(uBackIdx);
735 
736 }
737 
GetBackCardIdx()738 UINT CardWindow::GetBackCardIdx()
739 {
740     return nBackCardIdx;
741 }
742 
PaintCardRgn(HDC hdc,int dx,int dy,int width,int height,int sx,int sy)743 void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy)
744 {
745     RECT rect;
746 
747     //if just a solid background colour
748     if(hbmBackImage == 0)
749     {
750         SetRect(&rect, dx, dy, dx+width, dy+height);
751 
752         /*if(GetVersion() < 0x80000000)
753         {
754             PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
755         }
756         else*/
757         {
758             HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd));
759             FillRect(hdc, &rect, hbr);
760             DeleteObject(hbr);
761         }
762     }
763     //otherwise, paint using the bitmap
764     else
765     {
766         // Draw whatever part of background we can
767         BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY);
768 
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)
772         {
773             // Find out size of bitmap
774             BITMAP bm;
775             GetObject(hbmBackImage, sizeof(bm), &bm);
776 
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);
781 
782             CombineRgn(hr3, hr1, hr2, RGN_DIFF);
783 
784             GetClipRgn(hdc, hr4);
785 
786             CombineRgn(hr3, hr4, hr3, RGN_AND);
787             SelectClipRgn(hdc, hr3);
788 
789             // Fill remaining space not filled with bitmap
790             HBRUSH hbr = CreateSolidBrush(crBackgnd);
791             FillRgn(hdc, hr3, hbr);
792             DeleteObject(hbr);
793 
794             // Clean up
795             SelectClipRgn(hdc, hr4);
796 
797             DeleteObject(hr1);
798             DeleteObject(hr2);
799             DeleteObject(hr3);
800             DeleteObject(hr4);
801         }
802     }
803 }
804 
SetBackImage(HBITMAP hBitmap)805 void CardWindow::SetBackImage(HBITMAP hBitmap)
806 {
807     //delete current image?? NO!
808     if(hdcBackImage == 0)
809     {
810         hdcBackImage = CreateCompatibleDC(0);
811     }
812 
813     hbmBackImage = hBitmap;
814 
815     if(hBitmap)
816         SelectObject(hdcBackImage, hBitmap);
817 }
818