home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / appwiz / logowiz / cstm1dlg.cpp < prev    next >
C/C++ Source or Header  |  1998-03-05  |  11KB  |  358 lines

  1. // cstm1dlg.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "logowiz.h"
  15. #include "cstm1dlg.h"
  16. #include "logowaw.h"
  17.  
  18. #ifdef _PSEUDO_DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. // these are expected to be in the same order as the radio buttons corresponding to these choices
  24. // they are also assumed to start at zero
  25. #define RAD_UPLEFT  0       // logo goes in upper left corner
  26. #define RAD_LOLEFT  1       // logo goes in lower left corner
  27. #define RAD_LORIGHT 2       // logo goes in lower right corner
  28. #define RAD_NOLOGO  3       // no logo
  29. // other buttons
  30. #define BT_PRESS_ME 4       // press me button (keep below radio button set)
  31. #define BT_DLGPIC   5       // dialog box picture (keep at bottom of list: not part of radio button set)
  32.  
  33. // Size of dialog box bitmap
  34. #define BMP_LEFT 16
  35. #define BMP_TOP 16
  36. #define BMP_WIDTH 195
  37. #define BMP_HEIGHT 147
  38.  
  39. // Other values used for drawing around the dialog box bitmap
  40. #define RIGHT_YELLOW (163 + BMP_LEFT)
  41. #define BOTTOM_YELLOW_DLGU 197
  42. #define RIGHT_GRAY_DLGU 125
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CCustom1Dlg dialog
  46.  
  47.  
  48. CCustom1Dlg::CCustom1Dlg()
  49.     : CAppWizStepDlg(CCustom1Dlg::IDD)
  50. {
  51.     //{{AFX_DATA_INIT(CCustom1Dlg)
  52.     m_nLogoSpot = -1;
  53.     m_nPressMe = FALSE;
  54.     //}}AFX_DATA_INIT
  55. }
  56.  
  57.  
  58. void CCustom1Dlg::DoDataExchange(CDataExchange* pDX)
  59. {
  60.     CAppWizStepDlg::DoDataExchange(pDX);
  61.     //{{AFX_DATA_MAP(CCustom1Dlg)
  62.     DDX_Radio(pDX, IDC_LOGO_UL, m_nLogoSpot);
  63.     DDX_Check(pDX, IDC_PRESS_ME, m_nPressMe);
  64.     //}}AFX_DATA_MAP
  65. }
  66.  
  67. // set appropriate entries in the dictionary
  68. // Parameters:
  69. //  bWriteSymbol - Boolean value determining whether we need to write (TRUE) or delete (FALSE)
  70. //                  a dictionary value
  71. //       strName - the dictionary value we're working with
  72. void CCustom1Dlg::SetSymbol(BOOL bWriteSymbol, LPCTSTR strName)
  73. {
  74.     if (bWriteSymbol)
  75.         logowizaw.m_Dictionary.SetAt(strName, CString("1"));
  76.     else
  77.         logowizaw.m_Dictionary.RemoveKey(strName);
  78. }
  79.  
  80. // This is called whenever the user presses Next, Back, or Finish with this step
  81. //  present.  Do all validation & data exchange from the dialog in this function.
  82. BOOL CCustom1Dlg::OnDismiss()
  83. {
  84.     if (!UpdateData(TRUE))
  85.         return FALSE;
  86.  
  87.     // set the template variables
  88.     SetSymbol(m_nLogoSpot == RAD_UPLEFT, _T("LOGO_UPLEFT"));
  89.     SetSymbol(m_nLogoSpot == RAD_LOLEFT, _T("LOGO_LOLEFT"));
  90.     SetSymbol(m_nLogoSpot == RAD_LORIGHT, _T("LOGO_LORIGHT"));
  91.     // don't need to set a symbol for LOGO_NONE
  92.     SetSymbol(RAD_UPLEFT || RAD_LOLEFT || RAD_LORIGHT, _T("LOGO_YES"));
  93.     SetSymbol(m_nPressMe == TRUE, _T("PRESS_ME_DIALOG"));
  94.  
  95.     return TRUE;    // return FALSE if the dialog shouldn't be dismissed
  96. }
  97.  
  98.  
  99. BEGIN_MESSAGE_MAP(CCustom1Dlg, CAppWizStepDlg)
  100.     ON_CONTROL_RANGE(BN_CLICKED, IDC_LOGO_UL, IDC_LOGO_NONE, OnLogoClicked)
  101.     //{{AFX_MSG_MAP(CCustom1Dlg)
  102.     ON_WM_PAINT()
  103.     ON_BN_CLICKED(IDC_PRESS_ME, OnPressMe)
  104.     //}}AFX_MSG_MAP
  105. END_MESSAGE_MAP()
  106.  
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. // CCustom1Dlg message handlers
  110.  
  111. // draw a logo on the AppWiz page in the right place.  will erase the old logo if one exists
  112. //  Parameters:
  113. //      nOldID - logo location to erase (if it exists)
  114. //      nNewID - logo location to draw in now
  115. void CCustom1Dlg::DrawLogo(int nOldID, int nNewID)
  116. {
  117.     CDC* pdc = GetDC();
  118.  
  119.     if (nNewID == nOldID && nOldID >= RAD_UPLEFT)       // redraw without erase if same spot
  120.     {
  121.         DrawBitmap(pdc, IDB_LOGO_SMALL, nNewID);
  122.         return;
  123.     }
  124.  
  125.     if (nOldID >= RAD_UPLEFT)   // there is an old ID present, so erase it
  126.         EraseBitmap(pdc, nOldID);
  127.  
  128.     // draw the logo in the new spot
  129.     DrawBitmap(pdc, IDB_LOGO_SMALL, nNewID);
  130. }
  131.  
  132. // Determine the rectangle we need to draw the desired bitmap in
  133. //  there are three kinds of bitmaps expected here:
  134. //   1. the 'big' bitmap with the picture of the dialog box on it
  135. //   2. the 'baby' bitmap that represents the logo that shifts around on the 'big' bitmap
  136. //   3. the 'press me' bitmap that goes in the middle of the dialog box
  137. void CCustom1Dlg::GetBitmapRect(int nLocID, LPRECT rect)
  138. {
  139.     if (nLocID == BT_DLGPIC)    // major bitmap
  140.     {
  141.         rect->left = BMP_LEFT;
  142.         rect->top = BMP_TOP;
  143.         rect->right = BMP_LEFT + BMP_WIDTH;
  144.         rect->bottom = BMP_TOP + BMP_HEIGHT;
  145.         return;
  146.     }
  147.     else if (nLocID == BT_PRESS_ME)     // looking for location of 'press me' bitmap
  148.     {
  149.         rect->left = BMP_LEFT - 10 + (BMP_WIDTH - m_nPressWidth)/2;
  150.         rect->top = BMP_TOP + (BMP_HEIGHT - m_nPressHeight)/2;
  151.         rect->right = rect->left + m_nPressWidth;
  152.         rect->bottom = rect->top + m_nPressHeight;
  153.         return;
  154.  
  155.     }
  156.     else if (nLocID == RAD_NOLOGO)      // no baby bitmap needed
  157.     {
  158.         rect->top = rect->bottom = rect->left = rect->right = 0;
  159.         return;
  160.     }
  161.  
  162.     // figure out where to put the baby bitmap (small logo)
  163.     if (nLocID == RAD_LOLEFT || nLocID == RAD_LORIGHT)
  164.         rect->top = BMP_TOP + BMP_HEIGHT - 30;
  165.     else
  166.         rect->top = BMP_TOP + 25;
  167.     if (nLocID == RAD_LOLEFT || nLocID == RAD_UPLEFT)
  168.         rect->left = BMP_LEFT + 15;
  169.     else
  170.         rect->left = BMP_LEFT + BMP_WIDTH - 30;
  171.  
  172.     rect->right = rect->left + m_nLogoWidth;
  173.     rect->bottom = rect->top + m_nLogoHeight;
  174. }
  175.  
  176. // erase a bitmap.  do NOT call this from OnPaint.  doing so causes an infinite recursion
  177. //  and crashes MSVC very nicely (not).  (MSVC will crash in this case only because the
  178. //  program you are actually running is the IDE itself.  If you do this kind of stuff in
  179. //  a different .exe, you will crash that .exe instead.)
  180. void CCustom1Dlg::EraseBitmap(CDC* pdc, int nLocID)
  181. {
  182.     RECT rect;
  183.  
  184.     GetBitmapRect(nLocID, &rect);
  185.     RedrawWindow(&rect, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
  186. }
  187.  
  188. // draw a bitmap
  189. //  Parameters:
  190. //            pdc - device context to draw in
  191. //      nBitmapID - which bitmap to draw
  192. //         nLocID - where to draw it
  193. void CCustom1Dlg::DrawBitmap(CDC* pdc, int nBitmapID, int nLocID)
  194. {
  195.     CDC dcMem;
  196.     RECT rect;
  197.  
  198.     if (nLocID == RAD_NOLOGO)   // nothing to do
  199.         return;
  200.  
  201.     if (!dcMem.CreateCompatibleDC(pdc))
  202.         return;
  203.  
  204.     CBitmap picture;
  205.     picture.LoadBitmap(nBitmapID);
  206.     BITMAP bitmap;
  207.     picture.GetObject(sizeof (BITMAP), &bitmap);
  208.  
  209.     GetBitmapRect(nLocID, &rect);
  210.  
  211.     CBitmap* pOldBitmap = dcMem.SelectObject(&picture);
  212.     pdc->BitBlt(rect.left, rect.top, bitmap.bmWidth, bitmap.bmHeight, &dcMem, 0, 0, SRCCOPY);
  213.     dcMem.SelectObject(pOldBitmap);
  214. }
  215.  
  216. // user clicked one of the logo location radio buttons
  217. void CCustom1Dlg::OnLogoClicked(UINT /* nCmdID */)
  218. {
  219.     int oldLogoSpot = m_nLogoSpot;
  220.  
  221.     UpdateData();
  222.     DrawLogo(oldLogoSpot, m_nLogoSpot);
  223. }
  224.  
  225. void CCustom1Dlg::OnPressMe()
  226. {
  227.     UpdateData();
  228.  
  229.     CPaintDC dc(this); // device context for painting
  230.  
  231.     // this erase forces a redraw of the 'press me' button area.
  232.     //  if we don't do a RedrawWindow (such as is done in EraseBitmap()),
  233.     //  the bitmap won't paint regardless of the value of m_nPressMe.
  234.     //  by restricting the area that gets redrawn (erased first in this
  235.     //  case), we avoid flicker.
  236.     EraseBitmap(&dc, BT_PRESS_ME);
  237.     if (m_nPressMe)
  238.         DrawBitmap(&dc, IDB_PRESS_ME, BT_PRESS_ME);
  239. }
  240.  
  241. BOOL CCustom1Dlg::OnInitDialog()
  242. {
  243.     CAppWizStepDlg::OnInitDialog();
  244.  
  245.     // pick up sizing information for the logo
  246.     SetBitmapSize(IDB_LOGO_SMALL, &m_nLogoWidth, &m_nLogoHeight);
  247.  
  248.     // pick up sizing information for the 'press me' button
  249.     SetBitmapSize(IDB_PRESS_ME, &m_nPressWidth, &m_nPressHeight);
  250.  
  251.     m_nLogoSpot = IDC_LOGO_LL - IDC_LOGO_UL;
  252.     m_nPressMe = TRUE;
  253.     UpdateData(FALSE);
  254.  
  255.     return TRUE;  // return TRUE unless you set the focus to a control
  256.                   // EXCEPTION: OCX Property Pages should return FALSE
  257. }
  258.  
  259. // initialize the bitmap size for the specified bitmap ID
  260. void CCustom1Dlg::SetBitmapSize(int nID, int* pwidth, int* pheight)
  261. {
  262.     CBitmap picture;
  263.     picture.LoadBitmap(nID);
  264.     BITMAP bitmap;
  265.     picture.GetObject(sizeof (BITMAP), &bitmap);
  266.     *pwidth = bitmap.bmWidth;
  267.     *pheight = bitmap.bmHeight;
  268. }
  269.  
  270. // returns which dialog box bitmap we need (with or without help button on it as appropriate)
  271. int CCustom1Dlg::GetDlgBitmapID()
  272. {
  273.     if (logowizaw.m_Dictionary.Lookup(_T("HELP"), CString("1")))
  274.         return IDB_DLGPIC_WHELP;
  275.     else
  276.         return IDB_DLGPIC_NOHLP;
  277. }
  278.  
  279. void CCustom1Dlg::OnPaint()
  280. {
  281.     CPaintDC dc(this); // device context for painting
  282.  
  283.     CBitmap pattern;
  284.     pattern.LoadBitmap(IDB_YELLOW_PATTERN);
  285.     CBrush brush(&pattern);
  286.     RECT rectBmp;
  287.     GetBitmapRect(BT_DLGPIC, &rectBmp);
  288.     CPen penBogus(PS_SOLID, 0, COLORREF(0));
  289.     CPen* pOldPen = dc.SelectObject(&penBogus);  // Remember current pen.
  290.  
  291.     DrawBitmap(&dc, GetDlgBitmapID(), BT_DLGPIC);   // major bitmap (dialog box picture)
  292.     DrawBitmap(&dc, IDB_LOGO_SMALL, m_nLogoSpot);   // baby bitmap (logo to go on above)
  293.     if (m_nPressMe)
  294.         DrawBitmap(&dc, IDB_PRESS_ME, BT_PRESS_ME); // 'press me' button
  295.  
  296.     // Since the other two bitmaps are contained entirely on the major bitmap, we only have
  297.     //  to worry about the major one when we draw the background.  If all of the bitmaps
  298.     //  were not contained in the same rectangle, we would have to worry about all of them
  299.     //  when drawing the background.
  300.  
  301.     // Draw yellow ABOVE bitmap(s)
  302.     RECT rect = {0, 0, 0, 0};
  303.     rect.bottom = rectBmp.top;
  304.     rect.right = RIGHT_YELLOW + 1;
  305.     dc.DPtoLP(&rect);
  306.     dc.FillRect(&rect, &brush);
  307.  
  308.     // draw yellow to LEFT of bitmap(s)
  309.     rect.left = 0;
  310.     rect.top = rectBmp.top;
  311.     rect.right = rectBmp.left;
  312.     rect.bottom = rectBmp.bottom;
  313.     dc.DPtoLP(&rect);
  314.     dc.FillRect(&rect, &brush);
  315.  
  316.     // Draw yellow BELOW bitmap(s)
  317.     rect.left = 0;
  318.     rect.top = 0;
  319.     rect.right = 1;
  320.     rect.bottom = BOTTOM_YELLOW_DLGU;
  321.     MapDialogRect(&rect);
  322.     rect.right = RIGHT_YELLOW + 1;
  323.     rect.top = rectBmp.bottom;
  324.     dc.DPtoLP(&rect);
  325.     dc.FillRect(&rect, &brush);
  326.  
  327.     // Draw right border lines
  328.     CPen penGray(PS_SOLID, 0, 0x00808080);
  329.     dc.SelectObject(&penGray);
  330.     dc.MoveTo(rect.right, 0);
  331.     POINT point;
  332.     point.x = rect.right;
  333.     point.y = rectBmp.top;
  334.     dc.DPtoLP(&point);
  335.     dc.LineTo(point.x, point.y);
  336.     point.x = rect.right;
  337.     point.y = rectBmp.bottom;
  338.     dc.DPtoLP(&point);
  339.     dc.MoveTo(point.x, point.y);
  340.     dc.LineTo(point.x, rect.bottom);
  341.  
  342.     CPen penWhite(PS_SOLID, 0, 0x00ffffff);
  343.     dc.SelectObject(&penWhite);
  344.     dc.MoveTo(rect.right+1, 0);
  345.     point.x = rect.right+1;
  346.     point.y = rectBmp.top;
  347.     dc.DPtoLP(&point);
  348.     dc.LineTo(point.x, point.y);
  349.     point.x = rect.right+1;
  350.     point.y = rectBmp.bottom;
  351.     dc.DPtoLP(&point);
  352.     dc.MoveTo(point.x, point.y);
  353.     dc.LineTo(point.x, rect.bottom);
  354.  
  355.     // Restore original pen
  356.     dc.SelectObject(pOldPen);
  357. }
  358.