1, 用Win32 Dynamic-link library创建动态链接库工程HOOKDLL(注:选择empty dll工程)
2, 在Source Files中添加dll.cpp文件
3, 在Head Files中添加dll.h文件
4, 编译,链接, 生成HOOKDLL.dll, HOOKDLL.lib
//------------------------------------上面是动态链接库内容,下面的是调用dll的程序----------
5, 选择MFC AppWizard后, 创建基于对话框的应用程序HOOK
6, 在HOOK的资源对话框的模板上添加 1 个文本框(IDC_EDIT1), 2 个按钮(IDC_BUTTON1)和(IDC_BUTTON2)
7, 在HOOKDlg.cpp中, 添加头文件#include "dll.h"
8, 将上述第四步所生成的HOOKDLL.dll,HOOKDLL.lib 和文件dll.h拷贝到工程HOOK的目录中
9, 添加两个按钮的单击消息,然后,在IDC_BUTTON1的消息响应下,添加代码。在IDC_BUTTON2的的消息响应下添加代码。
10,编译(顺利通过),链接(出错)
//2步骤
//dll.cpp文件如下
#include <windows.h>
#include "dll.h"
#pragma data_seg("Shared")
HHOOK mhook=NULL;
HINSTANCE hInstance=NULL;
#pragma data_seg()
//#pragma comment(linker,"/section:Shared,rws")LRESULT WINAPI KeyProc(int code,WPARAM wParam,LPARAM lParam)
{

if(code == HC_ACTION && (lParam & 0xc000ffff) == 1)
{
char *sName;
BOOL b_Sft = ::GetAsyncKeyState(VK_SHIFT) >> ((sizeof(short) * 8)-1);
if(b_Sft)
{
switch(wParam)
{
case '1':sName = "!";break;
case '2':sName = "@";break;
case '3':sName = "#";break;
case '4':sName = "$";break;
case '5':sName = "%";break;
case '6':sName = "^";break;
case '7':sName = "&";break;
case '8':sName = "*";break;
case '9':sName = "(";break;
case '0':sName = ")";break;
case 'A':sName = "A";break;
    case 'B':sName = "B";break;
    case 'C':sName = "C";break;
    case 'D':sName = "D";break;
    case 'E':sName = "E";break;
    case 'F':sName = "F";break;
    case 'G':sName = "G";break;
    case 'H':sName = "H";break;
    case 'I':sName = "I";break;
    case 'J':sName = "J";break;
    case 'K':sName = "K";break;
    case 'L':sName = "L";break;
    case 'M':sName = "M";break;
    case 'N':sName = "N";break;
    case 'O':sName = "O";break;
    case 'P':sName = "P";break;
    case 'Q':sName = "Q";break;
    case 'R':sName = "R";break;
    case 'S':sName = "S";break;
    case 'T':sName = "T";break;
    case 'U':sName = "U";break;
    case 'V':sName = "V";break;
    case 'W':sName = "W";break;
    case 'X':sName = "X";break;
    case 'Y':sName = "Y";break;
    case 'Z':sName = "Z";break; }
}
else
{
switch(wParam)
{
// 0~9
    case '1':sName = "1";break;
    case '2':sName = "2";break;
    case '3':sName = "3";break;
    case '4':sName = "4";break;
    case '5':sName = "5";break;
    case '6':sName = "6";break;
    case '7':sName = "7";break;
    case '8':sName = "8";break;
    case '9':sName = "9";break;
    case '0':sName = "0";break;// A~Z
    case 'A':sName = "a";break;
    case 'B':sName = "b";break;
    case 'C':sName = "c";break;
    case 'D':sName = "d";break;
    case 'E':sName = "e";break;
    case 'F':sName = "f";break;
    case 'G':sName = "g";break;
    case 'H':sName = "h";break;
      case 'I':sName = "i";break;
     case 'J':sName = "j";break;
     case 'K':sName = "k";break;
    case 'L':sName = "l";break;
    case 'M':sName = "m";break;
    case 'N':sName = "n";break;
    case 'O':sName = "o";break;
    case 'P':sName = "p";break;
    case 'Q':sName = "q";break;
    case 'R':sName = "r";break;
    case 'S':sName = "s";break;
    case 'T':sName = "t";break;
    case 'U':sName = "u";break;
    case 'V':sName = "v";break;
    case 'W':sName = "w";break;
    case 'X':sName = "x";break;
    case 'Y':sName = "y";break;
    case 'Z':sName = "z";break;
}
}
//数字键 switch(wParam)
{
  case VK_BACK:sName = "~";break; case VK_NUMPAD1:sName = "1";break;
case VK_NUMPAD2:sName = "2";break;
case VK_NUMPAD3:sName = "3";break;
case VK_NUMPAD4:sName = "4";break;
case VK_NUMPAD5:sName = "5";break;
case VK_NUMPAD6:sName = "6";break;
        case VK_NUMPAD7:sName = "7";break;
case VK_NUMPAD8:sName = "8";break;
case VK_NUMPAD9:sName = "9";break;
case VK_NUMPAD0:sName = "0";break;
        case VK_MULTIPLY:sName = "*";break;
case VK_ADD:     sName = "+";break;
case VK_SUBTRACT:sName = "-";break;
case VK_DECIMAL: sName = ".";break;
case VK_DIVIDE: sName = "/";break;
} HWND H_wnd = ::GetForegroundWindow();
MessageBox(H_wnd,sName,"键盘",MB_OK);
} return FALSE;
}
BOOL APIENTRY DllMain(HANDLE hModule,
  DWORD ul_reason_for_call,
  LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hInstance=(HINSTANCE)hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) BOOL WINAPI Start()
{
if(mhook!=NULL)
return FALSE;
mhook=::SetWindowsHookEx(WH_KEYBOARD,KeyProc,hInstance,0);
return mhook!=NULL;
}
extern "C" __declspec(dllexport) void WINAPI Stop()
{
::UnhookWindowsHookEx(mhook);
}第三步骤
//dll.h文件如下
extern "C" __declspec(dllexport) BOOL WINAPI Start();
extern "C" __declspec(dllexport) void WINAPI Stop();第九步骤
void CHOODDlg::OnButton1() 
{
Start();
}void CHOODDlg::OnButton2() 
{
Stop();
}第十步骤(错误信息如下)
--------------------Configuration: HOOD - Win32 Debug--------------------
Linking...
HOODDlg.obj : error LNK2001: unresolved external symbol _Start@0
HOODDlg.obj : error LNK2001: unresolved external symbol _Stop@0
Debug/HOOD.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.HOOD.exe - 3 error(s), 0 warning(s)//如果注释掉OnButton1() OnButton2() 函数体中的内容,则编译链接通过, 显然按钮在访问dll库中的函数时候,出问  
//题, 但我又不知道如何改动才能顺利通过, 有请高手指点, 谢谢void CHOODDlg::OnButton1() 
{
// Start();
}void CHOODDlg::OnButton2() 
{
// Stop();
}

