Click here to Skip to main content
Click here to Skip to main content

Address Book

By , 6 Aug 2000
 

Sample Image

Introduction

Address Book demonstrates the use of GfxListCtrl control, CHyperlink class, CSystemTray class in one useful application. It also demonstrates dropdown tool button and well as using the template class CArray.

Even though a lot of programs at CodeProject come with samples, beginners find it difficult to learn how to actually use them in real application because the demos usually stick to just displaying the capabilities of that control. I decided to write a program which will not just demonstrate the functionality of the control but also how to make it work for you in your programs.

I will be focusing on the GfxListCtrl because my program is based around it. GfxListCtrl is written by Iuri Apollonio. CHyperLink and CSystemTray are written by Chris Maunder.

How do I use the Text callback function ?

Well, first of all I create a class called CPerson. This class holds all the details about the person and the Serialize function is overloaded to save and load the details.

An array is created to hold the CPerson objects as in CAddressDoc as

CArray<CPerson,CPerson&> m_PersonArray;

This makes it easy to use the TextCallBack function. Your TextCallBack function for the GfxListCtrl is declared as

void GetTextCallback(int iIndex, int iSubItem, long lCode, CString &cs)

where lCode gives which item in the array is required. iIndex and iSubItem gives you the row and column respectively on the screen. To get the actual column you will have to use GetColumnIndex() member function of the GfxListControl, which means in your view class you would write something like this

void CAddressView::GetTextCallback(int iIndex, <BR>   int iSubItem, long lCode, CString &cs)
{
   int rc = wndList.GetColumnIndex(<BR>     iSubItem); // wndList is the GfxListControl
   CPerson person;
   cs = "";
   if (GetDocument()->m_PersonArray.GetSize() == 0 || 
   GetDocument()->m_PersonArray.GetSize() < (iIndex + 1)) {
     return;
   }
   person = GetDocument()->m_PersonArray[lCode - 1 ];
   switch (rc) {
     case 0: cs.Format("%d", iIndex + 1 ); break;
     case ADDR_FIRST_NAME: cs = person.m_strFirstName;  break;
     case ADDR_LAST_NAME:  cs = person.m_strLastName;   break;
     case ADDR_MIDDLE_NAME:cs = person.m_strMiddleName; break;
     case ADDR_NAME:       cs = person.m_strName;       break;
     case ADDR_NICK_NAME:  cs = person.m_strNickName;   break;
     case ADDR_EMAIL:      cs = person.m_strEMail;      break;
     default:  cs.Format("%d, %d", lCode, rc);
   }
}

For the AutoPreview alone you have to draw the text you want on to the screen in the function

 long CAddressView::GetExInfoCallback(LXHDREX * pLx)

as

   :
   :
   case NTEX_AUTOPREVIEW: {
      LXHDREX_DIV * pLxEx = (LXHDREX_DIV *) pLx;
      COLORREF ocr = pLxEx->pDC->SetTextColor(RGB(0,0,255));
      pLxEx->pDC->DrawText(<BR>             GetDocument()->m_PersonArray[pLx->dwItemData - 1].m_strNotes , 
             pLxEx->rcItem, DT_END_ELLIPSIS|DT_WORDBREAK);
      pLxEx->pDC->SetTextColor(ocr);
      return 1;
}

where m_PersonArray[Index].strNotes is the text I want it to display.

How to solve the double click problem of GfxListCtrl when the tooltip is displayed

To solve the double click problem just make the following changes to the class CGfxListTip.

Add the style CS_DBLCLKS to the WNDCLASS as

