65.9K
CodeProject 正在变化。 阅读更多。
Home

入门指南

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.49/5 (26投票s)

2005年5月26日

4分钟阅读

viewsIcon

77861

了解简单的 DLL、多线程以及其他一些内容……

引言

动态链接库、多线程……这些概念对于初学者来说都有些高深。但正如“简单”二字所言,它们在概念上是简单的。本文旨在为你提供关于这些概念的一些有用的技术基础知识,特别是为初学者准备。本文不涉及概念的理论定义。

创建一个简单的 DLL

DLL 部分

  • 在 Win32 动态链接库上创建一个空项目。
  • 在工作区创建一个新的 CPP 文件。(在工作区的“文件视图”选项卡中,右键单击“源文件”->“添加文件到文件夹…”然后创建一个新的 CPP 文件)。
  • 按以下方式编写你的代码……
    #include <afxwin.h>
    extern "C" _declspec(dllexport) void SayHello()
    {
        AfxMessageBox(“Hello World”);
    }

DLL 代码就这些了……编译它,然后得到你的 DLL。

应用程序部分

  • 创建一个应用程序向导(对话框或 SDI 或 MDI……随意选择)。
  • 使用任何消息处理程序来测试这个 DLL……例如,一个按钮处理程序。
  • 使用以下代码加载你的 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
    }
  • 将你的 DLL 放在应用程序的路径中……
  • 现在编译你的应用程序……

技巧

  • 这是上述应用程序中一个简单的单行代码。如果 DLL 或函数不存在,可能会导致问题……
    GetProcessAddress(LoadLibrary(“yourDLLName.dll”),”SayHello”)();
  • GetProcessAddress() 将返回你 DLL 中函数的地址。第二个参数是你正在查找的确切函数名,所以请确保函数名拼写正确。

简单的多线程概念

  1. 创建一个结构用于你的线程和应用程序之间的数据传输。例如
    struct threadinfo{ 
        CString somedata; 
    } info;
  2. 声明一个 `CWinThread` 类型的指针成员变量(对象)。这里是 `CWinThread *m_pthread`。
  3. 在你的应用程序中的任何地方初始化你的线程,如下所示
    m_pthread=AfxBeginThread(functionname,(LPVOID) &info);

    AfxBeginThread() API 接受两个参数,函数名(将是你的线程)和必要的信息,例如 `threadinfo` 结构。

  4. 将你的线程函数编写为
    UINT functionname(LPVOID param)
    {
        threadinfo *info=(threadinfo *)param;
        CString s=info->somedata;
        // handle your thread code here…
    }
  5. 终止线程
    ::TerminateThread(m_pthread->m_hThread,0);

将你的应用程序最小化到系统托盘

  1. 使用任何向导创建你的应用程序(SDI、MDI 或对话框)。
  2. 添加 `NOTIFYICONDATA` 和 `CMenu` 的成员变量。

    例如

    NOTIFYICONDATA m_traydata; 
    CMenu m_menu;
  3. 将以下代码添加到你的 `OnSysCommand()` 消息处理程序中
    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 WM_MY_TRAY (WM_USER+1)`。
  5. 为该消息添加一个消息处理程序,例如 `OnTrayNotify()`,如下所示
    • void OnTrayNotify(WPARAM wParam, LPARAM lParam); // 在你的头文件中
    • ON_MESSAGE(WM_MY_TRAY,OnTrayNotify) // 在你的 `MESSAGE_MAP` 中
    • 在你的 CPP 文件中的以下代码
      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. 添加一个名为 `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. OnDestroy 方法
    void CYourDialog::OnDestroy() 
    {
        CDialog::OnDestroy();
        Shell_NotifyIcon(NIM_DELETE,&m_traydata);
    }
  8. 好了,你的应用程序现在就在系统托盘里了。

应用程序的弹出菜单

方法 1

  • 为 `CMenu` 添加一个成员变量(例如 `m_menu`);
  • 将菜单资源加载到你的菜单成员 `m_menu.LoadMenu(IDR_MENU1);` 中
  • 为你的应用程序添加上下文菜单处理程序(`WM_CONTEXTMENU`)。
    void CYourDlg:: OnContextMenu(CWnd* pWnd, CPoint point) 
    { 
        m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTBUTTON,
                                           point.x,point.y,this);
    }

