首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder 6 / Delphi 7 完美整合 CHM 說明檔:上下文敏感與 API 封裝

     編輯:關於C++

C++Builder 6 / Delphi 7 的 VCL 僅原生支援舊式 WinHelp(.hlp),面對功能更強、格式更現代的 HTML Help(.chm)無能為力。本文詳細記錄從 CHM 製作、別名/對應表建立、hhctrl.ocx 靜態庫導入、WM_HELP 訊息攔截、彈出選單特殊處理到完整程式碼整合的全流程,實現控制項層級的上下文敏感說明。

一、CHM 製作與上下文敏感配置

  1. 使用 Microsoft HTML Help Workshop 製作 CHM,主題檔(如 1001.htm...)對應主題 ID。
  2. 建立標頭檔 helpids.h 定義符號常數:
    #define IDH_TOPIC1 1001
    #define IDH_TOPIC2 1002
    #define IDH_TOPIC3 1003
    #define IDH_TOPIC4 1004
  3. 在專案中 Include 該 .h,於 Alias 頁面建立別名(如 IDH_TOPIC1=1001.htm),於 Map 頁面匯入 .h 產生對應表。
  4. 編譯 CHM,用 Workshop 測試 API:HH_HELP_CONTEXT + Map Number 驗證跳轉正確。

二、VCL 訊息機制分析

VCL 在三種情況發送 WM_HELP:

  1. 主選單/選單項按 F1
  2. 視窗控制項按 F1
  3. 彈出選單(TPopupMenu)按 F1 —— 此訊息由隱藏視窗 PopupList->Window 統一分派

前兩類易於在表單 Message Map 攔截;第三類需在執行期 子類別化 PopupList->Window 的視窗程序。

三、核心程式碼實作

1. 表單標頭檔 MainFormUnit.h

class TMainForm : public TForm {
__published: // IDE 元件...
private:
public:
    __fastcall TMainForm(TComponent* Owner);
protected:
    // 取消內聯優化避免警告
    #pragma option push -vi-
    BEGIN_MESSAGE_MAP
        VCL_MESSAGE_HANDLER(WM_HELP, Messages::TMessage, MyHelp)
    END_MESSAGE_MAP(TForm)
    #pragma option pop
    void __fastcall MyHelp(Messages::TMessage &Message);
};

2. 表單實作檔 MainFormUnit.cpp

#include <htmlhelp.h> // 需先 implib hhctrl.lib hhctrl.ocx 並加入專案
static FARPROC OldMenuProc = NULL;

// 新視窗程序:處理 PopupMenu 的 WM_HELP
static long CALLBACK NewMenuProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    if (uMsg != WM_HELP) return CallWindowProc(OldMenuProc, hwnd, uMsg, wParam, lParam);

    HELPINFO* phi = (HELPINFO*)lParam;
    for (int n=0; nCount; ++n) {
        TMenu* popMenu = (TMenu*)PopupList->Items[n];
        TMenuItem* item = (phi->hItemHandle == popMenu->Handle) ?
            popMenu->Items :
            ((TPopupMenu*)popMenu)->FindItem((int)phi->hItemHandle, fkHandle);
        if (item) {
            int ctx = popMenu->GetHelpContext(phi->iCtrlId, true);
            if (!ctx) ctx = popMenu->GetHelpContext((int)phi->hItemHandle, false);
            if (!ctx && Screen->ActiveForm) ctx = Screen->ActiveForm->HelpContext;

            HtmlHelp(hwnd, Application->HelpFile.c_str(),
                     ctx ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, ctx);
            break;
        }
    }
    return TRUE;
}

// 表單建立:子類別化 PopupList->Window
void __fastcall TMainForm::FormCreate(TObject *Sender) {
    OldMenuProc = (FARPROC)SetWindowLong(PopupList->Window, GWL_WNDPROC, (long)NewMenuProc);
}

// 表單關閉:還原視窗程序
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) {
    SetWindowLong(PopupList->Window, GWL_WNDPROC, (long)OldMenuProc);
}

// 通用 WM_HELP 處理:主選單、一般控制項
void __fastcall TMainForm::MyHelp(Messages::TMessage &Message) {
    HELPINFO* HI = (HELPINFO*)Message.LParam;
    if (HI->iContextType == HELPINFO_MENUITEM) { // 主選單
        TMenuItem* mi = NULL;
        for (int i=0; iFindItem(HI->iCtrlId, fkCommand))) break;
        }
        HtmlHelp(Handle, Application->HelpFile.c_str(),
                 mi && mi->HelpContext ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC,
                 mi ? mi->HelpContext : 0);
    } else { // 一般控制項
        TWinControl* wc = FindControl(HI->hItemHandle);
        HtmlHelp(Handle, Application->HelpFile.c_str(),
                 wc && wc->HelpContext ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC,
                 wc ? wc->HelpContext : 0);
    }
}

// 工具列/選單項直接呼叫說明
void __fastcall TMainForm::ActionHelpExecute(TObject *Sender) {
    HtmlHelp(Handle, Application->HelpFile.c_str(), HH_DISPLAY_TOPIC, 0);
}

四、關鍵技術點總結

五、常見坑位與對策

  • CHM 無法開啟:確認 hhctrl.ocx 版本 ≥ 4.74(Win98+ 內建),或隨安裝包部署。
  • Map Number 不生效:檢查 .h 是否正確 #include 於專案、Alias/Map 是否重新編譯。
  • PopupMenu 不觸發:PopupList 需包含 Menus.hpp,且 SetWindowLong 必須在 FormCreate 執行,FormClose 必須還原,否則程式結束崩潰。
  • 64 位元相容:SetWindowLongPtr/GetWindowLongPtr 替代 SetWindowLong,LONG_PTR 替代 long。

六、總結

透過 HtmlHelp API、訊息攔截與 PopupList 子類別化,C++Builder 6 / Delphi 7 可零成本升級至現代 CHM 說明系統,完整支援控制項、選單、彈出選單的上下文敏感說明。完整範例專案已整理,可直接遷移至維護中的舊專案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
環節做法
API 導入implib hhctrl.lib hhctrl.ocx → 專案加入 hhctrl.lib,包含 htmlhelp.h
HelpFile 設定Application->HelpFile = "MyApp.chm"(專案選項或執行期指定)
控制項 HelpContext物件檢視器設定對應 Map Number(如 1001)
主選單/控制項表單 WM_HELP 處理器 MyHelp 統一分派
彈出選單FormCreate 子類別化 PopupList->Window,FormClose 還原
訊息參數HELPINFO.iContextType 區分選單/控制項;iCtrlId/hItemHandle 定位項目