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

Beginner's Guide

By , 25 May 2005
 

Introduction

Dynamic Link Libraries, Multithreading... are all somehow advanced concepts for beginners. But as the word "simple", they are conceptually simple. The aim of this article is to give you some useful technical initiative knowledge on these concepts, especially for the beginners. The article is not moving towards the theoretical definitions of the concept.

Creating a simple DLL

DLL part:

  • Create an empty project on Win32 Dynamic-Link Library.
  • Create a new CPP file in your workspace. (On File View tab in the workspace, right click on the Source Files->Add Files to Folder.. then create a new CPP file).
  • Write your code as follows…
    #include <afxwin.h>
    extern "C" _declspec(dllexport) void SayHello()
    {
        AfxMessageBox(“Hello World”);
    }

Thatzaal all with the DLL code… Build it and get your DLL.

Application part:

  • Create an application wizard (dialog or SDI or MDI…. anything as your wish).
  • Use any message handler to test this DLL… say for example a button handler.
  • Use the following code to load your DLL:
    typedef void (*SayHello) (); // typedef a function pointer
    // load your dll into the memory
    HMODULE hmodule=::LoadLibrary("yourDLLName.dll"); 
    if(hmodule)
    {
        //get your function
        SayHello sm=(SayHello) GetProcAddress(hmodule,"SayHello"); 
        sm(); // thatzaal call your function now
    }
  • Take your DLL to the application’s path.…
  • Build your application now…..

Tips:

  • This is a simple single line code of the above application. It may cause problems if the DLL or the function does not exist…
    GetProcessAddress(LoadLibrary(“yourDLLName.dll”),”SayHello”)();
  • GetProcessAddress() will return the address of the function residing in your DLL. The second parameter is the exact function name that you are going for, so be sure the function name is spelled correctly.

Simple multithreading concept

  1. Create a structure for data transaction between your thread and application. Say for example:
    struct threadinfo{ 
        CString somedata; 
    } info;
  2. Declare a pointer member variable (object) of type CWinThread. Here, CWinThread *m_pthread.
  3. Initiate your thread anywhere in your application as follows:
    m_pthread=AfxBeginThread(functionname,(LPVOID) &info);

    AfxBeginThread() API takes two parameters, the function name (will be your thread) and the necessary information as threadinfo structure.

  4. Write your thread function as:
    UINT functionname(LPVOID param)
    {
        threadinfo *info=(threadinfo *)param;
        CString s=info->somedata;
        // handle your thread code here…
    }
  5. To terminate the thread:
    ::TerminateThread(m_pthread->m_hThread,0);

Minimizing your application to System tray

  1. Create your application in any wizard as your wish (SDI, MDI or dialog).
  2. Add a member variable for NOTIFYICONDATA and CMenu.

    Say for example:

    NOTIFYICONDATA m_traydata; 
    CMenu m_menu;
  3. Add the following code to your OnSysCommand() message handler:
    void CYourDialog::OnSysCommand(UINT nID, LPARAM lParam)
    {
        if(nID==SC_MINIMIZE)
        {
            m_traydata.cbSize=sizeof(NOTIFYICONDATA);
            m_traydata.hWnd =this->m_hWnd;
            m_traydata.uID = 1;
            m_traydata.hIcon=AfxGetApp()->LoadIcon(IDI_YOURICON);
            m_traydata.uCallbackMessage =WM_MY_TRAY;
            strcpy(m_traydata.szTip,"Systray application");
            m_traydata.uFlags=NIF_ICON|NIF_MESSAGE;
            m_menu.DestroyMenu(); // if already exists
            if(!m_menu.LoadMenu(IDR_MENU1)) return;
            Shell_NotifyIcon(NIM_DELETE,&m_traydata); // if already exisits
            If(!Shell_NotifyIcon(NIM_ADD,&m_traydata)) return;
            this->ShowWindow(SW_HIDE);
        }
    }
  4. Define a message as #define WM_MY_TRAY (WM_USER+1) in your header file.
  5. Add a message handler for the message, say OnTrayNotify() as follows:
    • void OnTrayNotify(WPARAM wParam, LPARAM lParam); // in your header file
    • ON_MESSAGE(WM_MY_TRAY,OnTrayNotify) // on your MESSAGE_MAP
    • Following code in your CPP file:
      void CYourDialog::OnTrayNotify(WPARAM wParam, LPARAM lParam)
      {
          UINT uID,uMsg;
          uID=(UINT)wParam;
          uMsg=(UINT)lParam;
          if(uID!=1) return;
          CPoint pt;
          switch(uMsg)
          {
              case WM_LBUTTONDOWN:
              this->ShowWindow(SW_SHOW);
              this->ShowWindow(SW_NORMAL);
              Shell_NotifyIcon(NIM_DELETE,&m_traydata);
              break;
              case WM_RBUTTONDOWN:
              case WM_CONTEXTMENU:
              GetCursorPos(&pt);
              OnTrayRButton(pt);
              break;
          }
          return;
      }
  6. Add a member function called OnTrayRButton(CPoint point):
    void CYourDialog::OnTrayRButton(CPoint point)
    {
        // assuming that the IDR_MENU1 is having atleast one submenu
        m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN| 
        TPM_LEFTBUTTON| TPM_RIGHTBUTTON,point.x,point.y,this);
    }
  7. The OnDestroy method:
    void CYourDialog::OnDestroy() 
    {
        CDialog::OnDestroy();
        Shell_NotifyIcon(NIM_DELETE,&m_traydata);
    }
  8. Thatzaal, you are having your application in systray now.

