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