點擊下載范例代碼 

很久以前就有個朋友問過,怎么實現 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 的工程)。