nt-makefile-clean-targets-20010917
[openafs.git] / src / WINNT / afsapplib / al_wizard.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include <WINNT/al_wizard.h>
16
17
18 /*
19  * DEFINITIONS ________________________________________________________________
20  *
21  */
22
23 #define REFRESH_LEFT_PANE   0x00000001
24 #define REFRESH_RIGHT_PANE  0x00000002
25
26 #define cxRECT(_r)  ((_r).right - (_r).left)
27 #define cyRECT(_r)  ((_r).bottom - (_r).top)
28
29 #define clrWASH_SOLID       RGB(0,0,128)
30 #define clrWASH_BRIGHTEST   RGB(0,0,252)
31 #define clrWASH_DARKEST     RGB(0,0,4)
32 #define clrWASH_INCREMENT   RGB(0,0,4)
33 #define clrWASH_TEXT_BG     RGB(0,0,0)
34 #define clrWASH_TEXT_FG     RGB(255,255,255)
35
36 #define ToPALETTERGB(_rgb)  PALETTERGB(GetRValue(_rgb),GetGValue(_rgb),GetBValue(_rgb))
37
38 #define cxLEFT_BACKGROUND    20
39 #define cxRIGHT_BACKGROUND   20
40 #define cyTOP_BACKGROUND     20
41 #define cyBOTTOM_BACKGROUND  20
42
43 #define xTEXT                30
44 #define yTEXT                30
45 #define cxSHADOW              2
46 #define cySHADOW              2
47
48 #define cptWASH_TEXT_SIZE    20
49
50
51 /*
52  * PROTOTYPES _________________________________________________________________
53  *
54  */
55
56 static void MoveRect (RECT *_pr, LONG _dx, LONG _dy);
57 static void GetRectInParent (HWND hWnd, RECT *pr);
58
59
60 /*
61  * ROUTINES ___________________________________________________________________
62  *
63  */
64
65
66 WIZARD::WIZARD (void)
67 {
68    m_iddTemplate = -1;
69    m_idcLeftPane = -1;
70    m_idcRightPane = -1;
71    m_idcBack = -1;
72    m_idcNext = -1;
73    m_idbGraphic16 = -1;
74    m_bmpGraphic16 = NULL;
75    m_idbGraphic256 = -1;
76    m_bmpGraphic256 = NULL;
77    m_palGraphic = NULL;
78    m_aStates = NULL;
79    m_cStates = 0;
80    m_stCurrent = -1;
81    m_fShowing = FALSE;
82    m_hWnd = NULL;
83
84    m_iddBackground = -1;
85    m_hBkg = NULL;
86    m_fBlue = TRUE;
87    m_fnBackground = NULL;
88    m_szBackground[0] = TEXT('\0');
89    m_bmpBackground = NULL;
90    m_pfnCallback = NULL;
91    m_bmpBuffer = NULL;
92    SetRectEmpty (&m_rBuffer);
93
94    HDC hdc = GetDC (NULL);
95    LOGFONT lf;
96    memset (&lf, 0x00, sizeof(lf));
97    GetObject (GetStockObject (DEFAULT_GUI_FONT), sizeof(lf), &lf);
98    lf.lfHeight = -MulDiv (cptWASH_TEXT_SIZE, GetDeviceCaps (hdc, LOGPIXELSY), 72);
99    lf.lfWidth = 0;
100    m_hfBackground = CreateFontIndirect (&lf);
101    ReleaseDC (NULL, hdc);
102
103    GeneratePalette();
104 }
105
106
107 WIZARD::~WIZARD (void)
108 {
109    if (m_hWnd && IsWindow (m_hWnd))
110       DestroyWindow (m_hWnd);
111    if (m_bmpGraphic16 != NULL)
112       DeleteObject (m_bmpGraphic16);
113    if (m_bmpGraphic256 != NULL)
114       DeleteObject (m_bmpGraphic256);
115    if (m_bmpBuffer != NULL)
116       DeleteObject (m_bmpBuffer);
117    if (m_palGraphic != NULL)
118       DeleteObject (m_palGraphic);
119    if (m_bmpBackground != NULL)
120       DeleteObject (m_bmpBackground);
121    if (m_hfBackground != NULL)
122       DeleteObject (m_hfBackground);
123 }
124
125
126 HWND WIZARD::GetWindow (void)
127 {
128    if (m_hWnd && IsWindow (m_hWnd))
129       return m_hWnd;
130    return NULL;
131 }
132
133
134 LPWIZARD WIZARD::GetWizard (HWND hWnd)
135 {
136    LPWIZARD pWiz = NULL;
137
138    try {
139       if ((pWiz = (LPWIZARD)GetWindowLong (hWnd, DWL_USER)) != NULL)
140          {
141          if ( (pWiz->m_hWnd != hWnd) && (pWiz->m_hBkg != hWnd) )
142             pWiz = NULL;
143          }
144    } catch(...) {
145       pWiz = NULL;
146    }
147
148    return pWiz;
149 }
150
151
152 void WIZARD::SetDialogTemplate (int iddTemplate, int idcLeftPane, int idcRightPane, int idcBack, int idcNext)
153 {
154    m_iddTemplate = iddTemplate;
155    m_idcLeftPane = idcLeftPane;
156    m_idcRightPane = idcRightPane;
157    m_idcBack = idcBack;
158    m_idcNext = idcNext;
159
160    if (m_fShowing)
161       {
162       Show (FALSE);
163       Show (TRUE);
164       }
165 }
166
167
168 void WIZARD::SetGraphic (int idbGraphic16, int idbGraphic256)
169 {
170    LPRGBQUAD pargb = NULL;
171
172    m_idbGraphic16 = idbGraphic16;
173    m_idbGraphic256 = idbGraphic256;
174
175    if (m_bmpGraphic16 != NULL)
176       {
177       DeleteObject (m_bmpGraphic16);
178       m_bmpGraphic16 = NULL;
179       }
180
181    if (m_bmpGraphic256 != NULL)
182       {
183       DeleteObject (m_bmpGraphic256);
184       m_bmpGraphic256 = NULL;
185       }
186
187    if (m_palGraphic != NULL)
188       {
189       DeleteObject (m_palGraphic);
190       m_palGraphic = NULL;
191       }
192
193    m_bmpGraphic16 = (HBITMAP)TaLocale_LoadImage (idbGraphic16, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
194
195    if ((m_bmpGraphic256 = (HBITMAP)TaLocale_LoadImage (idbGraphic256, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION)) != NULL)
196       {
197       BITMAP bm;
198       GetObject (m_bmpGraphic256, sizeof(BITMAP), &bm);
199
200       if ((bm.bmBitsPixel * bm.bmPlanes) == 8)
201          {
202          HDC hdc = CreateCompatibleDC (NULL);
203          HBITMAP bmpOld = (HBITMAP)SelectObject (hdc, m_bmpGraphic256);
204
205          RGBQUAD argb[256];
206          GetDIBColorTable (hdc, 0, 256, argb);
207          pargb = argb;
208
209          SelectObject (hdc, bmpOld);
210          DeleteDC (hdc);
211          }
212       }
213
214    GeneratePalette (pargb);
215
216    if (m_fShowing)
217       {
218       Refresh (REFRESH_LEFT_PANE);
219       }
220 }
221
222
223 void WIZARD::SetGraphicCallback (void (CALLBACK *pfnCallback)(LPWIZARD pWiz, HDC hdcTarget, LPRECT prTarget, HPALETTE hPal))
224 {
225    m_pfnCallback = pfnCallback;
226
227    if (m_fShowing)
228       {
229       Refresh (REFRESH_LEFT_PANE);
230       }
231 }
232
233
234 void WIZARD::SetStates (LPWIZARD_STATE aStates, size_t cStates)
235 {
236    m_aStates = aStates;
237    m_cStates = cStates;
238
239    if (m_fShowing)
240       {
241       Refresh (REFRESH_RIGHT_PANE);
242       }
243 }
244
245
246 int WIZARD::GetState (void)
247 {
248    return m_stCurrent;
249 }
250
251
252 void WIZARD::SetState (int stNew, BOOL fForce)
253 {
254    SendStateCommand (m_stCurrent, wcSTATE_LEAVE);
255
256    int stOriginal = m_stCurrent;
257    m_stCurrent = stNew;
258
259    if (!fForce && SendStateCommand (stNew, wcIS_STATE_DISABLED))
260       {
261       if (stOriginal <= stNew)
262          {
263          for (int st = stNew+1; st < (int)m_cStates; ++st)
264             {
265             LPWIZARD_STATE pState;
266             if ((pState = FindState (st)) != NULL)
267                {
268                m_stCurrent = st;
269                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
270                   break;
271                m_stCurrent = stOriginal;
272                SendStateCommand (st, wcSTATE_ENTER);
273                SendStateCommand (st, wcSTATE_LEAVE);
274                }
275             }
276          stNew = (st < (int)m_cStates) ? st : m_stCurrent;
277          }
278       else // (moving backwards?)
279          {
280          for (int st = stNew-1; st >= 0; --st)
281             {
282             LPWIZARD_STATE pState;
283             if ((pState = FindState (st)) != NULL)
284                {
285                m_stCurrent = st;
286                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
287                   break;
288                m_stCurrent = stOriginal;
289                SendStateCommand (st, wcSTATE_ENTER);
290                SendStateCommand (st, wcSTATE_LEAVE);
291                }
292             }
293          stNew = (st >= 0) ? st : m_stCurrent;
294          }
295       }
296
297    m_stCurrent = stNew;
298
299    SendStateCommand (m_stCurrent, wcSTATE_ENTER);
300
301    if (m_fShowing)
302       {
303       Refresh (REFRESH_RIGHT_PANE);
304       }
305 }
306
307
308 BOOL WIZARD::Show (BOOL fShowReq)
309 {
310    if (m_fShowing && !fShowReq)
311       {
312       m_fShowing = FALSE;
313       if (m_hWnd && IsWindow (m_hWnd))
314          DestroyWindow (m_hWnd);
315       m_hWnd = NULL;
316       }
317    else if (!m_fShowing && fShowReq)
318       {
319       if (m_iddTemplate == -1)
320          return FALSE;
321       if (m_idcLeftPane == -1)
322          return FALSE;
323       if (m_idcRightPane == -1)
324          return FALSE;
325       if (m_idcBack == -1)
326          return FALSE;
327       if (m_idcNext == -1)
328          return FALSE;
329
330       if ((m_hWnd = ModelessDialogParam (m_iddTemplate, m_hBkg, (DLGPROC)WIZARD::Template_DlgProc, (LPARAM)this)) == NULL)
331          return FALSE;
332       m_fShowing = TRUE;
333
334       MSG msg;
335       while (GetMessage (&msg, 0, 0, NULL))
336          {
337          if (!IsDialogMessage (m_hWnd, &msg))
338             {
339             TranslateMessage (&msg);
340             DispatchMessage (&msg);
341             }
342
343          if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
344             break;
345          }
346       }
347
348    return TRUE;
349 }
350
351
352 void WIZARD::EnableButton (int idcButton, BOOL fEnable)
353 {
354    EnableWindow (GetDlgItem (m_hWnd, idcButton), fEnable);
355 }
356
357
358 void WIZARD::EnableButtons (DWORD dwButtonFlags)
359 {
360    EnableWindow (GetDlgItem (m_hWnd, m_idcBack), (dwButtonFlags & BACK_BUTTON) ? TRUE : FALSE);
361    EnableWindow (GetDlgItem (m_hWnd, m_idcNext), (dwButtonFlags & NEXT_BUTTON) ? TRUE : FALSE);
362 }
363
364
365 void WIZARD::SetButtonText (int idcButton, int idsText)
366 {
367    HWND hButton;
368    if ((hButton = GetDlgItem (m_hWnd, idcButton)) != NULL)
369       {
370       TCHAR szText[ cchRESOURCE ];
371       GetString (szText, idsText);
372       SetWindowText (hButton, szText);
373       }
374 }
375
376
377 void WIZARD::SetDefaultControl (int idc)
378 {
379    HWND hControl;
380    if ((hControl = GetDlgItem (m_hWnd, idc)) == NULL)
381       {
382       HWND hRHS;
383       if ((hRHS = GetRightHandWindow()) != NULL)
384          hControl = GetDlgItem (hRHS, idc);
385       }
386
387    if (hControl)
388       {
389       PostMessage (m_hWnd, WM_NEXTDLGCTL, (WPARAM)hControl, TRUE);
390       }
391 }
392
393
394 void WIZARD::SetBackground (int iddBackground, BOOL fBlue, DLGPROC dlgproc)
395 {
396    m_iddBackground = iddBackground;
397    m_fBlue = fBlue;
398    m_fnBackground = dlgproc;
399
400    if (m_hBkg && IsWindow (m_hBkg))
401       {
402       ShowBackground (FALSE);
403       ShowBackground (TRUE);
404       }
405 }
406
407
408 void WIZARD::SetBackgroundText (int idsText, HFONT hf)
409 {
410    GetString (m_szBackground, idsText);
411
412    if ((hf != NULL) && (hf != m_hfBackground))
413       {
414       if (m_hfBackground != NULL)
415          DeleteObject (m_hfBackground);
416       m_hfBackground = hf;
417       }
418
419    if (m_hBkg && IsWindow (m_hBkg))
420       {
421       Background_OnSize();
422       }
423 }
424
425
426 void WIZARD::SetBackgroundText (LPTSTR pszText, HFONT hf)
427 {
428    if (!pszText)
429       m_szBackground[0] = TEXT('\0');
430    else
431       lstrcpy (m_szBackground, pszText);
432
433    if ((hf != NULL) && (hf != m_hfBackground))
434       {
435       if (m_hfBackground != NULL)
436          DeleteObject (m_hfBackground);
437       m_hfBackground = hf;
438       }
439
440    if (m_hBkg && IsWindow (m_hBkg))
441       {
442       Background_OnSize();
443       }
444 }
445
446
447 BOOL WIZARD::ShowBackground (BOOL fShow)
448 {
449    if (!fShow && m_hBkg && IsWindow (m_hBkg))
450       {
451       DestroyWindow (m_hBkg);
452       m_hBkg = NULL;
453       }
454    else if (fShow && !(m_hBkg && IsWindow (m_hBkg)))
455       {
456       if ((m_hBkg = ModelessDialogParam (m_iddBackground, NULL, (DLGPROC)WIZARD::Background_DlgProc, (LPARAM)this)) == NULL)
457          return FALSE;
458
459       RECT rDesktop;
460       SystemParametersInfo (SPI_GETWORKAREA, 0, &rDesktop, 0);
461
462       WINDOWPLACEMENT wpl;
463       wpl.length = sizeof(wpl);
464       wpl.flags = 0;
465       wpl.showCmd = (GetWindowLong (m_hBkg, GWL_STYLE) & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOW;
466       wpl.ptMinPosition.x = 0;
467       wpl.ptMinPosition.y = 0;
468       wpl.ptMaxPosition.x = 0;
469       wpl.ptMaxPosition.y = 0;
470       wpl.rcNormalPosition.left = rDesktop.left + cxLEFT_BACKGROUND;
471       wpl.rcNormalPosition.right = rDesktop.right - cxRIGHT_BACKGROUND;
472       wpl.rcNormalPosition.top = rDesktop.top + cyTOP_BACKGROUND;
473       wpl.rcNormalPosition.bottom = rDesktop.bottom - cyBOTTOM_BACKGROUND;
474       SetWindowPlacement (m_hBkg, &wpl);
475       }
476
477    return TRUE;
478 }
479
480
481 HWND WIZARD::GetBackgroundWindow (void)
482 {
483    return m_hBkg;
484 }
485
486
487 void WIZARD::Refresh (DWORD dwRefFlags)
488 {
489    if (dwRefFlags & REFRESH_LEFT_PANE)
490       {
491       HWND hLHS;
492       if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
493          {
494          RECT rr;
495          GetClientRect (hLHS, &rr);
496          InvalidateRect (hLHS, &rr, TRUE);
497          UpdateWindow (hLHS);
498          }
499       }
500
501    if (dwRefFlags & REFRESH_RIGHT_PANE)
502       {
503       HWND hRHS;
504       if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
505          {
506          HWND hOld = GetRightHandWindow();
507
508          LPWIZARD_STATE pState;
509          if ((pState = FindState (m_stCurrent)) != NULL)
510             {
511             int stCurrent = m_stCurrent;
512
513             HWND hNew;
514             if ((hNew = ModelessDialogParam (pState->idd, m_hWnd, pState->dlgproc, pState->lp)) != NULL)
515                {
516                if (stCurrent != m_stCurrent)
517                   DestroyWindow (hNew);
518                else
519                   {
520                   RECT rRHS;
521                   GetRectInParent (hRHS, &rRHS);
522                   SetWindowPos (hNew, NULL, rRHS.left, rRHS.top, cxRECT(rRHS), cyRECT(rRHS), SWP_NOZORDER | SWP_NOACTIVATE);
523                   SetWindowLong (hNew, GWL_ID, pState->idd);
524
525                   ShowWindow (hNew, SW_SHOW);
526                   ShowWindow (hRHS, SW_HIDE);
527                   }
528                }
529             }
530
531          if (hOld != NULL)
532             DestroyWindow (hOld);
533          }
534       }
535 }
536
537
538 HWND WIZARD::GetRightHandWindow (void)
539 {
540    if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
541       return NULL;
542
543    HWND hRHS = NULL;
544
545    for (HWND hFound = ::GetWindow (m_hWnd, GW_CHILD);
546         hFound != NULL;
547         hFound = ::GetWindow (hFound, GW_HWNDNEXT))
548       {
549       TCHAR szClassName[ cchRESOURCE ];
550       if (GetClassName (hFound, szClassName, cchRESOURCE))
551          {
552          if (!lstrcmp (szClassName, TEXT("#32770"))) // WC_DIALOG
553             {
554             if (!hRHS || IsWindowVisible(hRHS))
555                hRHS = hFound;
556             }
557          }
558       }
559
560    return hRHS;
561 }
562
563
564 void WIZARD::GeneratePalette (LPRGBQUAD argb)
565 {
566    HDC hdc = GetDC (NULL);
567    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
568    ReleaseDC (NULL, hdc);
569
570    if (wDepthDisplay == 8)
571       {
572       BYTE aPalBuffer[ sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY) ];
573       LPLOGPALETTE pPal = (LPLOGPALETTE)aPalBuffer;
574       pPal->palVersion = 0x300;
575       pPal->palNumEntries = 256;
576
577       for (size_t ii = 0; ii < 256; ++ii)
578          {
579          pPal->palPalEntry[ ii ].peRed   = (argb) ? argb[ ii ].rgbRed : 0;
580          pPal->palPalEntry[ ii ].peGreen = (argb) ? argb[ ii ].rgbGreen : 0;
581          pPal->palPalEntry[ ii ].peBlue  = (argb) ? argb[ ii ].rgbBlue : 0;
582          pPal->palPalEntry[ ii ].peFlags = 0;
583          }
584
585       for (COLORREF clr = clrWASH_DARKEST; clr <= clrWASH_BRIGHTEST; clr += clrWASH_INCREMENT)
586          {
587          for (size_t ii = 0; ii < 256; ++ii)
588             {
589             if ( (pPal->palPalEntry[ ii ].peRed   == GetRValue (clr)) &&
590                  (pPal->palPalEntry[ ii ].peGreen == GetGValue (clr)) &&
591                  (pPal->palPalEntry[ ii ].peBlue  == GetBValue (clr)) )
592                break;
593             }
594          if (ii == 256)
595             {
596             for (size_t ii = 10; ii < 246; ++ii)
597                {
598                if ( (pPal->palPalEntry[ ii ].peRed == 0) &&
599                     (pPal->palPalEntry[ ii ].peGreen == 0) &&
600                     (pPal->palPalEntry[ ii ].peBlue == 0) )
601                   break;
602                if ( (pPal->palPalEntry[ ii ].peRed == 255) &&
603                     (pPal->palPalEntry[ ii ].peGreen == 255) &&
604                     (pPal->palPalEntry[ ii ].peBlue == 255) )
605                   break;
606                }
607             if (ii == 246)
608                break;
609
610             pPal->palPalEntry[ ii ].peRed   = GetRValue (clr);
611             pPal->palPalEntry[ ii ].peGreen = GetGValue (clr);
612             pPal->palPalEntry[ ii ].peBlue  = GetBValue (clr);
613             }
614          }
615
616       m_palGraphic = CreatePalette (pPal);
617       }
618 }
619
620
621 LPWIZARD_STATE WIZARD::FindState (int stFind)
622 {
623    for (size_t ii = 0; ii < m_cStates; ++ii)
624       {
625       if (m_aStates[ ii ].st == stFind)
626          return &m_aStates[ ii ];
627       }
628    return NULL;
629 }
630
631
632 BOOL WIZARD::SendStateCommand (int st, WIZARD_COMMAND wc)
633 {
634    BOOL rc = FALSE;
635
636    LPWIZARD_STATE pState;
637    if ((pState = FindState (st)) != NULL)
638       {
639       rc = CallWindowProc ((WNDPROC)(pState->dlgproc), NULL, WM_COMMAND, MAKEWPARAM(IDC_WIZARD,(WORD)wc), (LPARAM)this);
640       }
641
642    return rc;
643 }
644
645
646 BOOL CALLBACK WIZARD::Template_DlgProc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
647 {
648    if (msg == WM_INITDIALOG)
649       SetWindowLong (hWnd, DWL_USER, lp);
650
651    LPWIZARD pWiz = (LPWIZARD)GetWindowLong (hWnd, DWL_USER);
652
653    switch (msg)
654       {
655       case WM_INITDIALOG:
656          if (pWiz)
657             pWiz->Template_OnInitDialog (hWnd);
658          break;
659
660       case WM_DESTROY:
661          if (pWiz && (pWiz->m_hWnd == hWnd))
662             pWiz->Show (FALSE);
663          break;
664
665       case WM_COMMAND:
666          return pWiz->Template_ForwardMessage (hWnd, msg, wp, lp);
667       }
668
669    return FALSE;
670 }
671
672
673 BOOL CALLBACK WIZARD::Template_LeftPaneHook (HWND hLHS, UINT msg, WPARAM wp, LPARAM lp)
674 {
675    PVOID oldProc = Subclass_FindNextHook (hLHS, WIZARD::Template_LeftPaneHook);
676
677    switch (msg)
678       {
679       case WM_PAINT:
680          LPWIZARD pWiz;
681          if ((pWiz = WIZARD::GetWizard (GetParent (hLHS))) != NULL)
682             {
683             if (pWiz->Template_OnPaintLHS (hLHS))
684                return TRUE;
685             }
686          break;
687
688       case WM_DESTROY:
689          Subclass_RemoveHook (hLHS, WIZARD::Template_LeftPaneHook);
690          break;
691       }
692
693    if (oldProc)
694       return CallWindowProc ((WNDPROC)oldProc, hLHS, msg, wp, lp);
695    else
696       return DefWindowProc (hLHS, msg, wp, lp);
697 }
698
699
700 BOOL WIZARD::Template_ForwardMessage (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
701 {
702    HWND hRHS;
703    if ((hRHS = GetRightHandWindow()) != NULL)
704       return SendMessage (hRHS, msg, wp, lp);
705
706    LPWIZARD_STATE pState;
707    if ((pState = FindState (m_stCurrent)) != NULL)
708       return CallWindowProc ((WNDPROC)(pState->dlgproc), hWnd, msg, wp, lp);
709
710    return FALSE;
711 }
712
713
714 void WIZARD::Template_OnInitDialog (HWND hWnd)
715 {
716    m_hWnd = hWnd;
717    m_fShowing = TRUE;
718
719    HWND hLHS;
720    if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
721       {
722       Subclass_AddHook (hLHS, WIZARD::Template_LeftPaneHook);
723       }
724
725    HWND hRHS;
726    if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
727       {
728       ShowWindow (hRHS, SW_HIDE);
729       }
730
731    Refresh (REFRESH_RIGHT_PANE);
732
733    ShowWindow (m_hWnd, SW_SHOW);
734 }
735
736
737 BOOL WIZARD::Template_OnPaintLHS (HWND hLHS)
738 {
739    BOOL fShow16 = FALSE;
740    BOOL fShow256 = FALSE;
741
742    HDC hdc = GetDC (NULL);
743    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
744    ReleaseDC (NULL, hdc);
745
746    if ( (m_bmpGraphic256 != NULL) && (wDepthDisplay >= 8) )
747       fShow256 = TRUE;
748    else if (m_bmpGraphic16 != NULL)
749       fShow16 = TRUE;
750    else
751       return FALSE;
752
753    PAINTSTRUCT ps;
754    HDC hdcTarget;
755    if ((hdcTarget = BeginPaint (hLHS, &ps)) != NULL)
756       {
757       HBITMAP bmpSource = (fShow256) ? m_bmpGraphic256 : m_bmpGraphic16;
758
759       BITMAP bm;
760       GetObject (bmpSource, sizeof(BITMAP), &bm);
761
762       RECT rWindow;
763       GetClientRect (hLHS, &rWindow);
764
765       RECT rSource = { 0, 0, bm.bmWidth, bm.bmHeight };
766       RECT rTarget = rWindow;
767
768       if (cxRECT(rSource) > cxRECT(rTarget))
769          {
770          MoveRect (&rSource, (cxRECT(rSource) - cxRECT(rTarget)) / 2, 0);
771          rSource.right = rSource.left + cxRECT(rTarget);
772          }
773       else if (cxRECT(rSource) < cxRECT(rTarget))
774          {
775          MoveRect (&rTarget, (cxRECT(rTarget) - cxRECT(rSource)) / 2, 0);
776          }
777
778       if (cyRECT(rSource) > cyRECT(rTarget))
779          {
780          MoveRect (&rSource, 0, (cyRECT(rSource) - cyRECT(rTarget)) / 2);
781          rSource.bottom = rSource.top + cyRECT(rTarget);
782          }
783       else if (cyRECT(rSource) < cyRECT(rTarget))
784          {
785          MoveRect (&rTarget, 0, (cyRECT(rTarget) - cyRECT(rSource)) / 2);
786          }
787       rTarget.right = rTarget.left + cxRECT(rSource);
788       rTarget.bottom = rTarget.top + cyRECT(rSource);
789
790       // If the user has supplied a custom draw-proc, then we should
791       // do our rendering to an off-screen bitmap.
792       //
793       HDC hdcFinalTarget = NULL;
794       HBITMAP bmpTempTarget = NULL;
795       if (m_pfnCallback)
796          {
797          // First make sure our offscreen buffer is large enough
798          //
799          if (!m_bmpBuffer || (cxRECT(m_rBuffer) < cxRECT(rWindow)) || (cyRECT(m_rBuffer) < cyRECT(rWindow)))
800             {
801             if (m_bmpBuffer != NULL)
802                DeleteObject (m_bmpBuffer);
803             if ((m_bmpBuffer = CreateCompatibleBitmap (hdcTarget, cxRECT(rWindow), cyRECT(rWindow))) != NULL)
804                {
805                m_rBuffer.right = cxRECT(rWindow);  // m_rBuffer.left=already 0
806                m_rBuffer.bottom = cyRECT(rWindow); // m_rBuffer.top=already 0
807                }
808             }
809
810          // Then set up to double-buffer, if possible
811          //
812          if (m_bmpBuffer)
813             {
814             hdcFinalTarget = hdcTarget;
815             hdcTarget = CreateCompatibleDC (hdcFinalTarget);
816             bmpTempTarget = (HBITMAP)SelectObject (hdcTarget, m_bmpBuffer);
817             }
818          }
819
820       HDC hdcSource = CreateCompatibleDC (hdcTarget);
821       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, bmpSource);
822       HPALETTE palOld = NULL;
823       if ((wDepthDisplay == 8) && (m_palGraphic != NULL) && (fShow256))
824          {
825          palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
826          RealizePalette (hdcTarget);
827          }
828
829       if ( (bm.bmWidth < cxRECT(rWindow)) || (bm.bmHeight < cyRECT(rWindow)) )
830          {
831          COLORREF clrFill = GetPixel (hdcSource, 0, rSource.bottom -1);
832          clrFill = ToPALETTERGB(clrFill);
833          HBRUSH hbrFill = CreateSolidBrush (clrFill);
834
835          if (bm.bmWidth < cxRECT(rWindow))
836             {
837             RECT rr;
838             rr = rWindow;
839             rr.right = rTarget.left;
840             FillRect (hdcTarget, &rr, hbrFill);
841
842             rr = rWindow;
843             rr.left = rTarget.right;
844             FillRect (hdcTarget, &rr, hbrFill);
845             }
846
847          if (bm.bmHeight < cyRECT(rWindow))
848             {
849             RECT rr;
850             rr = rWindow;
851             rr.bottom = rTarget.top;
852             FillRect (hdcTarget, &rr, hbrFill);
853
854             rr = rWindow;
855             rr.top = rTarget.bottom;
856             FillRect (hdcTarget, &rr, hbrFill);
857             }
858
859          DeleteObject (hbrFill);
860          }
861
862       BitBlt (hdcTarget, rTarget.left, rTarget.top, cxRECT(rTarget), cyRECT(rTarget), hdcSource, rSource.left, rSource.top, SRCCOPY);
863
864       // Call the user-supplied callback function (if there is one)
865       //
866       if (m_pfnCallback)
867          {
868          (*m_pfnCallback)(this, hdcTarget, &rWindow, (palOld) ? m_palGraphic : NULL);
869          }
870
871       if (palOld != NULL)
872          SelectPalette (hdcTarget, palOld, FALSE);
873
874       // If we've been drawing to an off-screen bitmap, blit the result to
875       // the display.
876       //
877       if (hdcFinalTarget)
878          {
879          BitBlt (hdcFinalTarget, rWindow.left, rWindow.top, cxRECT(rWindow), cyRECT(rWindow), hdcTarget, 0, 0, SRCCOPY);
880          SelectObject (hdcTarget, bmpTempTarget);
881          DeleteDC (hdcTarget);
882          hdcTarget = hdcFinalTarget;
883          }
884
885       SelectObject (hdcSource, bmpOld);
886       DeleteDC (hdcSource);
887
888       EndPaint (hLHS, &ps);
889       }
890
891    return TRUE;
892 }
893
894
895 void MoveRect (RECT *_pr, LONG _dx, LONG _dy)
896 {
897    _pr->left += _dx;
898    _pr->right += _dx;
899    _pr->top += _dy;
900    _pr->bottom += _dy;
901 }
902
903
904 void GetRectInParent (HWND hWnd, RECT *pr)
905 {
906    POINT pt;
907
908    GetWindowRect (hWnd, pr);
909
910    pr->right -= pr->left;
911    pr->bottom -= pr->top;       // right/bottom == width/height for now
912
913    pt.x = pr->left;
914    pt.y = pr->top;
915
916    ScreenToClient (GetParent (hWnd), &pt);
917
918    pr->left = pt.x;
919    pr->top = pt.y;
920    pr->right += pr->left;
921    pr->bottom += pr->top;
922 }
923
924
925 BOOL CALLBACK WIZARD::Background_DlgProc (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
926 {
927    if (msg == WM_INITDIALOG)
928       SetWindowLong (hBkg, DWL_USER, lp);
929
930    LPWIZARD pWiz = (LPWIZARD)GetWindowLong (hBkg, DWL_USER);
931
932    switch (msg)
933       {
934       case WM_INITDIALOG:
935          if (pWiz)
936             pWiz->Background_OnInitDialog (hBkg);
937          break;
938
939       case WM_SIZE:
940          if (pWiz)
941             pWiz->Background_OnSize();
942          break;
943
944       case WM_DESTROY:
945          if (pWiz)
946             pWiz->Background_OnDestroy();
947          break;
948
949       case WM_COMMAND:
950          switch (LOWORD(wp))
951             {
952             case IDCANCEL:
953                if (pWiz)
954                   pWiz->Background_OnClose();
955                else
956                   DestroyWindow (hBkg);
957                break;
958             }
959          break;
960       }
961
962    if (pWiz && pWiz->m_fnBackground)
963       {
964       if (CallWindowProc ((WNDPROC)(pWiz->m_fnBackground), hBkg, msg, wp, lp))
965          return TRUE;
966       }
967
968    return FALSE;
969 }
970
971
972 BOOL CALLBACK WIZARD::Background_PaintHook (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
973 {
974    PVOID oldProc = Subclass_FindNextHook (hBkg, WIZARD::Background_PaintHook);
975
976    switch (msg)
977       {
978       case WM_PAINT:
979          LPWIZARD pWiz;
980          if ((pWiz = WIZARD::GetWizard (hBkg)) != NULL)
981             {
982             if (pWiz->Background_OnPaint())
983                return TRUE;
984             }
985          break;
986
987       case WM_DESTROY:
988          Subclass_RemoveHook (hBkg, WIZARD::Background_PaintHook);
989          break;
990       }
991
992    if (oldProc)
993       return CallWindowProc ((WNDPROC)oldProc, hBkg, msg, wp, lp);
994    else
995       return DefWindowProc (hBkg, msg, wp, lp);
996 }
997
998
999
1000 void WIZARD::Background_OnInitDialog (HWND hBkg)
1001 {
1002    m_hBkg = hBkg;
1003    Background_OnSize();
1004    Subclass_AddHook (m_hBkg, (DLGPROC)WIZARD::Background_PaintHook);
1005 }
1006
1007
1008 void WIZARD::Background_OnSize (void)
1009 {
1010    if (m_bmpBackground)
1011       {
1012       DeleteObject (m_bmpBackground);
1013       m_bmpBackground = NULL;
1014       }
1015
1016    RECT rr;
1017    GetClientRect (m_hBkg, &rr);
1018
1019    if (m_fBlue)
1020       {
1021       HDC hdc = GetDC (NULL);
1022       WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
1023       ReleaseDC (NULL, hdc);
1024
1025       hdc = GetDC (m_hBkg);
1026       HDC hdcTarget = CreateCompatibleDC (hdc);
1027
1028       if ((m_bmpBackground = CreateCompatibleBitmap (hdc, cxRECT(rr), cyRECT(rr))) != NULL)
1029          {
1030          HBITMAP bmpOld = (HBITMAP)SelectObject (hdcTarget, m_bmpBackground);
1031
1032          HPALETTE palOld = NULL;
1033          if (m_palGraphic)
1034             {
1035             palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
1036             RealizePalette (hdcTarget);
1037             }
1038
1039          size_t yy = 0;
1040          size_t cy = cyRECT(rr) / ((clrWASH_BRIGHTEST - clrWASH_DARKEST) / clrWASH_INCREMENT);
1041          for (COLORREF clr = clrWASH_BRIGHTEST; clr >= clrWASH_DARKEST; clr -= clrWASH_INCREMENT)
1042             {
1043             RECT rSection = rr;
1044             rSection.top = yy;
1045             rSection.bottom = yy +cy;
1046             HBRUSH hbr = CreateSolidBrush (ToPALETTERGB(clr));
1047             FillRect (hdcTarget, &rSection, hbr);
1048             DeleteObject (hbr);
1049             yy += cy;
1050             }
1051
1052          if (m_szBackground[0] != TEXT('\0'))
1053             {
1054             HFONT hfOld = (HFONT)SelectObject (hdcTarget, m_hfBackground);
1055             COLORREF clrOld = SetTextColor (hdcTarget, clrWASH_TEXT_BG);
1056             SetBkMode (hdcTarget, TRANSPARENT);
1057
1058             RECT rText = rr;
1059             rText.left += xTEXT + cxSHADOW;
1060             rText.top += yTEXT + cySHADOW;
1061             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1062
1063             rText.left -= cxSHADOW;
1064             rText.top -= cySHADOW;
1065             SetTextColor (hdcTarget, clrWASH_TEXT_FG);
1066             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1067
1068             SetTextColor (hdcTarget, clrOld);
1069             SelectObject (hdcTarget, hfOld);
1070             }
1071
1072          if (palOld)
1073             SelectPalette (hdcTarget, palOld, FALSE);
1074
1075          SelectObject (hdcTarget, bmpOld);
1076          }
1077
1078       DeleteDC (hdcTarget);
1079       ReleaseDC (m_hBkg, hdc);
1080       }
1081
1082    InvalidateRect (m_hBkg, &rr, TRUE);
1083    UpdateWindow (m_hBkg);
1084 }
1085
1086
1087 void WIZARD::Background_OnDestroy (void)
1088 {
1089    if (m_bmpBackground)
1090       {
1091       DeleteObject (m_bmpBackground);
1092       m_bmpBackground = NULL;
1093       }
1094 }
1095
1096
1097 void WIZARD::Background_OnClose (void)
1098 {
1099    LPWIZARD_STATE pState;
1100
1101    if (m_hWnd && IsWindow (m_hWnd))
1102       {
1103       PostMessage (m_hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), (LPARAM)GetDlgItem(m_hWnd,IDCANCEL));
1104       }
1105    else if ((pState = FindState (m_stCurrent)) != NULL)
1106       {
1107       CallWindowProc ((WNDPROC)(pState->dlgproc), m_hBkg, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), 0);
1108       }
1109    else
1110       {
1111       ShowBackground (FALSE);
1112       }
1113 }
1114
1115
1116 BOOL WIZARD::Background_OnPaint (void)
1117 {
1118    if (!m_bmpBackground)
1119       return FALSE;
1120       
1121    PAINTSTRUCT ps;
1122    HDC hdcTarget;
1123    if ((hdcTarget = BeginPaint (m_hBkg, &ps)) != NULL)
1124       {
1125       BITMAP bm;
1126       GetObject (m_bmpBackground, sizeof(BITMAP), &bm);
1127
1128       HDC hdcSource = CreateCompatibleDC (hdcTarget);
1129       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, m_bmpBackground);
1130       HPALETTE palOld = NULL;
1131       if (m_palGraphic)
1132          {
1133          palOld = SelectPalette (hdcSource, m_palGraphic, FALSE);
1134          RealizePalette (hdcTarget);
1135          }
1136
1137       BitBlt (hdcTarget, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY);
1138
1139       if (palOld != NULL)
1140          SelectPalette (hdcTarget, palOld, FALSE);
1141       SelectObject (hdcSource, bmpOld);
1142       DeleteDC (hdcSource);
1143
1144       EndPaint (m_hBkg, &ps);
1145       }
1146
1147    return TRUE;
1148 }
1149