CGfxListTip::CGfxListTip()
{
   WNDCLASS wndcls;
   HINSTANCE hInst = AfxGetInstanceHandle();
   if(!(::GetClassInfo(hInst, GFXLISTTIP_CLASSNAME, &wndcls)))
   {
     wndcls.style = CS_DBLCLKS | CS_SAVEBITS ; // Xavier added CS_DBLCLKS 
     wndcls.lpfnWndProc = AfxWndProc; // Xavier changed from ::DefWindowProc
     wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
     :
     :

and add the line

case WM_LBUTTONDBLCLK: 

to the function

BOOL CGfxListTip::PreTranslateMessage(MSG* pMsg)

as

BOOL CGfxListTip::PreTranslateMessage(MSG* pMsg)
{
   CWnd *pWnd;
   int hittest;

   switch(pMsg->message)
   {
     case WM_LBUTTONDBLCLK:         // Xavier added
     case WM_LBUTTONDOWN:
     case WM_RBUTTONDOWN:
     case WM_MBUTTONDOWN:
     POINTS pts = MAKEPOINTS(pMsg->lParam);
     POINT  point;
     point.x = pts.x;
     :
     :

To use double click features in your program derive a class from GfxListCtrl. In my program that class is CAddressCtrl.

You have to override the OnLButtonDblClk(UINT nFlags, CPoint point) member function. Pass the point to CGfxListCtrl::HitTestEx(CPoint & point, int * col) member function and it will return to you the physical row and column on the screen at which the double click occurred. You can use the GetItemTextEx(index,column,cs) function where cs is a CString object to get the text of that Item. If you need to know the actual column on which the double click occurred like I do then you will have to use

column = pManager->FindColumnById(GetColumnIndex(column));

Based on this you can take the required action. In my program if you double click on the phone number it dials that number or double clicking on the URL will take you there. Here is the code

void CAddressCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
   if( GetFocus() != this ) SetFocus();
   int index, column;
   if ((index = HitTestEx(point, &column)) != -1) {
   if (column > 0 )  {
      CString cs;
      CString strURL;
      CString strName;
      CString strComment;
      GetItemTextEx(index,column,cs);
      if (pManager) {
         column = pManager->FindColumnById(GetColumnIndex(column));
      }
      switch (column) {
        case ADDR_EMAIL: 
          if (!cs.IsEmpty()) {
            strURL.Format("mailto:%s",(LPCTSTR)cs);
            CHyperLink::GotoURL(strURL,SW_SHOWNORMAL);
            break;
          }
      case ADDR_PERSONAL_WEB_PAGE:
      case ADDR_BUSINESS_WEB_PAGE:
          if (!cs.IsEmpty()) {
            if (strncmp((LPCTSTR) cs, "http://",7)==0)
              strURL=cs;
            else {
              strURL.Format("http://%s",(LPCTSTR)cs);
            }
            CHyperLink::GotoURL(strURL,SW_SHOWNORMAL);
            break;
          }
     case ADDR_HOME_PHONE:
     case ADDR_BUSINESS_PHONE:
         if (!cs.IsEmpty()) {
            if ( column == ADDR_BUSINESS_PHONE)
               strComment = "Business Number";
            else
               strComment = "Home Number";
            GetItemTextEx(index,ADDR_NAME,strName);
            if (tapiRequestMakeCall(cs,"Address",strName, strComment)!=0) {
              AfxMessageBox("Unable to dial the number");
            }
            break;
         }
    default: 
            DisplayProperties();
     }
   }
   }
   CGfxListCtrl::OnLButtonDblClk(nFlags, point);
}

I modified Chris Maunder's class (CHyperLink) and made the GotoURL and GetRegKey member functions as static so that they can be called directly without the need to create an instance of the class. tapiRequestMakeCall is the TAPI function to make a call. If you want to use it in your project just include <tapi.h> and TAPI32.LIB into your project.

Serializations of the Template class CArray

To load and save my address array I serialized the CArray derived class as follows

template <> 
void AFXAPI SerializeElements <CPerson> ( <BR> CArchive& ar, CPerson* pNewPersons, int nCount ) {
   for ( int i = 0; i < nCount; i++, pNewPersons++ )    {
       // Serialize each CPerson object
       pNewPersons->Serialize( ar );
   }
}
which makes the serialization of my CDocument class as simple as
void CAddressDoc::Serialize(CArchive& ar)
{
   m_PersonArray.Serialize(ar);
}

You can start the address book program with /tray as a command line parameter to tray it as it starts up.

If you like this program please let me know. If you want anymore details ask me I will it try to add it to this page.

Wishing you all the best with Visual C++

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xavier John
Software Developer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralAddress Bookmemberkiransrinivas28 Feb '11 - 4:46 
What is the username and Password for address book Project
General[Message Deleted]memberit.ragester28 Mar '09 - 5:38 
[Message Deleted]
QuestionHow to remove some of the fields in the list?memberreiner tolentino20 Nov '07 - 23:25 
How to remove some of the fields in the list? For Example I only want the fields First Name, Last Name, Email and Home Phone fields to appear in the list, how can I do it?
 
Thanks.
GeneralA Great Tutorial!membergoiania4 May '05 - 10:00 
Many thanks for your article.
Best Regards.

Generalhelp address bookmemberpromego2 May '05 - 4:03 

hi...i have to inform that i'm beginner at visual c++.

i have done a simple address book programme (not file based, with access database)(oleeeeey). but have a problem.there isn't search engine in prog.Help me,please.need to codes and how do it?
 


 
celica gt4
General.SetHotItem(); problemsussAnonymous31 Mar '05 - 4:30 
Hi there, How to fix list.SetHotItem(index);
? Its nt workin here Frown | :(
Thanks ahead,
GeneralCSVmemberimajit29 Mar '05 - 19:06 
I am unable to use import function.
whenever i import my yahoo.csv file ,empty rows get added to the list.
can u help me out
GeneralRe: CSVmemberXavier John1 Apr '05 - 7:04 
is your CSV in the same format as the one used by address book?
Generalisdn sms facsimilememberawani green12 Feb '05 - 0:22 
I want to create aplication use the phone line, but i don't now how i can connect to the phone line with modem. I want to use sms and facsimile from it.
 
help me ( i want use c++ language)

 
awani green
Generalplease help me Xavier:code for tapi in vc++ for accepting incoming callsmemberabhiaruna26 Jan '05 - 18:26 
i'm doing my final year project "information enquiry system for an organization using 'interactive voice response systems'"Smile | :)
for this i need tapi and sapi codes for detecting an incoming call and answer to the call by sending voice messages for this we need text to speech conversation Confused | :confused: Unsure | :~ so please help me with my projectSmile | :)
my email id is abhi_friend99@yahoo.co.in
GeneralRe: please help me Xavier:code for tapi in vc++ for accepting incoming callsmemberXavier John28 Mar '05 - 14:39 
Did you look at the sample
http://www.codeproject.com/internet/TAPISample.asp[^]
General(SOS) Please Help me Xavier John...membervahid.k1LOO6 Jan '05 - 5:44 
D'Oh! | :doh:
 
Dear Sir,
First of all,I would like to express my appreciation.Thanks alot
for writing such a wonderful program.It really helps me alot in my study.
I am still a beginner in VC++ programming.Actually,I am engaged in a project (an answering machine).
In this project,I include "tapi.h" and "mmsystem.h" .
But I'm getting a problem in the link of code in Visual C++ 6.0 :
" error LNK2001 : Unresolved external Symbol mmioOpen... "
Please help me.
My E-mail : vahid_k1LOO@iryahoo.com
I would be very happy if you could answer my questions.
Thanks again.Blush | :O

 
v.k1LOO
GeneralRe: (SOS) Please Help me Xavier John...memberXavier John6 Jan '05 - 6:37 
You need to add Winmm.lib to the project
 
From MSDN.
 
HMMIO mmioOpen(
LPSTR szFilename,
LPMMIOINFO lpmmioinfo,
DWORD dwOpenFlags
);
 
Requirements
 
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Mmsystem.h; include Windows.h.
Library: Use Winmm.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT/2000/XP.

QuestionHow To Solve itmemberthienle5 Nov '03 - 14:55 
Smile | :) Poke tongue | ;-P Cry | :(( OMG | :OMG:
I am doing a project on create a data base to insert books( include booktitle, author name, and book subject). what I have to do is to insert book in unsorted order of class Bookinfo, then create another sorted class to store books in order by 3 key searches from the 1.booktitle, 2.authoranme,and 3.booksubject.for Example,, I entered first book name Noting Hills, Delson, F. G. Fantasy and store in and array[0] of bookType class and keep insert couples of books to array[1], array[2] and so on. when I want to Print out by Sorted order
through thier subscript of class BookType ,how could I dothis?
 
here is example: in insert
[0]Best Men Frankie,G.D. Romatic
[1]Noting Hills Delson, F. G. Fantasy
[2]Always Be James,Eric Action
 
and want to print on alphabet order by comparing between books and print out this order according to their subcripts 2 then 0, then 1.. Can you give me any idea ?
 
A new C++
GeneralSerializing CArraymembermellertson14 Aug '03 - 9:57 
I'm trying to serialize a CArray derived class. I'm not an expert with template classes, so bear with me. When you implement the SerializeElements() function, how do you declare it as part of your CPerson class? Is that implied as part of your definition below:
 
template <> 
void AFXAPI SerializeElements <CPerson> ( CArchive& ar, CPerson* pNewPersons, int nCount ) {
   for ( int i = 0; i < nCount; i++, pNewPersons++ )    {
       // Serialize each CPerson object
       pNewPersons->Serialize( ar );
   }
}
 
Thanks in advance,
 
Mike Ellertson
GeneralRe: Serializing CArraymembermellertson14 Aug '03 - 10:01 
Sorry I posted the wrong code before, here's the correct code:
 
template <> 
void AFXAPI SerializeElements <CPerson> ( CArchive& ar, CPerson* pNewPersons, int nCount ) {
   for ( int i = 0; i < nCount; i++, pNewPersons++ )    {
       // Serialize each CPerson object
       pNewPersons->Serialize( ar );
   }
}

 
Mike Ellertson
GeneralVC.net 2003 Problem!memberYoyoboy31 Jul '03 - 23:55 
It seems not work well in VS.net 2003.I think it caused by th difference in Syntax, and Who can help me??
Thank you!
GeneralRepeatedly causing an ASSERT when converted to VC++ 7memberpariann11 May '03 - 20:44 
In GFXColumnManager
 
for (t = 0; t < iDefColumn; t++)
{
idx = FindColumnById(pDefColumn[t]);
ASSERT(idx >= 0);
if (idx >= 0)

Once I compile the code, before the program starts, I get an ASSERT at this point. When I close the program there is an additional ASSERT on line 209 in the same file. Any idea why this is happening? The only thing I have changed is the code for OnToolBarDropDown, the pointers in the function were not working properly so I changed the code to a function that you can find in the sample 'mfcie'. This works to allow the drop down from the toolbar. I can't see how that would in any way affect the Column manager code. If anyone could explain to me how to get past the assertion I would appreciate it.
 
ComputerQueen
QuestionHow to use the address book with other projectmembervvv_slava9 May '03 - 14:35 
I have the some dialog box with "book" switch and how to use the Address book application with my project, and create to address book after pushing on the "book" buttom.Confused | :confused:
 
Thank you for additional information
AnswerRe: How to use the address book with other projectmemberXavier John10 May '03 - 4:19 
Use CreateProcess API to start address book when the "book" button is pressed.
GeneralRe: How to use the address book with other projectmembervvv_slava10 May '03 - 8:27 
Thank you for help, but my main problem that I want to send or get data between two applications, therefore I want build common application from two work application as:
1. my project that read to the address book after buttom pusshing
2. address book application that should allow to get or send data to my project.
 

How I can to compile two project together (build one common code) and add any dependences or function, that allow to do this operation.
 
Thank you,
Questionhow Uses tapi.h in C++ builder 6.0membersnake_plus_plus5 Mar '03 - 10:29 
hi i don't know how uses the library tapi.h in c++builder
i,m make the Answering Machine.
please help me
 

thenks
GeneralProblem with tapirequestmakecall() as defined in tapi32.dllsussRahul Rana7 Feb '03 - 19:38 
Hi I'm getting a problem in Assisted Telephony.I'm developing
a telephony application in which i need to place a call
through my web browser(i.e internet explorer).For that
i've developed an activex control in visual basic 6.0. I'm
using tapirequestmakecall() as defined in tapi32.dll but
problem arises, when this control loads then it invokes
phone dialer of windows 2000 but place an Internet call
instead of telephone call.And i don't find a parameter or
flag to pass through this function so that i can make
forcibly a " Telephone Call". Please tell me the solution
(only for windows 2000 prof OS) as early as possible.
I would be greatful to you all for suggesting me possible
answer as soon as possible at rahulrana82@yahoo.com
Thanks
Rana

General2 convert x Dialog projectmemberkits20 Jan '03 - 3:11 
Hi ,
can any one plz tell me how 2 convert the whole address book project into
a dialog based project.Confused | :confused:
Pla help me out
thanx in advance

 
krishnaswamy
GeneralRe: 2 convert x Dialog projectmemberXavier John20 Jan '03 - 3:43 
Start by studing GfxListCtrl at www.codeguru.com
GeneralEquation editormemberdodinh20 Jan '03 - 2:29 
I am studying about "Equation editor". May I use your code ?
 
wewqe
GeneralI can't change the lable in the columnssussAngel Gavrilov10 Aug '02 - 23:41 
I'm very new in MFC. How is the way to change the column's header?
pManager->DefineColumn(0, "", NULL,..........
pManager->DefineColumn(1, "First Name",........
pManager->DefineColumn(2, "Last Name",..........
When I change this strings("First Name", "Last Name"), after the compilation nothing is changed, way?
GeneralRe: I can't change the lable in the columnssussAngel Gavrilov11 Aug '02 - 0:54 
Smile | :) I solve this problem. Just ignore the
pManager->ReadFromProfile("AddressList");
, and make changes in
pManager->DefineColumn(..........
The migration from c/c++ to VC is very hard for me.
Wink | ;)

Questioncan not adjust the wide of first columnsussFujun13 Jul '02 - 12:28 
Dear Xavier John,
 
When the address records exceed 100, the index column(first column) will overlap on the second column, I have tried to adjust the width in the init code. but it didnot work.
 
Thanks a lot for your sample code!
 
Richard
AnswerRe: can not adjust the wide of first columnsussAngel Gavrilov11 Aug '02 - 1:07 
You must edit the arguments right here:
pManager->DefineColumn(0, "", NULL, LVCFMT_LEFT, 40, fhNoSortArrow|fhNoResizeColumn);
in AddressView.cpp

QuestionMay I use your code?memberFish23 Dec '01 - 20:49 
Dear Sir,
First of all,I would like to express my appreciation.Thanks alot
for writing such a wonderful program.It really helps me alot in my study.
I am still a beginner in VC++ programming.Actually,I am engaged in a project.
I wish to include your program in my project.Of course,I am going to make some changes on it.Is it possible for me to do that?My another question is
what are the conditions for using your code in a commercial project?
I would be very happy if you could answer my questions.
Thanks again.
 

 

 
A beginner in VC++.
AnswerRe: May I use your code?memberXavier John15 Jan '02 - 20:09 
Sure, you can use my code as you like.
Not everything in the sample is my code.
GfxListCtrl control, CHyperlink class, CSystemTray class are not my code so you have to findout from the respective authors.
And all the best Smile | :)
 
Regards,
Xavier
GeneralRe: May I use your code?memberArash2 Feb '02 - 22:05 
May I use your code?
GeneralRe: May I use your code?memberArmyman12b16 Sep '04 - 10:01 
WTF | :WTF: NO!
 
Smoove
QuestionAdd New Contact???memberParas Shah30 Jul '01 - 1:07 
Hi there,
I want to add new contact without opening the addressbook. Is there any way to do it??
 

AnswerRe: Add New Contact???memberXavier John30 Jul '01 - 4:49 
You could modify the address.dat file directly, but that will require some experimenting using a HEX editor to find out the format in which MFC CArchive class stores the data.
 
template <>
void AFXAPI SerializeElements ( CArchive& ar, CPerson* pNewPersons, int nCount ) {
for ( int i = 0; i < nCount; i++, pNewPersons++ ) {
// Serialize each CPerson object
pNewPersons->Serialize( ar );
}
}
 

GeneralRe: Add New Contact???memberParas Shah2 Aug '01 - 23:06 
I got the reply from u but still i need ur help. Address book is the separate application. And from another application i want to add new contact without using the addressbook application. and what i just want is the email address and name of the person as a new contact and the required info. is taken from the second application. How can i do that? What should i write in the address.dat file so that whenever i open the addressbook at that time the newly added contact will be appear in it.
GeneralRe: Add New Contact???memberXavier John3 Aug '01 - 8:20 
You could use the class CPerson in you second application. Fill in the data into this object and serilize this object to a file. Just look at how it in done the CAddressDoc.
If you are are familiar with serilizing MFC classes check the book Inside VC++.
Generalsearch functionsmemberTaketo17 Jun '01 - 8:17 
izit possible to include search functions too.
i'm new to c++. I'm much more familiar with visual basic and Java.Confused | :confused:
 
thanz
GeneralNotes Edit Box scrolls off the bordersussPeter Hopkins30 Aug '00 - 16:14 
How can the behavior be fixed? When more than one line's worth of information is typed in, the carriage return never occurs.
Thanks
 
Pete
GeneralRe: Notes Edit Box scrolls off the bordersussXavier John31 Aug '00 - 4:35 
I do not see this behaviour. In the properties dialog you can press Enter to move to the next line in the Notes field.
 
Regards,
Xavier
GeneralRe: Notes Edit Box scrolls off the bordersussPeter Hopkins31 Aug '00 - 10:37 
Thanks for the quick response but I still want to know how other programs code their notes edit boxes - for instance Outlook 2000, when entering notes for a contact, gracerfully moves to the next line just as I am typing in this box. I have coded some other small C++ applications derived from CFormView -always checking the multiline property of the edit box and I never could get the text to gracefully scroll down to the next line.
 
Thanks for all the help
 
Pete
GeneralSorting in the Address Book SamplesussAlex Mitchell10 Jul '00 - 6:26 
John, the column sorting feature of your sample application fails.
GeneralRe: Sorting in the Address Book SamplesussXavier John31 Aug '00 - 4:37 
It's fixed now.
 
Regards,
Xavie

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 7 Aug 2000
Article Copyright 1999 by Xavier John
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid