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:
Thatzaal all with the DLL code� Build it and get your DLL.
Application part:
Tips:
Simple multithreading concept
- Create a structure for data transaction between your thread and application. Say for example:
struct threadinfo{
CString somedata;
} info;
- Declare a pointer member variable (object) of type
CWinThread
. Here, CWinThread *m_pthread
.
- 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.
- Write your thread function as:
UINT functionname(LPVOID param)
{
threadinfo *info=(threadinfo *)param;
CString s=info->somedata;
}
- To terminate the thread:
::TerminateThread(m_pthread->m_hThread,0);
Minimizing your application to System tray
- Create your application in any wizard as your wish (SDI, MDI or dialog).
- Add a member variable for
NOTIFYICONDATA
and CMenu
.
Say for example:
NOTIFYICONDATA m_traydata;
CMenu m_menu;
- 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(!m_menu.LoadMenu(IDR_MENU1)) return;
Shell_NotifyIcon(NIM_DELETE,&m_traydata);
If(!Shell_NotifyIcon(NIM_ADD,&m_traydata)) return;
this->ShowWindow(SW_HIDE);
}
}
- Define a message as
#define WM_MY_TRAY (WM_USER+1)
in your header file.
- 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;
}
- Add a member function called
OnTrayRButton(CPoint point)
: void CYourDialog::OnTrayRButton(CPoint point)
{
m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN|
TPM_LEFTBUTTON| TPM_RIGHTBUTTON,point.x,point.y,this);
}
- The
OnDestroy
method: void CYourDialog::OnDestroy()
{
CDialog::OnDestroy();
Shell_NotifyIcon(NIM_DELETE,&m_traydata);
}
- 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();
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:
m_objList.AddTail((void *) new CPoint(2,2));
POSITION pos=m_objList.GetHeadPosition();
while(pos)
{
CPoint *obj=(CPoint *)m_objList.GetNext(pos);
obj->x=10;obj->y=10;
}
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.