方法 2

  • 为 `CMenu` 添加一个成员变量(例如 `m_menu`);
  • 为你的应用程序添加上下文菜单处理程序(`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 是菜单项的命令 ID。使用此 ID 在 `WM_COMMAND` 消息的 `wParam` 中识别你的菜单项。
  • `MF_POPUP` 用于将子菜单附加到你的弹出菜单。在这种情况下,命令 ID 参数将接受一个菜单句柄而不是 ID。菜单句柄可以是任何你创建的其他菜单,例如 `m_menu`。

关于 CPtrList 类

  • CPtrList 是一个指针列表类(链表)。它可以动态地存储任意数量的项目。
  • 要向列表中添加项目,请调用 `CPtrList::AddTail()` / `CPtrList:::AddHead()` / `CPtrList::InsertAfter()` / `CPtrList::InsertBefore()` /CPtrList::SetAt()
  • CPtrList 中的项目是 void* 类型。在将对象添加到列表时,将其类型转换为 void*
  • 要从列表中检索项目,请使用 `CPtrList::GetHead()` / `CPtrList::GetTail()` / `CPtrList::GetAt()` / `CPtrList:::GetNext()` / `CPtrList::GetPrev()`。
  • 从列表中检索项目时,将 void 类型转换为你的对象类型。
  • 使用 `POSITION` 句柄来遍历列表。它不是索引。它是一个指向列表中对象的句柄。
  • 你列表中的所有元素都将仅通过 `POSITION` 句柄进行处理。
  • 要查找列表中的项目,你可以同时使用索引和 `POSITION`。`CPtrList::FindIndex(index)` 将返回 `POSTION` 值。`CPtrList::Find(void *)` 将返回项目。
  • CPtrList::GetNext(POSITION) 将返回当前对象并将位置值递增到下一个。`POSITION` 是引用参数。
  • 要从列表中删除项目/所有项目:`CPtrList::RemoveAt()` / `CPtrList::RemoveAll()`。
  • 在添加和删除对象时,要注意分配和释放对象的内存。你有责任删除分配的对象。`CPtrList` 在从列表中删除对象时不会删除它们。

    示例

    // 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();

关于 CListCtrl

  • 显示网格线
    CListCtrl::SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
  • 添加列
    CListCtrl::InsertColumn(index,title,alignment,<title length>*25,-1)

    对齐方式 - `LVCFMT_LEFT`、`LVCFMT_RIGHT`、`LVCFMT_CENTER`

  • 设置列的宽度
    CListCtrl::SetColumnWidth(index,size);
  • 向列表中插入项目
    CListCtrl::InsertItem(index,””);
    CListCtrl::SetItemText(index,column,item_text);
  • 从列表中获取项目
    CString txt=CListCtrl::GetItemText(item,column);
  • 获取列表中的选定项目
    POSITION pos=CListCtrl:: GetFirstSelectedItemPosition();
    while(pos)
    {
       int item=CListCtrl::GetNextSelectedItem(pos);
       CString txt=CListCtrl::GetItemText(item,column);
    }
  • 将焦点设置到某一行
    CListCtrl::SetItemState(index,LVIS_FOCUSED,LVIS_FOCUSED);
  • 删除列表中的所有项目
    CListCtrl::DeleteAllItems();

关于数据库连接……

  • 打开数据库
    CDatabase db;
    db.OpenEx("DRIVER=Microsoft Access Driver (*.mdb);DBQ=mydatabase.mdb;")
  • 为数据库创建记录集
    CRecordset rs;
    rs.m_pDatabase=&db;
  • 从记录集中获取值
    rs.GetFieldValue(index,CString&);
  • 获取记录总数
    rs.GetRecordCount();
  • 遍历数据库的完整记录集
    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(); 
    }

(待续……)

结论

我并不是说这些是标题所包含的全部概念。但这些是基础。本文可能无法涵盖这些概念的全部领域。没有哪篇文章能完全满足所有人的期望。但是,每篇文章都应该成为你技术成长的一颗种子。因此,我相信这会是一颗种子。谢谢大家。

© . All rights reserved.