Popup menu for your application

Method 1:

  • Add a member variable for CMenu (say for e.g.. m_menu);
  • Load menu resource into your menu member m_menu.LoadMenu(IDR_MENU1);
  • Add context menu handler to your application (WM_CONTEXTMENU).
    void CYourDlg:: OnContextMenu(CWnd* pWnd, CPoint point) 
    { 
        m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON,
                                           point.x,point.y,this);
    }

Method 2:

  • Add a member variable for CMenu ( say for e.g.. m_menu);
  • Add context menu handler to your application (WM_CONTEXTMENU).
    void CYourDlg:: OnContextMenu(CWnd* pWnd, CPoint point) 
    { 
        m_menu.DestroyMenu(); // Destroy the old menu if any.
        m_menu.CreatePopupMenu();
        m_menu.AppendMenu(MF_STRING,1000,"item 1");
        m_menu.AppendMenu(MF_SEPARATOR);
        m_menu.AppendMenu(MF_STRING,1001,"item 2");
        m_menu.AppendMenu(MF_STRING,1002,"item 3");
        m_menu.AppendMenu(MF_POPUP,(UINT) m_menu2.m_hMenu,”sub menu”);
        m_menu.TrackPopupMenu(TPM_RIGHTBUTTON,point.x,point.y,this);
    }
  • 1000, 1001, 1002 are the command IDs for the menu items. Use this ID to identify your menu item in wParam of WM_COMMAND message.
  • MF_POPUP is used to attach a submenu to your popup menu. In this case command ID parameter will take a menu handle instead of an ID. Menu handle can be any other menu you have created like m_menu.

About CPtrList class

  • CPtrList is a pointer list class (linked list). It can hold any number of items in the list dynamically.
  • To add an item to the list, call CPtrList::AddTail() / CPtrList:::AddHead() / CPtrList::InsertAfter() / CPtrList::InsertBefore() /CPtrList::SetAt().
  • The items in the CPtrList are void* type. Type cast your objects to void* while adding it to the list.
  • To retrieve an item from the list, use CPtrList::GetHead() / CPtrList::GetTail() / CPtrList::GetAt() / CPtrList:::GetNext() / CPtrList::GetPrev().
  • While retrieving items from the list, type cast the void type to your object type.
  • Use POSITION handle to parse the list. It is not an index. It is the handle that points to your objects in the list.
  • All the elements in your list will be handled with the POSITION handle only.
  • To find an item in the list you can use both the index and the POSITION. CPtrList::FindIndex(index) will return the POSTION value. CPtrList::Find(void *) will return the item.
  • CPtrList::GetNext(POSITION) will return the current object and will increment the position value to the next. POSITION is the reference parameter.
  • To remove an item / all item from the list: CPtrList::RemoveAt() / CPtrList::RemoveAll().
  • Take care while allocating and freeing the memory of your objects while adding and removing it from the list. It is your responsibility to delete the allocated objects. CPtrList won't delete the objects while removing it from the list.

    Example:

    // Adding an object to the list
    // Should be deleted. Caution: Memory Leak
    m_objList.AddTail((void *) new CPoint(2,2)); 
    // Traversing a CPtrList; and assigning value to the objects 
    POSITION pos=m_objList.GetHeadPosition(); 
    while(pos)
    {
       CPoint *obj=(CPoint *)m_objList.GetNext(pos);
       obj->x=10;obj->y=10;
    }
    // Removing the objects from the list
    POSITION pos=m_objList.GetHeadPosition(); 
    while(pos)
    {
       CPoint *obj=(CPoint *)m_objList.GetNext(pos);
       delete obj;
    }
    m_objList.RemoveAll();

