点击下载范例代码 

很久以前就有个朋友问过,怎么实现 Outlook Express 的工具条。
当时因为理解错了,仅仅写了个 Outlook 2000 插件的范例,以为能够满足他。
后来又因为时间比较忙,事情就不了了之了(惭愧)。
最近又有个朋友要做这玩意(这玩意很吃香吗?),虽然最近一直很忙,不过还是抽空写了个范例,效果很不错。
希望这个工程对其他要做这方面开发的朋友有所帮助。

其实,Outlook Express 并不能像 Office 系列软件那样能支持插件。
所以我们只能通过一些非正常手段来实现,比如 HOOK,或者远程注入等。
个人觉得 HOOK 还是要比远程注入要安全,也稳定得多(当然也容易掌握得多,汗一个)!
我因为要进入 Outlook Express 的进程空间,所以 HOOK 必须是全局的,也就是说必须以 DLL 形式加载(这样有一个不方便的地方就是必须要有一个程序来先加载这个 DLL ,并将 HOOK 挂入系统)。

恩,现在就先来讲一下实现方法:
1、在系统中挂入 WH_SHELL 钩子,这个钩子会在顶级窗口(进程主窗口)创建、注销等事件时收到消息,这是个好机会,我们要的就是窗口创建时判断窗口是否 Outlook Express 主窗口。
LRESULT CALLBACK shellProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    switch(nCode)
    {
    case HSHELL_WINDOWCREATED:
        if(isOutlookExpress((HWND)wParam))  // 如果是 Outlook Express 窗口
        {
            // 处理
        }
        break;
        default:break;
    }
    return CallNextHookEx(hHook,nCode,wParam,lParam);
}

2、如果是的,则遍历 Outlook Express 的子窗口,找到 ReBar 窗口句柄(其实微软叫他:ReBarWindow32,简称 ReBar 好了,ReBar 其实是一个容器,可以包容工具条、ComboBox 等各种控件)。得到这个句柄之后,我们就可以将我们创建的工具条插入 ReBar 中。
HWND WINAPI findCoolbar(HWND hwnd)
{
    HWND hWnd = NULL;
    EnumChildWindows(hwnd,enumChildProc,(LPARAM)&hWnd);
    return hWnd;
}

BOOL CALLBACK enumChildProc(HWND hwnd,LPARAM lParam)
{
    TCHAR szClass[MAX_PATH] = TEXT("");
    GetClassName(hwnd,szClass,MAX_PATH);
    if(lstrcmpi(szClass,TEXT("ReBarWindow32")) == 0)
    {
        *((HWND*)lParam) = hwnd;
        return FALSE;
    }
    return TRUE;
}

3、现在问题来了,我们怎么响应我们插入的工具条的消息呢?其实简单,只要在 HOOK 过程中(本例中为 shellProc)重置 Outlook Express 的主窗口过程就 OK 了:)
    .
    hWndOE = (HWND)wParam;  // 保存窗口句柄
    if(insertToolbar(hWndOE))lpfnOldOEWindowProc = (WNDPROC)SetWindowLong(hWndOE,GWL_WNDPROC,(LONG)newOEWindowProc);     // 插入工具条成功之后,重置窗口过程
    .

4、在新的窗口过程中接收 WM_COMMAND 消息:
LRESULT CALLBACK newOEWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDC_SAMPLE:
            MessageBox(hWnd,TEXT("呵呵,你点我干嘛?"),NULL,MB_OK | MB_ICONINFORMATION);
            break;
        default:break;
        }
        break;
    .
    // 其他处理

好了,这样就基本完成了 Outlook Express 工具条。
当然还有其他一些细节要处理,比如工具条的创建、退出 Outlook Express、中途退出 HOOK 等情况。
不多说了吧,具体看范例代码(VC6 的工程)。