解决方案 »

  1.   

    你想用包含头文件的方法调用dll中的函数, 必须要把生成dll时生成lib文件也导入到你的工程中. 否则就应该用LoadLibrary和函数指针的方法动态调用.
    因为你的头文件中只有函数的声明, 而没有实现. 你只包含了头文件, 而没有加载dll. 所以编译找不到这两个函数的实现, 就会报这个错误了!
      

  2.   

    //非常感谢你的指点, 而且也指出了问题的所在, 请问:可以把“第 1 点的方法”写出来吗(该删的删,该
    //添的添)? 因为我对dll确实不怎么地
      

  3.   


    //请问: 怎样把"生成dll时,生成的lib文件导入到我的工程" ????????
    //另外: 如果采用LoadLibrary和函数指针的方法动态调用, 我又该如何做???
      

  4.   

    1. //请问: 怎样把"生成dll时,生成的lib文件导入到我的工程" ????????
    2. //另外: 如果采用LoadLibrary和函数指针的方法动态调用, 我又该如何做???第一个问题可以有两种方式, 一, #import comment(lib, "dll.lib"); 二, 就是工程的属性中Link选项的Input项中加上dll.lib就可以了.第二个问题:    typedef BOOL (*StartFunType)();
        
        StartFunType stratFun;
        HINSTANCE hIns = ::LoadLibrary("HOOKDLL.dll");
        stratFun = (StartFunType)::GetProcAddress(hIns, "Start");
        startFun();
       
        ::FreeLibrary(hIns);
    这是调用Start函数的方法, Stop也一样.这是调用dll很基础的方法, 建议你找一本<<Windows 程序设计>>这样的书look look.
      

  5.   

    修改一下头文件//请在HOOKDLL工程设置,预编译选项中加入_BUILD_HOOK#ifdef _BUILD_HOOK
    #define HOOK_API __declspec(dllexport)
    #else
    #define HOOK_API
    #pragma comment(lib,"HOOKDLL.lib")
    #endif
    //dll.h文件如下
    extern "C" HOOK_API BOOL Start();
    extern "C" HOOK_API void Stop();
    你再试试看
      

  6.   

    请问, 你使用的是VC6.0吗?
    我的在VC6.0的link下有://---------------------------------------------
    Y分类: Input (下拉列表的一项)M对象/库模块
    (文本框)I忽略库:          A忽略全部默认库
    (文本框)F强制符号说明
    (文本框)D附加库路径
    (文本框)Project option
    ..........
    //---------------------------------------------------------------//请问你所说的:“加上dll.lib就可以了”
    //是在那一个下面? 怎么加上? 是直接在某个文本框内填写上 dll.lib 就OK
    //了吗???