ec5b2bd988b142e1d008f1dd48a23734f254c6ea
[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)GetWindowLongPtr (hWnd, DWLP_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    RGBQUAD argb[256];
172
173    m_idbGraphic16 = idbGraphic16;
174    m_idbGraphic256 = idbGraphic256;
175
176    if (m_bmpGraphic16 != NULL)
177       {
178       DeleteObject (m_bmpGraphic16);
179       m_bmpGraphic16 = NULL;
180       }
181
182    if (m_bmpGraphic256 != NULL)
183       {
184       DeleteObject (m_bmpGraphic256);
185       m_bmpGraphic256 = NULL;
186       }
187
188    if (m_palGraphic != NULL)
189       {
190       DeleteObject (m_palGraphic);
191       m_palGraphic = NULL;
192       }
193
194    m_bmpGraphic16 = (HBITMAP)TaLocale_LoadImage (idbGraphic16, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
195
196    if ((m_bmpGraphic256 = (HBITMAP)TaLocale_LoadImage (idbGraphic256, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION)) != NULL)
197       {
198       BITMAP bm;
199       GetObject (m_bmpGraphic256, sizeof(BITMAP), &bm);
200
201       if ((bm.bmBitsPixel * bm.bmPlanes) == 8)
202          {
203          HDC hdc = CreateCompatibleDC (NULL);
204          HBITMAP bmpOld = (HBITMAP)SelectObject (hdc, m_bmpGraphic256);
205
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          int st;
264          for (st = stNew+1; st < (int)m_cStates; ++st)
265             {
266             LPWIZARD_STATE pState;
267             if ((pState = FindState (st)) != NULL)
268                {
269                m_stCurrent = st;
270                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
271                   break;
272                m_stCurrent = stOriginal;
273                SendStateCommand (st, wcSTATE_ENTER);
274                SendStateCommand (st, wcSTATE_LEAVE);
275                }
276             }
277          stNew = (st < (int)m_cStates) ? st : m_stCurrent;
278          }
279       else // (moving backwards?)
280          {
281          int st;
282          for (st = stNew-1; st >= 0; --st)
283             {
284             LPWIZARD_STATE pState;
285             if ((pState = FindState (st)) != NULL)
286                {
287                m_stCurrent = st;
288                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
289                   break;
290                m_stCurrent = stOriginal;
291                SendStateCommand (st, wcSTATE_ENTER);
292                SendStateCommand (st, wcSTATE_LEAVE);
293                }
294             }
295          stNew = (st >= 0) ? st : m_stCurrent;
296          }
297       }
298
299    m_stCurrent = stNew;
300
301    SendStateCommand (m_stCurrent, wcSTATE_ENTER);
302
303    if (m_fShowing)
304       {
305       Refresh (REFRESH_RIGHT_PANE);
306       }
307 }
308
309
310 BOOL WIZARD::Show (BOOL fShowReq)
311 {
312    if (m_fShowing && !fShowReq)
313       {
314       m_fShowing = FALSE;
315       if (m_hWnd && IsWindow (m_hWnd))
316          DestroyWindow (m_hWnd);
317       m_hWnd = NULL;
318       }
319    else if (!m_fShowing && fShowReq)
320       {
321       if (m_iddTemplate == -1)
322          return FALSE;
323       if (m_idcLeftPane == -1)
324          return FALSE;
325       if (m_idcRightPane == -1)
326          return FALSE;
327       if (m_idcBack == -1)
328          return FALSE;
329       if (m_idcNext == -1)
330          return FALSE;
331
332       if ((m_hWnd = ModelessDialogParam (m_iddTemplate, m_hBkg, (DLGPROC)WIZARD::Template_DlgProc, (LPARAM)this)) == NULL)
333          return FALSE;
334       m_fShowing = TRUE;
335
336       MSG msg;
337       while (GetMessage (&msg, 0, 0, NULL))
338          {
339          if (!IsDialogMessage (m_hWnd, &msg))
340             {
341             TranslateMessage (&msg);
342             DispatchMessage (&msg);
343             }
344
345          if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
346             break;
347          }
348       }
349
350    return TRUE;
351 }
352
353
354 void WIZARD::EnableButton (int idcButton, BOOL fEnable)
355 {
356    EnableWindow (GetDlgItem (m_hWnd, idcButton), fEnable);
357 }
358
359
360 void WIZARD::EnableButtons (DWORD dwButtonFlags)
361 {
362    EnableWindow (GetDlgItem (m_hWnd, m_idcBack), (dwButtonFlags & BACK_BUTTON) ? TRUE : FALSE);
363    EnableWindow (GetDlgItem (m_hWnd, m_idcNext), (dwButtonFlags & NEXT_BUTTON) ? TRUE : FALSE);
364 }
365
366
367 void WIZARD::SetButtonText (int idcButton, int idsText)
368 {
369    HWND hButton;
370    if ((hButton = GetDlgItem (m_hWnd, idcButton)) != NULL)
371       {
372       TCHAR szText[ cchRESOURCE ];
373       GetString (szText, idsText);
374       SetWindowText (hButton, szText);
375       }
376 }
377
378
379 void WIZARD::SetDefaultControl (int idc)
380 {
381    HWND hControl;
382    if ((hControl = GetDlgItem (m_hWnd, idc)) == NULL)
383       {
384       HWND hRHS;
385       if ((hRHS = GetRightHandWindow()) != NULL)
386          hControl = GetDlgItem (hRHS, idc);
387       }
388
389    if (hControl)
390       {
391       PostMessage (m_hWnd, WM_NEXTDLGCTL, (WPARAM)hControl, TRUE);
392       }
393 }
394
395
396 void WIZARD::SetBackground (int iddBackground, BOOL fBlue, DLGPROC dlgproc)
397 {
398    m_iddBackground = iddBackground;
399    m_fBlue = fBlue;
400    m_fnBackground = dlgproc;
401
402    if (m_hBkg && IsWindow (m_hBkg))
403       {
404       ShowBackground (FALSE);
405       ShowBackground (TRUE);
406       }
407 }
408
409
410 void WIZARD::SetBackgroundText (int idsText, HFONT hf)
411 {
412    GetString (m_szBackground, idsText);
413
414    if ((hf != NULL) && (hf != m_hfBackground))
415       {
416       if (m_hfBackground != NULL)
417          DeleteObject (m_hfBackground);
418       m_hfBackground = hf;
419       }
420
421    if (m_hBkg && IsWindow (m_hBkg))
422       {
423       Background_OnSize();
424       }
425 }
426
427
428 void WIZARD::SetBackgroundText (LPTSTR pszText, HFONT hf)
429 {
430    if (!pszText)
431       m_szBackground[0] = TEXT('\0');
432    else
433       lstrcpy (m_szBackground, pszText);
434
435    if ((hf != NULL) && (hf != m_hfBackground))
436       {
437       if (m_hfBackground != NULL)
438          DeleteObject (m_hfBackground);
439       m_hfBackground = hf;
440       }
441
442    if (m_hBkg && IsWindow (m_hBkg))
443       {
444       Background_OnSize();
445       }
446 }
447
448
449 BOOL WIZARD::ShowBackground (BOOL fShow)
450 {
451    if (!fShow && m_hBkg && IsWindow (m_hBkg))
452       {
453       DestroyWindow (m_hBkg);
454       m_hBkg = NULL;
455       }
456    else if (fShow && !(m_hBkg && IsWindow (m_hBkg)))
457       {
458       if ((m_hBkg = ModelessDialogParam (m_iddBackground, NULL, (DLGPROC)WIZARD::Background_DlgProc, (LPARAM)this)) == NULL)
459          return FALSE;
460
461       RECT rDesktop;
462       SystemParametersInfo (SPI_GETWORKAREA, 0, &rDesktop, 0);
463
464       WINDOWPLACEMENT wpl;
465       wpl.length = sizeof(wpl);
466       wpl.flags = 0;
467       wpl.showCmd = (GetWindowLong (m_hBkg, GWL_STYLE) & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOW;
468       wpl.ptMinPosition.x = 0;
469       wpl.ptMinPosition.y = 0;
470       wpl.ptMaxPosition.x = 0;
471       wpl.ptMaxPosition.y = 0;
472       wpl.rcNormalPosition.left = rDesktop.left + cxLEFT_BACKGROUND;
473       wpl.rcNormalPosition.right = rDesktop.right - cxRIGHT_BACKGROUND;
474       wpl.rcNormalPosition.top = rDesktop.top + cyTOP_BACKGROUND;
475       wpl.rcNormalPosition.bottom = rDesktop.bottom - cyBOTTOM_BACKGROUND;
476       SetWindowPlacement (m_hBkg, &wpl);
477       }
478
479    return TRUE;
480 }
481
482
483 HWND WIZARD::GetBackgroundWindow (void)
484 {
485    return m_hBkg;
486 }
487
488
489 void WIZARD::Refresh (DWORD dwRefFlags)
490 {
491    if (dwRefFlags & REFRESH_LEFT_PANE)
492       {
493       HWND hLHS;
494       if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
495          {
496          RECT rr;
497          GetClientRect (hLHS, &rr);
498          InvalidateRect (hLHS, &rr, TRUE);
499          UpdateWindow (hLHS);
500          }
501       }
502
503    if (dwRefFlags & REFRESH_RIGHT_PANE)
504       {
505       HWND hRHS;
506       if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
507          {
508          HWND hOld = GetRightHandWindow();
509
510          LPWIZARD_STATE pState;
511          if ((pState = FindState (m_stCurrent)) != NULL)
512             {
513             int stCurrent = m_stCurrent;
514
515             HWND hNew;
516             if ((hNew = ModelessDialogParam (pState->idd, m_hWnd, pState->dlgproc, pState->lp)) != NULL)
517                {
518                if (stCurrent != m_stCurrent)
519                   DestroyWindow (hNew);
520                else
521                   {
522                   RECT rRHS;
523                   GetRectInParent (hRHS, &rRHS);
524                   SetWindowPos (hNew, NULL, rRHS.left, rRHS.top, cxRECT(rRHS), cyRECT(rRHS), SWP_NOZORDER | SWP_NOACTIVATE);
525                   SetWindowLong (hNew, GWL_ID, pState->idd);
526
527                   ShowWindow (hNew, SW_SHOW);
528                   ShowWindow (hRHS, SW_HIDE);
529                   }
530                }
531             }
532
533          if (hOld != NULL)
534             DestroyWindow (hOld);
535          }
536       }
537 }
538
539
540 HWND WIZARD::GetRightHandWindow (void)
541 {
542    if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
543       return NULL;
544
545    HWND hRHS = NULL;
546
547    for (HWND hFound = ::GetWindow (m_hWnd, GW_CHILD);
548         hFound != NULL;
549         hFound = ::GetWindow (hFound, GW_HWNDNEXT))
550       {
551       TCHAR szClassName[ cchRESOURCE ];
552       if (GetClassName (hFound, szClassName, cchRESOURCE))
553          {
554          if (!lstrcmp (szClassName, TEXT("#32770"))) // WC_DIALOG
555             {
556             if (!hRHS || IsWindowVisible(hRHS))
557                hRHS = hFound;
558             }
559          }
560       }
561
562    return hRHS;
563 }
564
565
566 void WIZARD::GeneratePalette (LPRGBQUAD argb)
567 {
568    HDC hdc = GetDC (NULL);
569    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
570    ReleaseDC (NULL, hdc);
571
572    if (wDepthDisplay == 8)
573       {
574       BYTE aPalBuffer[ sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY) ];
575       LPLOGPALETTE pPal = (LPLOGPALETTE)aPalBuffer;
576       pPal->palVersion = 0x300;
577       pPal->palNumEntries = 256;
578
579       size_t ii;
580       for (ii = 0; ii < 256; ++ii)
581          {
582          pPal->palPalEntry[ ii ].peRed   = (argb) ? argb[ ii ].rgbRed : 0;
583          pPal->palPalEntry[ ii ].peGreen = (argb) ? argb[ ii ].rgbGreen : 0;
584          pPal->palPalEntry[ ii ].peBlue  = (argb) ? argb[ ii ].rgbBlue : 0;
585          pPal->palPalEntry[ ii ].peFlags = 0;
586          }
587
588       for (COLORREF clr = clrWASH_DARKEST; clr <= clrWASH_BRIGHTEST; clr += clrWASH_INCREMENT)
589          {            
590          for (ii = 0; ii < 256; ++ii)
591             {
592             if ( (pPal->palPalEntry[ ii ].peRed   == GetRValue (clr)) &&
593                  (pPal->palPalEntry[ ii ].peGreen == GetGValue (clr)) &&
594                  (pPal->palPalEntry[ ii ].peBlue  == GetBValue (clr)) )
595                break;
596             }
597          if (ii == 256)
598             {
599             for (ii = 10; ii < 246; ++ii)
600                {
601                if ( (pPal->palPalEntry[ ii ].peRed == 0) &&
602                     (pPal->palPalEntry[ ii ].peGreen == 0) &&
603                     (pPal->palPalEntry[ ii ].peBlue == 0) )
604                   break;
605                if ( (pPal->palPalEntry[ ii ].peRed == 255) &&
606                     (pPal->palPalEntry[ ii ].peGreen == 255) &&
607                     (pPal->palPalEntry[ ii ].peBlue == 255) )
608                   break;
609                }
610             if (ii == 246)
611                break;
612
613             pPal->palPalEntry[ ii ].peRed   = GetRValue (clr);
614             pPal->palPalEntry[ ii ].peGreen = GetGValue (clr);
615             pPal->palPalEntry[ ii ].peBlue  = GetBValue (clr);
616             }
617          }
618
619       m_palGraphic = CreatePalette (pPal);
620       }
621 }
622
623
624 LPWIZARD_STATE WIZARD::FindState (int stFind)
625 {
626    for (size_t ii = 0; ii < m_cStates; ++ii)
627       {
628       if (m_aStates[ ii ].st == stFind)
629          return &m_aStates[ ii ];
630       }
631    return NULL;
632 }
633
634
635 BOOL WIZARD::SendStateCommand (int st, WIZARD_COMMAND wc)
636 {
637    BOOL rc = FALSE;
638
639    LPWIZARD_STATE pState;
640    if ((pState = FindState (st)) != NULL)
641       {
642       rc = CallWindowProc ((WNDPROC)(pState->dlgproc), NULL, WM_COMMAND, MAKEWPARAM(IDC_WIZARD,(WORD)wc), (LPARAM)this);
643       }
644
645    return rc;
646 }
647
648
649 BOOL CALLBACK WIZARD::Template_DlgProc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
650 {
651    if (msg == WM_INITDIALOG)
652       SetWindowLongPtr (hWnd, DWLP_USER, lp);
653
654    LPWIZARD pWiz = (LPWIZARD)GetWindowLongPtr (hWnd, DWLP_USER);
655
656    switch (msg)
657       {
658       case WM_INITDIALOG:
659          if (pWiz)
660             pWiz->Template_OnInitDialog (hWnd);
661          break;
662
663       case WM_DESTROY:
664          if (pWiz && (pWiz->m_hWnd == hWnd))
665             pWiz->Show (FALSE);
666          break;
667
668       case WM_COMMAND:
669          return pWiz->Template_ForwardMessage (hWnd, msg, wp, lp);
670       }
671
672    return FALSE;
673 }
674
675
676 BOOL CALLBACK WIZARD::Template_LeftPaneHook (HWND hLHS, UINT msg, WPARAM wp, LPARAM lp)
677 {
678    PVOID oldProc = Subclass_FindNextHook (hLHS, WIZARD::Template_LeftPaneHook);
679
680    switch (msg)
681       {
682       case WM_PAINT:
683          LPWIZARD pWiz;
684          if ((pWiz = WIZARD::GetWizard (GetParent (hLHS))) != NULL)
685             {
686             if (pWiz->Template_OnPaintLHS (hLHS))
687                return TRUE;
688             }
689          break;
690
691       case WM_DESTROY:
692          Subclass_RemoveHook (hLHS, WIZARD::Template_LeftPaneHook);
693          break;
694       }
695
696    if (oldProc)
697       return CallWindowProc ((WNDPROC)oldProc, hLHS, msg, wp, lp);
698    else
699       return DefWindowProc (hLHS, msg, wp, lp);
700 }
701
702
703 BOOL WIZARD::Template_ForwardMessage (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
704 {
705    HWND hRHS;
706    if ((hRHS = GetRightHandWindow()) != NULL)
707       return SendMessage (hRHS, msg, wp, lp);
708
709    LPWIZARD_STATE pState;
710    if ((pState = FindState (m_stCurrent)) != NULL)
711       return CallWindowProc ((WNDPROC)(pState->dlgproc), hWnd, msg, wp, lp);
712
713    return FALSE;
714 }
715
716
717 void WIZARD::Template_OnInitDialog (HWND hWnd)
718 {
719    m_hWnd = hWnd;
720    m_fShowing = TRUE;
721
722    HWND hLHS;
723    if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
724       {
725       Subclass_AddHook (hLHS, WIZARD::Template_LeftPaneHook);
726       }
727
728    HWND hRHS;
729    if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
730       {
731       ShowWindow (hRHS, SW_HIDE);
732       }
733
734    Refresh (REFRESH_RIGHT_PANE);
735
736    ShowWindow (m_hWnd, SW_SHOW);
737 }
738
739
740 BOOL WIZARD::Template_OnPaintLHS (HWND hLHS)
741 {
742    BOOL fShow16 = FALSE;
743    BOOL fShow256 = FALSE;
744
745    HDC hdc = GetDC (NULL);
746    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
747    ReleaseDC (NULL, hdc);
748
749    if ( (m_bmpGraphic256 != NULL) && (wDepthDisplay >= 8) )
750       fShow256 = TRUE;
751    else if (m_bmpGraphic16 != NULL)
752       fShow16 = TRUE;
753    else
754       return FALSE;
755
756    PAINTSTRUCT ps;
757    HDC hdcTarget;
758    if ((hdcTarget = BeginPaint (hLHS, &ps)) != NULL)
759       {
760       HBITMAP bmpSource = (fShow256) ? m_bmpGraphic256 : m_bmpGraphic16;
761
762       BITMAP bm;
763       GetObject (bmpSource, sizeof(BITMAP), &bm);
764
765       RECT rWindow;
766       GetClientRect (hLHS, &rWindow);
767
768       RECT rSource = { 0, 0, bm.bmWidth, bm.bmHeight };
769       RECT rTarget = rWindow;
770
771       if (cxRECT(rSource) > cxRECT(rTarget))
772          {
773          MoveRect (&rSource, (cxRECT(rSource) - cxRECT(rTarget)) / 2, 0);
774          rSource.right = rSource.left + cxRECT(rTarget);
775          }
776       else if (cxRECT(rSource) < cxRECT(rTarget))
777          {
778          MoveRect (&rTarget, (cxRECT(rTarget) - cxRECT(rSource)) / 2, 0);
779          }
780
781       if (cyRECT(rSource) > cyRECT(rTarget))
782          {
783          MoveRect (&rSource, 0, (cyRECT(rSource) - cyRECT(rTarget)) / 2);
784          rSource.bottom = rSource.top + cyRECT(rTarget);
785          }
786       else if (cyRECT(rSource) < cyRECT(rTarget))
787          {
788          MoveRect (&rTarget, 0, (cyRECT(rTarget) - cyRECT(rSource)) / 2);
789          }
790       rTarget.right = rTarget.left + cxRECT(rSource);
791       rTarget.bottom = rTarget.top + cyRECT(rSource);
792
793       // If the user has supplied a custom draw-proc, then we should
794       // do our rendering to an off-screen bitmap.
795       //
796       HDC hdcFinalTarget = NULL;
797       HBITMAP bmpTempTarget = NULL;
798       if (m_pfnCallback)
799          {
800          // First make sure our offscreen buffer is large enough
801          //
802          if (!m_bmpBuffer || (cxRECT(m_rBuffer) < cxRECT(rWindow)) || (cyRECT(m_rBuffer) < cyRECT(rWindow)))
803             {
804             if (m_bmpBuffer != NULL)
805                DeleteObject (m_bmpBuffer);
806             if ((m_bmpBuffer = CreateCompatibleBitmap (hdcTarget, cxRECT(rWindow), cyRECT(rWindow))) != NULL)
807                {
808                m_rBuffer.right = cxRECT(rWindow);  // m_rBuffer.left=already 0
809                m_rBuffer.bottom = cyRECT(rWindow); // m_rBuffer.top=already 0
810                }
811             }
812
813          // Then set up to double-buffer, if possible
814          //
815          if (m_bmpBuffer)
816             {
817             hdcFinalTarget = hdcTarget;
818             hdcTarget = CreateCompatibleDC (hdcFinalTarget);
819             bmpTempTarget = (HBITMAP)SelectObject (hdcTarget, m_bmpBuffer);
820             }
821          }
822
823       HDC hdcSource = CreateCompatibleDC (hdcTarget);
824       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, bmpSource);
825       HPALETTE palOld = NULL;
826       if ((wDepthDisplay == 8) && (m_palGraphic != NULL) && (fShow256))
827          {
828          palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
829          RealizePalette (hdcTarget);
830          }
831
832       if ( (bm.bmWidth < cxRECT(rWindow)) || (bm.bmHeight < cyRECT(rWindow)) )
833          {
834          COLORREF clrFill = GetPixel (hdcSource, 0, rSource.bottom -1);
835          clrFill = ToPALETTERGB(clrFill);
836          HBRUSH hbrFill = CreateSolidBrush (clrFill);
837
838          if (bm.bmWidth < cxRECT(rWindow))
839             {
840             RECT rr;
841             rr = rWindow;
842             rr.right = rTarget.left;
843             FillRect (hdcTarget, &rr, hbrFill);
844
845             rr = rWindow;
846             rr.left = rTarget.right;
847             FillRect (hdcTarget, &rr, hbrFill);
848             }
849
850          if (bm.bmHeight < cyRECT(rWindow))
851             {
852             RECT rr;
853             rr = rWindow;
854             rr.bottom = rTarget.top;
855             FillRect (hdcTarget, &rr, hbrFill);
856
857             rr = rWindow;
858             rr.top = rTarget.bottom;
859             FillRect (hdcTarget, &rr, hbrFill);
860             }
861
862          DeleteObject (hbrFill);
863          }
864
865       BitBlt (hdcTarget, rTarget.left, rTarget.top, cxRECT(rTarget), cyRECT(rTarget), hdcSource, rSource.left, rSource.top, SRCCOPY);
866
867       // Call the user-supplied callback function (if there is one)
868       //
869       if (m_pfnCallback)
870          {
871          (*m_pfnCallback)(this, hdcTarget, &rWindow, (palOld) ? m_palGraphic : NULL);
872          }
873
874       if (palOld != NULL)
875          SelectPalette (hdcTarget, palOld, FALSE);
876
877       // If we've been drawing to an off-screen bitmap, blit the result to
878       // the display.
879       //
880       if (hdcFinalTarget)
881          {
882          BitBlt (hdcFinalTarget, rWindow.left, rWindow.top, cxRECT(rWindow), cyRECT(rWindow), hdcTarget, 0, 0, SRCCOPY);
883          SelectObject (hdcTarget, bmpTempTarget);
884          DeleteDC (hdcTarget);
885          hdcTarget = hdcFinalTarget;
886          }
887
888       SelectObject (hdcSource, bmpOld);
889       DeleteDC (hdcSource);
890
891       EndPaint (hLHS, &ps);
892       }
893
894    return TRUE;
895 }
896
897
898 void MoveRect (RECT *_pr, LONG _dx, LONG _dy)
899 {
900    _pr->left += _dx;
901    _pr->right += _dx;
902    _pr->top += _dy;
903    _pr->bottom += _dy;
904 }
905
906
907 void GetRectInParent (HWND hWnd, RECT *pr)
908 {
909    POINT pt;
910
911    GetWindowRect (hWnd, pr);
912
913    pr->right -= pr->left;
914    pr->bottom -= pr->top;       // right/bottom == width/height for now
915
916    pt.x = pr->left;
917    pt.y = pr->top;
918
919    ScreenToClient (GetParent (hWnd), &pt);
920
921    pr->left = pt.x;
922    pr->top = pt.y;
923    pr->right += pr->left;
924    pr->bottom += pr->top;
925 }
926
927
928 BOOL CALLBACK WIZARD::Background_DlgProc (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
929 {
930    if (msg == WM_INITDIALOG)
931       SetWindowLongPtr (hBkg, DWLP_USER, lp);
932
933    LPWIZARD pWiz = (LPWIZARD)GetWindowLongPtr (hBkg, DWLP_USER);
934
935    switch (msg)
936       {
937       case WM_INITDIALOG:
938          if (pWiz)
939             pWiz->Background_OnInitDialog (hBkg);
940          break;
941
942       case WM_SIZE:
943          if (pWiz)
944             pWiz->Background_OnSize();
945          break;
946
947       case WM_DESTROY:
948          if (pWiz)
949             pWiz->Background_OnDestroy();
950          break;
951
952       case WM_COMMAND:
953          switch (LOWORD(wp))
954             {
955             case IDCANCEL:
956                if (pWiz)
957                   pWiz->Background_OnClose();
958                else
959                   DestroyWindow (hBkg);
960                break;
961             }
962          break;
963       }
964
965    if (pWiz && pWiz->m_fnBackground)
966       {
967       if (CallWindowProc ((WNDPROC)(pWiz->m_fnBackground), hBkg, msg, wp, lp))
968          return TRUE;
969       }
970
971    return FALSE;
972 }
973
974
975 BOOL CALLBACK WIZARD::Background_PaintHook (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
976 {
977    PVOID oldProc = Subclass_FindNextHook (hBkg, WIZARD::Background_PaintHook);
978
979    switch (msg)
980       {
981       case WM_PAINT:
982          LPWIZARD pWiz;
983          if ((pWiz = WIZARD::GetWizard (hBkg)) != NULL)
984             {
985             if (pWiz->Background_OnPaint())
986                return TRUE;
987             }
988          break;
989
990       case WM_DESTROY:
991          Subclass_RemoveHook (hBkg, WIZARD::Background_PaintHook);
992          break;
993       }
994
995    if (oldProc)
996       return CallWindowProc ((WNDPROC)oldProc, hBkg, msg, wp, lp);
997    else
998       return DefWindowProc (hBkg, msg, wp, lp);
999 }
1000
1001
1002
1003 void WIZARD::Background_OnInitDialog (HWND hBkg)
1004 {
1005    m_hBkg = hBkg;
1006    Background_OnSize();
1007    Subclass_AddHook (m_hBkg, (DLGPROC)WIZARD::Background_PaintHook);
1008 }
1009
1010
1011 void WIZARD::Background_OnSize (void)
1012 {
1013    if (m_bmpBackground)
1014       {
1015       DeleteObject (m_bmpBackground);
1016       m_bmpBackground = NULL;
1017       }
1018
1019    RECT rr;
1020    GetClientRect (m_hBkg, &rr);
1021
1022    if (m_fBlue)
1023       {
1024       HDC hdc = GetDC (NULL);
1025       WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
1026       ReleaseDC (NULL, hdc);
1027
1028       hdc = GetDC (m_hBkg);
1029       HDC hdcTarget = CreateCompatibleDC (hdc);
1030
1031       if ((m_bmpBackground = CreateCompatibleBitmap (hdc, cxRECT(rr), cyRECT(rr))) != NULL)
1032          {
1033          HBITMAP bmpOld = (HBITMAP)SelectObject (hdcTarget, m_bmpBackground);
1034
1035          HPALETTE palOld = NULL;
1036          if (m_palGraphic)
1037             {
1038             palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
1039             RealizePalette (hdcTarget);
1040             }
1041
1042          size_t yy = 0;
1043          size_t cy = cyRECT(rr) / ((clrWASH_BRIGHTEST - clrWASH_DARKEST) / clrWASH_INCREMENT);
1044          for (COLORREF clr = clrWASH_BRIGHTEST; clr >= clrWASH_DARKEST; clr -= clrWASH_INCREMENT)
1045             {
1046             RECT rSection = rr;
1047             rSection.top = yy;
1048             rSection.bottom = yy +cy;
1049             HBRUSH hbr = CreateSolidBrush (ToPALETTERGB(clr));
1050             FillRect (hdcTarget, &rSection, hbr);
1051             DeleteObject (hbr);
1052             yy += cy;
1053             }
1054
1055          if (m_szBackground[0] != TEXT('\0'))
1056             {
1057             HFONT hfOld = (HFONT)SelectObject (hdcTarget, m_hfBackground);
1058             COLORREF clrOld = SetTextColor (hdcTarget, clrWASH_TEXT_BG);
1059             SetBkMode (hdcTarget, TRANSPARENT);
1060
1061             RECT rText = rr;
1062             rText.left += xTEXT + cxSHADOW;
1063             rText.top += yTEXT + cySHADOW;
1064             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1065
1066             rText.left -= cxSHADOW;
1067             rText.top -= cySHADOW;
1068             SetTextColor (hdcTarget, clrWASH_TEXT_FG);
1069             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1070
1071             SetTextColor (hdcTarget, clrOld);
1072             SelectObject (hdcTarget, hfOld);
1073             }
1074
1075          if (palOld)
1076             SelectPalette (hdcTarget, palOld, FALSE);
1077
1078          SelectObject (hdcTarget, bmpOld);
1079          }
1080
1081       DeleteDC (hdcTarget);
1082       ReleaseDC (m_hBkg, hdc);
1083       }
1084
1085    InvalidateRect (m_hBkg, &rr, TRUE);
1086    UpdateWindow (m_hBkg);
1087 }
1088
1089
1090 void WIZARD::Background_OnDestroy (void)
1091 {
1092    if (m_bmpBackground)
1093       {
1094       DeleteObject (m_bmpBackground);
1095       m_bmpBackground = NULL;
1096       }
1097 }
1098
1099
1100 void WIZARD::Background_OnClose (void)
1101 {
1102    LPWIZARD_STATE pState;
1103
1104    if (m_hWnd && IsWindow (m_hWnd))
1105       {
1106       PostMessage (m_hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), (LPARAM)GetDlgItem(m_hWnd,IDCANCEL));
1107       }
1108    else if ((pState = FindState (m_stCurrent)) != NULL)
1109       {
1110       CallWindowProc ((WNDPROC)(pState->dlgproc), m_hBkg, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), 0);
1111       }
1112    else
1113       {
1114       ShowBackground (FALSE);
1115       }
1116 }
1117
1118
1119 BOOL WIZARD::Background_OnPaint (void)
1120 {
1121    if (!m_bmpBackground)
1122       return FALSE;
1123       
1124    PAINTSTRUCT ps;
1125    HDC hdcTarget;
1126    if ((hdcTarget = BeginPaint (m_hBkg, &ps)) != NULL)
1127       {
1128       BITMAP bm;
1129       GetObject (m_bmpBackground, sizeof(BITMAP), &bm);
1130
1131       HDC hdcSource = CreateCompatibleDC (hdcTarget);
1132       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, m_bmpBackground);
1133       HPALETTE palOld = NULL;
1134       if (m_palGraphic)
1135          {
1136          palOld = SelectPalette (hdcSource, m_palGraphic, FALSE);
1137          RealizePalette (hdcTarget);
1138          }
1139
1140       BitBlt (hdcTarget, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY);
1141
1142       if (palOld != NULL)
1143          SelectPalette (hdcTarget, palOld, FALSE);
1144       SelectObject (hdcSource, bmpOld);
1145       DeleteDC (hdcSource);
1146
1147       EndPaint (m_hBkg, &ps);
1148       }
1149
1150    return TRUE;
1151 }
1152