About CListCtrl

  • Having gridlines:
    CListCtrl::SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
  • Adding columns:
    CListCtrl::InsertColumn(index,title,alignment,<title length>*25,-1)

    Alignment - LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_CENTER

  • Setting width for columns:
    CListCtrl::SetColumnWidth(index,size);
  • Inserting items into the list:
    CListCtrl::InsertItem(index,””);
    CListCtrl::SetItemText(index,column,item_text);
  • Getting items from the list:
    CString txt=CListCtrl::GetItemText(item,column);
  • Getting selected items from the list:
    POSITION pos=CListCtrl:: GetFirstSelectedItemPosition();
    while(pos)
    {
       int item=CListCtrl::GetNextSelectedItem(pos);
       CString txt=CListCtrl::GetItemText(item,column);
    }
  • Set focus to a row:
    CListCtrl::SetItemState(index,LVIS_FOCUSED,LVIS_FOCUSED);
  • Delete all items in the list:
    CListCtrl::DeleteAllItems();

About Database connection…

  • Opening a database:
    CDatabase db;
    db.OpenEx("DRIVER=Microsoft Access Driver (*.mdb);DBQ=mydatabase.mdb;")
  • Having a recordset for the database:
    CRecordset rs;
    rs.m_pDatabase=&db;
  • Getting values from a recordset:
    rs.GetFieldValue(index,CString&);
  • Getting total number of records:
    rs.GetRecordCount();
  • Parsing full recordset of a database:
    if(rs.GetRecordCount()==0) return; 
    
    rs.MoveFirst();
    
    for(int i=0; i<rs.GetRecordCount(); i++)
    
    {
        CString emp_no,emp_name,;
        rs.GetFieldValue(0,emp_no);
        rs.GetFieldValue(1,emp_name);
        MessageBox(emp_no+” “+emp_name);
        rs.MoveNext(); 
    }

(to be continued...)

Conclusion

I am not telling that these are the full concepts indicated by the titles. But these are the basics. The article may not cover the full area over the concepts. None of the articles can satisfy one's expectations. But, each article should be a seed for your technical growth. Thus, I believe that this would be a seed. Thank you all.

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

Naren Neelamegam
Software Developer
India India
Member
E-Mail : loveablevirus@yahoo.com
Web : http://www.narenn.com

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   
GeneralProblem with closing tray menumemberMember 45806386 Nov '08 - 9:51 
When I click on tray icon and menu shows if i click outside of menu it does not close! How to close it? It Closes only if I click an item in menu
AnswerRe: Problem with closing tray menumemberNaren Neelamegam3 Nov '09 - 18:59 
call SetForegroundWindow() in the function which handles the tray popup menu (OnContextMenu)
 
- Naren

GeneralsamplesmemberSunilkumarmn28 Mar '07 - 22:56 
It would be nice if u add sample working codes for each topic as it is seen in many articles.
 
anyway it is a nice article, congrats.!
Questionnice article but what about win32!!!memberdfgdiewocxn27 Dec '06 - 0:53 
nice article!
 
can u please write a similar article for win32 instead of MFC?
it would be really great!
 
chill-
GeneralProblem With Making Loader :(memberridder21 Sep '06 - 23:18 
Hi i like your tutorial i made the dll Binary File but i Dont Understand How to creat the Loader Can you Explain it More Easily For Dumbas Newbie like me?
GeneralVery NicememberPravinSingh15 May '06 - 21:13 
For a long time I was looking for something like this. It's a very good starting point for the concepts. U get my 5 Smile | :)
 

It's better to know some of the questions than all of the answers.

Pravin.
Generalgood jobmembermousewolf9 Jul '05 - 13:50 
good job
GeneralNice, but...memberGeert van Horrik26 May '05 - 0:40 
Good start, but quote from MSDN:
MSDN:
TerminateThread is a dangerous function. Use it only in the most extreme cases.
 
I think it's better to send the thread a nice WM_QUIT message.
 
But it's just my opinion...
 
Waiting for your next article!
 
Geert
 
Want to spread the newest version of your software automatically? Use Updater!
Visit my website: http://geert.yoki.org
GeneralRe: Nice, but...memberNareen Neelamegam26 May '05 - 0:52 
Thanks Geert...
 
But as an initiative article i think this is enough. I have planned to prepare detailed articles on individual topics, at that time, i will give +ves and -ves of each thing.
 
Even you can note in the above code for dll, GetProcessAddress returns a function address, but not checked whether it is a valid address or not.
 
I remind, this is an initiative article.
 
Anyhow, thanks for your suggestion.Smile | :)
 

 
with regards
Nareen Neelamegam
GeneralRe: Nice, but...memberThatsAlok26 May '05 - 18:07 
Geert van Horrik wrote:
I think it's better to send the thread a nice WM_QUIT message.
 
Little Correction, there us no message Loop in Worker Thread, so it willnot listen the WM_QUIT message!
 
It's Possible with UI Thread Only!
 

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow

cheers,
Alok Gupta
GeneralGr8 JobmemberNMos26 May '05 - 0:13 
Done a good job. Got my 5 Cool | :cool:
 
Keep it up

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 26 May 2005
Article Copyright 2005 by Naren Neelamegam
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid