home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / VFORM.ZIP / Samples / vfTest / person3VF.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-10  |  19.7 KB  |  711 lines

  1. // -------------------------------------------------------------------------
  2. // Copyright @ 1997 TCK Software, Incorporated
  3. // All Rights Reserved
  4. // -------------------------------------------------------------------------
  5.  
  6. #include "stdafx.h"
  7. #include "person3VF.h"
  8. #include "resource.h"
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. // Static Data Members
  17.  
  18. VTIPerson::VTIPerson()
  19. {
  20.     m_nRecNo = 0;
  21.     m_name[0] = 0;
  22.     m_note[0] = 0;
  23.     m_nPhoneCnt = 0;
  24. }
  25.  
  26. VTIPersonPhone::VTIPersonPhone()
  27. {
  28.     m_nRecNo = 0;
  29.     m_nPhoneIdx = 0;
  30.     m_phoneDesc[0] = 0;
  31.     m_phone[0] = 0;
  32. }
  33.  
  34. // -------------------------------------------------------------------------
  35. // CPerson3Hdr Constructor
  36. // -------------------------------------------------------------------------
  37. CPerson3Hdr::CPerson3Hdr()
  38. {
  39.     Height(40);
  40.  
  41.     m_chkSelectors.Init(this, IDVC_CHK_SELECTORS, _T("Selectors"), 5,5,80,20);
  42.     m_lblBackGround.Init(this, -1, _T("Background:"), 100,7,83,20);
  43.     m_lstBgOption.Init(this, IDVC_BG_OPTION, _T("Bitmap"), 185,5,90,20);
  44.     m_btnSetBmp.Init(this, IDVC_SET_BMP, _T("Set Bmp"), 285,5,70,20);
  45.     m_chkShadow.Init(this, IDVC_CHK_SHADOW, _T("Shadow"), 370,5,80,20);
  46.     m_lstBoxStyle.Init(this, IDVC_BOX_STYLE, _T("Shadow"), 370,5,90,20);
  47.     m_nBackStyle = 0;
  48.     m_chkSelectors.Checked(TRUE);
  49.     m_chkShadow.Checked(TRUE);
  50.  
  51.     m_lstBgOption.AddString(_T("Normal"));
  52.     m_lstBgOption.AddString(_T("Green Bar"));
  53.     m_lstBgOption.AddString(_T("Paper Pad"));
  54.     m_lstBgOption.AddString(_T("Flat Look"));
  55.     m_lstBgOption.AddString(_T("Bitmap"));
  56.  
  57.     m_lstBoxStyle.AddString(_T("Normal"));
  58.     m_lstBoxStyle.AddString(_T("Shadow"));
  59.     m_lstBoxStyle.AddString(_T("Indented"));
  60.     m_lstBoxStyle.AddString(_T("Bumped"));
  61.  
  62.     AddCtl(&m_chkSelectors);
  63.     AddCtl(&m_lblBackGround);
  64.     AddCtl(&m_lstBgOption);
  65.     AddCtl(&m_btnSetBmp);
  66.     AddCtl(&m_lstBoxStyle);
  67. }
  68.  
  69. // -------------------------------------------------------------------------
  70. // CPerson3Ftr Constructor
  71. // -------------------------------------------------------------------------
  72. CPerson3Ftr::CPerson3Ftr()
  73. {
  74.     Height(35);
  75.     m_lblGoodbye.Init(this, -1, _T("Footer:"), 80,5,60,20);
  76.     m_ftrEdit.Init(this, IDVC_FTREDIT, _T("Goodbye"), 150,5,100,20);
  77.  
  78.     m_ftrEdit.LimitText(20);                    // Set max chars for m_ftrEdit
  79.  
  80.     AddCtl(&m_lblGoodbye);
  81.     AddCtl(&m_ftrEdit);
  82. }
  83.  
  84.  
  85. // -------------------------------------------------------------------------
  86. // CPerson3Row Constructor
  87. // -------------------------------------------------------------------------
  88. CPerson3Row::CPerson3Row(CPerson3VF* pVf)
  89. {
  90.     m_recno.Init(this, IDVCTREE_RECNO,     _T(""), 50,5,20,20);
  91.     m_btnPlus.Init(this, IDVCTREE_BTNPLUS, _T("+"), 75,3,18,18);
  92.     m_name.Init(this, IDVCTREE_NAME,       _T(""), 100,3,145,20);
  93.     m_note.Init(this, IDVCTREE_NOTE,       _T(""), 255,3,250,20);
  94.     m_phoneDesc.Init(this, IDVCTREE_PHONEDESC,  _T(""), 255,3,90,20);
  95.     m_phone.Init(this, IDVCTREE_PHONE,      _T(""), 355,3,160,20);
  96.  
  97. /*    --- If not for the Icon Pointer and Paper Pad look, 
  98. //  --- we would shift all the fields to the left, like so...
  99.     m_recno.Init(this, IDVCTREE_RECNO,     _T(""), 0,5,20,20);
  100.     m_btnPlus.Init(this, IDVCTREE_BTNPLUS, _T("+"), 25,3,18,18);
  101.     m_name.Init(this, IDVCTREE_NAME,       _T(""), 50,3,145,20);
  102.     m_note.Init(this, IDVCTREE_NOTE,       _T(""), 205,3,250,20);
  103.     m_phoneDesc.Init(this, IDVCTREE_PHONEDESC,  _T(""), 205,3,90,20);
  104.     m_phone.Init(this, IDVCTREE_PHONE,      _T(""), 305,3,160,20);
  105. */
  106.     m_name.LimitText(PERS2_NAME);
  107.     m_note.LimitText(PERS2_NOTE);
  108.  
  109.     m_phone.LimitText(PERS2_PHONE);
  110.     m_phoneDesc.LimitText(PERS2_PHONEDESC);
  111.  
  112.     SetIconPosition(5, 0);
  113.  
  114.     // --- Add a profile for each type of row to display ---
  115.     NewProfile(P2PROFILE_PERSON);
  116.     NewProfile(P2PROFILE_PHONE);
  117.  
  118.     VMorphProfile *pProfile;
  119.  
  120.     pProfile = GetProfile(P2PROFILE_PERSON);
  121.     // pProfile->AddCtl(&m_recno);
  122.     pProfile->AddCtl(&m_btnPlus);
  123.     pProfile->AddCtl(&m_name);
  124.     pProfile->AddCtl(&m_note);
  125.  
  126.     pProfile = GetProfile(P2PROFILE_PHONE);
  127.     pProfile->AddCtl(&m_phoneDesc);
  128.     pProfile->AddCtl(&m_phone);
  129.  
  130.     SetProfileIdx(P2PROFILE_PERSON);        // Default
  131.  
  132.     m_nBackStyle = 0;
  133.     SetForm(pVf);                // We need the form set BEFORE calling SetBG
  134.     SetEffect(VEFFECT_SHADOW);
  135. }
  136.  
  137. // -------------------------------------------------------------------------
  138. // CPerson3Row Destructor
  139. // -------------------------------------------------------------------------
  140. CPerson3Row::~CPerson3Row()
  141. {
  142. }
  143.  
  144.  
  145. // -------------------------------------------------------------------------
  146. // GetBackBmp
  147. // -------------------------------------------------------------------------
  148. HBITMAP CPerson3Row::GetBackBmp()
  149. {
  150.     return ((CPerson3VF*)Form())->GetBackBmp(); 
  151. }
  152.  
  153. // -------------------------------------------------------------------------
  154. // GetBackPalette
  155. // -------------------------------------------------------------------------
  156. HPALETTE CPerson3Row::GetBackPaletteHandle()
  157. {
  158.     return ((CPerson3VF*)Form())->GetBackPalette(); 
  159. }
  160.  
  161. // -------------------------------------------------------------------------
  162. // CPerson3Row SetEffect
  163. // -------------------------------------------------------------------------
  164. void CPerson3Row::SetEffect(int nEffect)
  165. {
  166.     int nEffectDepth = (nEffect == VEFFECT_SHADOW) ? 1 : 0;
  167.  
  168.     m_name.Effect(nEffect);
  169.     m_note.Effect(nEffect);
  170.     m_phoneDesc.Effect(nEffect);
  171.     m_phone.Effect(nEffect);
  172.  
  173.     m_name.EffectDepth(nEffectDepth);
  174.     m_note.EffectDepth(nEffectDepth);
  175.     m_phoneDesc.EffectDepth(nEffectDepth);
  176.     m_phone.EffectDepth(nEffectDepth);
  177.  
  178.     SetBG(m_nBackStyle);        // Switch us BACK from the gray (possibly)
  179. }
  180.  
  181. // -------------------------------------------------------------------------
  182. // CPerson3Row Background Drawing
  183. // -------------------------------------------------------------------------
  184. void CPerson3Row::SetBG(int nBackStyle)
  185. {
  186.     SetStyle(nBackStyle);
  187.  
  188.     CPerson3VF* pForm = (CPerson3VF *)Form();
  189.     COLORREF clr;
  190.     BOOL bTransparent = FALSE;
  191.     BOOL bNoInactBorder = TRUE;
  192.  
  193.     // These just look better in light gray
  194.     if(pForm->GetEffect() == VEFFECT_SUNKEN || 
  195.         pForm->GetEffect() == VEFFECT_RAISED)
  196.         clr = RGB(192,192,192);
  197.     else
  198.         clr = RGB(255,255,255);
  199.  
  200.     ResetCtl(m_name,      bTransparent, bNoInactBorder, clr);
  201.     ResetCtl(m_note,      bTransparent, bNoInactBorder, clr);
  202.     ResetCtl(m_phoneDesc, bTransparent, bNoInactBorder, clr);
  203.     ResetCtl(m_phone,     bTransparent, bNoInactBorder, clr);
  204.  
  205.     /* Not really needed anymore ------
  206.     switch(nBackStyle)
  207.     {
  208.     case VROW_BG_PAPER:                        // Paper
  209.     case VROW_BG_FLAT:                        // Flat
  210.     case VROW_BG_GREENBAR:                    // Greenbar
  211.     case VROW_BG_BMP:                        // Bitmap
  212.     default:                    // Normal
  213.     }
  214.     ---------------- */
  215. }
  216.  
  217.  
  218. // IMPLEMENT_DYNCREATE(CPerson3VF, VForm)
  219.  
  220. BEGIN_MESSAGE_MAP(CPerson3VF, VForm)
  221.     //{{AFX_MSG_MAP(CPerson3VF)
  222.     ON_WM_CREATE()
  223.     //}}AFX_MSG_MAP
  224. END_MESSAGE_MAP()
  225.  
  226. // -------------------------------------------------------------------------
  227. // CPerson3VF Constructor
  228. // -------------------------------------------------------------------------
  229. CPerson3VF::CPerson3VF()
  230. {
  231.     m_pFont = 0;                    // use default font
  232.     m_pPalMH = 0;
  233.     m_nBackIdx = 0;
  234.     m_hIcon = AfxGetApp()->LoadIcon(IDI_POINTHAND);
  235.     m_nRowHeight = 25;
  236.     m_nRowWidth = 510;
  237.     m_nRows = 0;                // Start at 400
  238.     m_nEffect = VEFFECT_SHADOW;
  239.     
  240.     // ------------- Header and footer with Something in them --------
  241.     CPerson3Hdr *pHdr = new CPerson3Hdr();
  242.     SetHeader(pHdr, FALSE);
  243.  
  244.     m_pFont = GetFonts()->GetOrAdd(_T("Arial"), 100);    
  245.  
  246.     if(!m_imgList.Create(IDB_IMG_TEST, 16, 0, RGB(0,255,255)))
  247.         TRACE(_T("CPerson3VF could not create image list\n"));
  248.     // m_imgList.SetBkColor(GetSysColor(COLOR_WINDOW));
  249.     if(!m_imgCycleList.Create(IDB_IMG_CYCLES, 16, 0, RGB(0,255,255)))
  250.         TRACE(_T("CPerson3VF could not create cycle image list\n"));
  251.     if(!m_imgPrintAnim.Create(IDB_IMG_PRINT_ANIM, 16, 0, RGB(0,255,255)))
  252.         TRACE(_T("CPerson3VF could not create print animation image list\n"));
  253.  
  254.     m_tree.SetSortCallback(SortFunc);        // Set the sorting function
  255.  
  256.       m_personDB.FileName(_T("person3.dat"));
  257.       if(!m_personDB.OpenOrCreate())
  258.       {
  259.           MessageBox(_T("Error opening/creating person2.dat"), _T("VForm Demo"),
  260.               MB_OK | MB_ICONEXCLAMATION);
  261.       }
  262.       SetPersonDB(&m_personDB);
  263. }
  264.  
  265. // -------------------------------------------------------------------------
  266. // CPerson3VF Destructor
  267. // -------------------------------------------------------------------------
  268. CPerson3VF::~CPerson3VF()
  269. {
  270. }
  271.  
  272. // -------------------------------------------------------------------------
  273. // CPerson3VF Load the tree structure
  274. // -------------------------------------------------------------------------
  275. void CPerson3VF::SetPersonDB(CPerson2DB *pDB)
  276. {
  277.     int i, j;
  278.     VTIPerson *pTPerson;
  279.     VTIPersonPhone *pTPhone;
  280.     CPerson2 data;
  281.     long nItem;
  282.  
  283.     m_pPersonDB = pDB;
  284.     int nRecords = m_pPersonDB->GetCount();
  285.     // m_tree.MsgCurPosition();
  286.  
  287.     for(i=0; i < nRecords; i++)
  288.     {
  289.         if(!m_pPersonDB->GetRec(i, data))
  290.         {
  291.             AfxMessageBox(_T("Error loading person data"));
  292.             nRecords = i;
  293.             break;
  294.         }
  295.         pTPerson = new VTIPerson;
  296.         pTPerson->m_nRecNo = i;
  297.         _tcscpy(pTPerson->m_name, data.m_name);
  298.         _tcscpy(pTPerson->m_note, data.m_note);
  299.         // if(!m_tree.InsertItem(pTPerson, VTI_ROOT, VTI_LASTCHILD))
  300.         if(!m_tree.InsertItem(pTPerson, VTI_ROOT, VTI_SORTCHILD))
  301.         {
  302.             AfxMessageBox(_T("Error adding Person to VTree"));
  303.             break;
  304.         }
  305.         // m_tree.MsgCurPosition();
  306.         nItem = m_tree.CurItem();
  307.         ASSERT(nItem >= 0);
  308.  
  309.         for(j=0; j < PERS2_MAX_PHONES; j++)
  310.         {
  311.             sPerson2Phone *pPhone = &data.m_phones[j];
  312.             if(pPhone->m_phoneDesc[0] == 0)    
  313.                 break;
  314.             pTPhone = new VTIPersonPhone;
  315.             pTPhone->m_nRecNo = i;
  316.             pTPhone->m_nPhoneIdx = j;
  317.             _tcscpy(pTPhone->m_phoneDesc, pPhone->m_phoneDesc);
  318.             _tcscpy(pTPhone->m_phone, pPhone->m_phone);
  319.             // if(!m_tree.InsertItem(pTPhone, nItem, VTI_LASTCHILD))
  320.             if(!m_tree.InsertItem(pTPhone, nItem, VTI_SORTCHILD))
  321.             {
  322.                 AfxMessageBox(_T("Error adding Phone to VTree"));
  323.                 break;
  324.             }
  325.             // m_tree.MsgCurPosition();
  326.         }
  327.         pTPerson->m_nPhoneCnt = j;
  328.     }
  329.  
  330.     long nRowCnt = m_tree.GetVisibleCount();
  331.     long nTotRowCnt = m_tree.GetCount();
  332.  
  333.     ResetNumRows(nRecords, 0);
  334. }
  335.  
  336.  
  337. BOOL CPerson3VF::SetBackBmp(LPCTSTR szFile)
  338. {
  339.     BOOL bRet;
  340.  
  341.     m_bmpBack.DeleteObject();                // remove old
  342.     bRet = m_bmpBack.LoadFile(szFile);        // load new
  343.     // m_pWnd->ResetPalette();
  344.     m_pPalMH->DoRealizePalette(TRUE);
  345.  
  346.     return bRet;
  347. }
  348.  
  349.  
  350. // -------------------------------------------------------------------------
  351. // Function to create a CPerson3Row
  352. // -------------------------------------------------------------------------
  353. VRow* CPerson3VF::InitRow()
  354. {
  355.     CPerson3Row *pRow = new CPerson3Row(this);
  356.     pRow->SetIcon(m_hIcon);
  357.     return(pRow); 
  358. }
  359.  
  360. // -------------------------------------------------------------------------
  361. // Called when a row needs to be put on the screen
  362. // -------------------------------------------------------------------------
  363. BOOL CPerson3VF::OnGetRow(VRow *pRow)
  364. {
  365.     CString s1;
  366.     CPerson3Row *r = (CPerson3Row*) pRow;
  367.     long idx;
  368.     VTreeItem *pItem;
  369.     VTIPerson *pPerson;
  370.     VTIPersonPhone *pPhone;
  371.  
  372.     idx = r->RowId();
  373.     pItem = m_tree.GetVisItem(idx);
  374.     ASSERT(pItem);
  375.     
  376.     switch(pItem->IsA())
  377.     {
  378.     case P2PROFILE_PERSON:
  379.         pPerson = (VTIPerson *) pItem;
  380.         r->m_name.SetWindowText(pPerson->m_name);
  381.         r->m_note.SetWindowText(pPerson->m_note);
  382.         r->SetProfileIdx(P2PROFILE_PERSON);
  383.         if(pPerson->m_nPhoneCnt == 0)
  384.             r->m_btnPlus.Visible(FALSE);
  385.         else
  386.         {
  387.             r->m_btnPlus.Visible(TRUE);
  388.             if(pPerson->IsExpanded())
  389.                 r->m_btnPlus.Text(_T("-"));
  390.             else
  391.                 r->m_btnPlus.Text(_T("+"));
  392.         }
  393.         break;
  394.     case P2PROFILE_PHONE:
  395.         pPhone = (VTIPersonPhone *) pItem;
  396.         r->m_phoneDesc.SetWindowText(pPhone->m_phoneDesc);
  397.         r->m_phone.SetWindowText(pPhone->m_phone);
  398.         r->SetProfileIdx(P2PROFILE_PHONE);
  399.         break;
  400.     default:
  401.         break;
  402.     }
  403.  
  404.     s1.Format(_T("%ld"), idx+1);
  405.     r->m_recno.SetWindowText(s1);
  406.  
  407.     return TRUE;
  408. }
  409.  
  410. // -------------------------------------------------------------------------
  411. // Called when a row needs to be saved (in the data)
  412. // -------------------------------------------------------------------------
  413. BOOL CPerson3VF::OnSaveRow(VRow *pRow)
  414. {
  415.     CPerson3Row *r = (CPerson3Row*) pRow;
  416.     long idx;
  417.     CPerson2    data;
  418.     sPerson2Phone *pPhoneData;
  419.  
  420.     VTreeItem *pItem;
  421.     VTIPerson *pPerson;
  422.     VTIPersonPhone *pPhone;
  423.  
  424.     idx = r->RowId();
  425.     long nRecId;
  426.     pItem = m_tree.GetVisItem(idx);
  427.     ASSERT(pItem);
  428.     
  429.     switch(pItem->IsA())
  430.     {
  431.     case P2PROFILE_PERSON:
  432.         pPerson = (VTIPerson *) pItem;
  433.         nRecId = pPerson->m_nRecNo;
  434.         if(!m_pPersonDB->GetRec(nRecId, data))    return FALSE;
  435.  
  436.         // --- Update our m_tree data ---
  437.         _tcscpy(pPerson->m_name, r->m_name.Text());
  438.         _tcscpy(pPerson->m_note, r->m_note.Text());
  439.  
  440.         // --- now update the database ---
  441.         _tcscpy(data.m_name, r->m_name.Text());
  442.         _tcscpy(data.m_note, r->m_note.Text());
  443.  
  444.         if(!m_pPersonDB->UpdateRec(nRecId, data))    return FALSE;
  445.         break;
  446.     case P2PROFILE_PHONE:
  447.         pPhone = (VTIPersonPhone *) pItem;
  448.         nRecId = pPhone->m_nRecNo;
  449.         if(!m_pPersonDB->GetRec(nRecId, data))    return FALSE;
  450.  
  451.         // --- Update our m_tree data ---
  452.         _tcscpy(pPhone->m_phoneDesc, r->m_phoneDesc.Text());
  453.         _tcscpy(pPhone->m_phone, r->m_phone.Text());
  454.  
  455.         // --- now update the database ---
  456.         pPhoneData = &data.m_phones[pPhone->m_nPhoneIdx];
  457.         _tcscpy(pPhoneData->m_phoneDesc, r->m_phoneDesc.Text());
  458.         _tcscpy(pPhoneData->m_phone, r->m_phone.Text());
  459.  
  460.         if(!m_pPersonDB->UpdateRec(nRecId, data))    return FALSE;
  461.         break;
  462.     default:
  463.         break;
  464.     }
  465.  
  466.     return TRUE;
  467. }
  468.  
  469. // -------------------------------------------------------------------------
  470. // Called when row(s) needs to be deleted from the data
  471. // -------------------------------------------------------------------------
  472. BOOL CPerson3VF::OnDelete()
  473. {
  474.     CString s1;
  475.     long nNumSelected = m_selectedList.Count();
  476.  
  477.     s1.Format(
  478.         _T("You have selected to delete %ld records\nActual delete not enabled in this demo"),
  479.         nNumSelected);
  480.     AfxMessageBox(s1);
  481.     return TRUE;                // Dont let delete key pass through
  482. }
  483.  
  484. // -------------------------------------------------------------------------
  485. // Called when a row needs to be added to the data
  486. // -------------------------------------------------------------------------
  487. BOOL CPerson3VF::OnAddRow(VRow *pRow)
  488. {
  489.     CPerson3Row *r = (CPerson3Row*) pRow;
  490.     int idx;
  491.     CPerson2    data;
  492.     long nItem;
  493.     int nRecId;
  494.     // nRecId = m_tree.GetRootCount();        // Next Person Id
  495.  
  496.     idx = r->RowId();
  497.  
  498.     _tcscpy(data.m_name, r->m_name.Text());
  499.     _tcscpy(data.m_note, r->m_note.Text());
  500.     data.m_deleted = 'N';
  501.  
  502.     if(!m_pPersonDB->AddRec(nRecId, data))
  503.         return FALSE;
  504.  
  505.     // We must also add the record to the tree
  506.     VTIPerson *pTPerson = new VTIPerson;
  507.     pTPerson->m_nRecNo = nRecId;
  508.     _tcscpy(pTPerson->m_name, data.m_name);
  509.     _tcscpy(pTPerson->m_note, data.m_note);
  510.     if(!m_tree.InsertItem(pTPerson, VTI_ROOT, VTI_LASTCHILD))
  511.     {
  512.         AfxMessageBox(_T("Error adding Person to VTree"));
  513.         return FALSE;
  514.     }
  515.     nItem = m_tree.CurItem();
  516.     ASSERT(nItem >= 0);
  517.  
  518.     return TRUE;
  519. }
  520.  
  521. // -------------------------------------------------------------------------
  522. // Called when a row is initially being added
  523. // -------------------------------------------------------------------------
  524. void CPerson3VF::OnStartAdd(VRow *pRow)
  525. {
  526.     CString s1;
  527.     CPerson3Row *r = (CPerson3Row*) pRow;
  528.     long idx;
  529.     // CPerson2   data;
  530.  
  531.     idx = r->RowId();
  532.     
  533.     s1.Format(_T("%ld"), idx+1);
  534.     r->m_recno.SetWindowText(s1);
  535.  
  536.     r->m_btnPlus.Visible(FALSE);
  537.     r->m_name.SetWindowText(_T(""));
  538.     r->m_note.SetWindowText(_T(""));
  539.     r->m_phoneDesc.SetWindowText(_T(""));
  540.     r->m_phone.SetWindowText(_T(""));
  541. }
  542.  
  543. // -------------------------------------------------------------------------
  544. // Called when a row is initially being added
  545. // -------------------------------------------------------------------------
  546. int    CPerson3VF::SortFunc(VTreeItem **ppItem1, VTreeItem **ppItem2)
  547. // int    SortFunc(const void *p1, const void *p2)
  548. {
  549.     VTreeItem *pItem1 = *ppItem1;
  550.     VTreeItem *pItem2 = *ppItem2;
  551.     int nType1 = pItem1->IsA();
  552.     int nType2 = pItem2->IsA();
  553.  
  554.     if(nType1 != nType2)
  555.         return nType2 - nType1;
  556.  
  557.     switch(nType1)
  558.     {
  559.     case P2PROFILE_PERSON:                        // Comparing 2 Person recs
  560.         {
  561.         VTIPerson *p1 = (VTIPerson *) pItem1;
  562.         VTIPerson *p2 = (VTIPerson *) pItem2;
  563.         return _tcscmp(p1->m_name, p2->m_name);
  564.         }
  565.         break;
  566.     case P2PROFILE_PHONE:
  567.         {
  568.         VTIPersonPhone *p1 = (VTIPersonPhone *) pItem1;
  569.         VTIPersonPhone *p2 = (VTIPersonPhone *) pItem2;
  570.         return _tcscmp(p1->m_phoneDesc, p2->m_phoneDesc);
  571.         }
  572.         break;
  573.     }
  574.  
  575.     return 0;                                    // Should never get here
  576. }
  577.  
  578.  
  579. // -------------------------------------------------------------------------
  580. // Called when a button is clicked
  581. // -------------------------------------------------------------------------
  582. void CPerson3VF::OnClick(VRow *pRow, int nId)
  583. {
  584.     CString s1, sBmpFile;
  585.     CPerson3Row *pPersonRow = (CPerson3Row*) pRow;
  586.     static _TCHAR szFilter[] = _T("Bitmaps (*.bmp)|*.bmp|All Files (*.*)|*.*||"); 
  587.  
  588.     switch(nId)
  589.     {
  590.     case IDVC_CHK_SELECTORS:
  591.         {
  592.             CPerson3Hdr *pHdr = (CPerson3Hdr *)Header();
  593.             if(pHdr->m_chkSelectors.Checked())
  594.                 UseSelectors(TRUE);
  595.             else
  596.                 UseSelectors(FALSE);
  597.             break;
  598.         }
  599.     case IDVCTREE_BTNPLUS:
  600.         {
  601.             // User wants to expand or contract row
  602.             long idx = pRow->RowId();
  603.             VTIPerson *pPerson;
  604.             pPerson = (VTIPerson*)m_tree.GetVisItem(idx);
  605.             ASSERT(pPerson);
  606.             if(pPerson->IsExpanded())
  607.             {
  608.                 pPerson->Collapse();
  609.                 pPersonRow->m_btnPlus.Text(_T("+"));
  610.                 pPersonRow->m_btnPlus.Draw();
  611.             }    
  612.             else
  613.             {
  614.                 pPerson->Expand();
  615.                 pPersonRow->m_btnPlus.Text(_T("-"));
  616.                 pPersonRow->m_btnPlus.Draw();
  617.             }
  618.  
  619.             long nNewRowCnt = m_tree.GetVisibleCount();
  620.             ResetNumRows(nNewRowCnt);
  621.             break;
  622.         }
  623.     case IDVC_SET_BMP:
  624.         {
  625.             CFileDialog dlg(TRUE, _T("bmp"), sBmpFile, 
  626.                 OFN_SHAREAWARE | OFN_PATHMUSTEXIST, szFilter); 
  627.             if(dlg.DoModal() != IDOK)
  628.                 break;
  629.  
  630.             sBmpFile = dlg.GetPathName();
  631.             if(SetBackBmp(sBmpFile) && m_nBackIdx == 4)
  632.             {
  633.                 RefreshScreen(VFR_BOTH);
  634.             }
  635.             break;
  636.         }
  637.     }
  638. }
  639.  
  640. // -------------------------------------------------------------------------
  641. // Called when list is closed is clicked
  642. // -------------------------------------------------------------------------
  643. BOOL CPerson3VF::OnEndList(VCtl* pCtl, CListBox* pLB)
  644. {
  645.     CPerson3Row *pRow;
  646.     CPerson3Hdr *pHdr;
  647.     int i;
  648.     int nBgStyle = VROW_BG_DEFAULT;
  649.  
  650.     switch(pCtl->Id())
  651.     {
  652.     case IDVC_BG_OPTION:
  653.         m_nBackIdx = pLB->GetCurSel();
  654.  
  655.         switch(m_nBackIdx)
  656.         {
  657.         case 0:    nBgStyle = VROW_BG_DEFAULT;        break;
  658.         case 1:    nBgStyle = VROW_BG_GREENBAR;    break;
  659.         case 2:    nBgStyle = VROW_BG_PAPER;        break;
  660.         case 3:    nBgStyle = VROW_BG_FLAT;        break;
  661.         case 4:    nBgStyle = VROW_BG_BMP;            break;
  662.         }
  663.  
  664.         // Reset detail rows to this style
  665.         pHdr = (CPerson3Hdr *)Header();
  666.         pHdr->SetStyle(nBgStyle);
  667.  
  668.         pRow = (CPerson3Row *)m_pDtlRow;
  669.         pRow->SetBG(nBgStyle);
  670.         pRow = (CPerson3Row *)m_pTmpRow;
  671.         pRow->SetBG(nBgStyle);
  672.  
  673.         RefreshScreen(VFR_BOTH);
  674.         break;
  675.     case IDVC_BOX_STYLE:
  676.         i = pLB->GetCurSel();
  677.  
  678.         switch(i)
  679.         {
  680.         case 0:        m_nEffect = VEFFECT_NORMAL;        break;
  681.         case 1:        m_nEffect = VEFFECT_SHADOW;        break;
  682.         case 2:        m_nEffect = VEFFECT_SUNKEN;        break;
  683.         case 3:        m_nEffect = VEFFECT_RAISED;        break;
  684.         default:    m_nEffect = VEFFECT_NORMAL;        break;
  685.         }
  686.  
  687.         // Reset detail rows to this style
  688.         pRow = (CPerson3Row *)m_pDtlRow;
  689.         pRow->SetEffect(m_nEffect);
  690.         pRow = (CPerson3Row *)m_pTmpRow;
  691.         pRow->SetEffect(m_nEffect);
  692.  
  693.         RefreshScreen(VFR_BOTH);
  694.     }
  695.     return TRUE;
  696. }
  697.  
  698.  
  699.  
  700. // -------------------------------------------------------------------------
  701. //    Start a timer for the form
  702. // -------------------------------------------------------------------------
  703. int CPerson3VF::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  704. {
  705.     if (VForm::OnCreate(lpCreateStruct) == -1)
  706.         return -1;
  707.     
  708.     return 0;
  709. }
  710.  
  711.