Skip to content

Latest commit

 

History

History
292 lines (235 loc) · 9.24 KB

File metadata and controls

292 lines (235 loc) · 9.24 KB

DIME 反查字根紀錄功能 - 程式碼修改指南

本指南整理了「點擊反查視窗紀錄字根」功能的完整程式碼修改,方便您在版本更新時重新套用。

1. 基礎定義 (BaseStructure.h)

目標: 新增一個通知類型,用來區分「反查視窗」與其他通知。

在此檔案中找到 enum class NOTIFY_TYPE,加入 NOTIFY_REVERSE_CONVERSION

// g:\App\DIME\BaseStructure.h

enum class NOTIFY_TYPE
{
    NOTIFY_CHN_ENG = 0,
    NOTIFY_SINGLEDOUBLEBYTE,
    NOTIFY_BEEP,
    NOTIFY_OTHERS,
    NOTIFY_REVERSE_CONVERSION // [新增]
};

2. 通知視窗標頭檔 (NotifyWindow.h)

目標:

  1. 讓視窗能儲存「被反查的字」(SourceText)。
  2. 新增設定這個字的方法。
// g:\App\DIME\NotifyWindow.h

class CNotifyWindow : public CBaseWindow
{
public:
    // ... 原有程式碼 ...
    void SetNotifyType(enum NOTIFY_TYPE notifytype) { _notifyType = notifytype;}
    NOTIFY_TYPE GetNotifyType() { return _notifyType;}
    
    // [新增] 宣告設定來源文字的方法
    void SetSourceText(_Inout_ const CStringRange *pSourceText); 

private:
   // ... 原有程式碼 ...
   CStringRange _notifyText;
   
   // [新增] 儲存來源文字 (例如: "我")
   CStringRange _sourceText; 

   NOTIFY_TYPE _notifyType;
   // ...
};

3. 通知視窗實作 (NotifyWindow.cpp)

目標:

  1. 加入必要的標頭檔 (處理檔案路徑)。
  2. 實作 SetSourceText
  3. 修改 _OnLButtonDown 處理點擊與寫入檔案。
  4. 修正 _WindowProcCallback 防止重複觸發。

3.1 加入 Include

在檔案最上方加入:

// g:\App\DIME\NotifyWindow.cpp

#include "NotifyWindow.h"
// [新增] 以下 include
#include <memory> 
#include <vector>
#include <string>
#include <shlobj.h>
#include <shlwapi.h>
#include <KnownFolders.h>
#pragma comment(lib, "shlwapi.lib")

3.2 修正重複觸發 (重要 bug fix)

找到 _WindowProcCallback 中的 WM_SETCURSOR 區塊,修改如下:

// g:\App\DIME\NotifyWindow.cpp -> _WindowProcCallback

    case WM_SETCURSOR:
        {
            POINT cursorPoint;
            GetCursorPos(&cursorPoint);
            MapWindowPoints(NULL, wndHandle, &cursorPoint, 1);

            // [修改] 只在 MOUSEMOVE 時處理,避免重複觸發點擊事件
            if (HIWORD(lParam) == WM_MOUSEMOVE)
            {
                _HandleMouseMsg(HIWORD(lParam), cursorPoint);
            }
        }
        return 1;

3.3 實作 SetSourceText 與 點擊紀錄邏輯

在任意位置 (建議在 _OnLButtonDown 上方) 加入 SetSourceText 實作,並修改 _OnLButtonDown

// g:\App\DIME\NotifyWindow.cpp

// [新增] 實作 SetSourceText
void CNotifyWindow::SetSourceText(_Inout_ const CStringRange *pSourceText)
{
    debugPrint(L"CNotifyWindow::SetSourceText()");
    if (pSourceText == nullptr) return;

    size_t sourceTextLen = pSourceText->GetLength();
    if (sourceTextLen)
    {
        std::unique_ptr<WCHAR[]> pwchString = std::make_unique<WCHAR[]>(sourceTextLen + 1);
        StringCchCopyN(pwchString.get(), sourceTextLen + 1, pSourceText->Get(), sourceTextLen);
        _sourceText.Set(pwchString.release(), sourceTextLen); 
        debugPrint(L"CNotifyWindow::SetSourceText(), sourceTextLen =%d", sourceTextLen);
    }
}

// [修改] _OnLButtonDown 加入寫檔邏輯
void CNotifyWindow::_OnLButtonDown(POINT pt)
{
    RECT rcWindow = {0, 0, 0, 0};
    _GetClientRect(&rcWindow);

    if(PtInRect(&rcWindow, pt))
    {
        if(_notifyType == NOTIFY_TYPE::NOTIFY_CHN_ENG)
        {
            _pfnCallback(_pObj, NOTIFY_WND::SWITCH_CHN_ENG, NULL, NULL);
        }
        // [新增] 處理反查視窗點擊
        else if (_notifyType == NOTIFY_TYPE::NOTIFY_REVERSE_CONVERSION) 
        {
            PWSTR pProfilePath = nullptr;
            // 取得 "我的文件" 路徑
            if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &pProfilePath)))
            {
                WCHAR szPath[MAX_PATH];
                StringCchPrintf(szPath, MAX_PATH, L"%s\\DIME\\reversed_roots.txt", pProfilePath);
                CoTaskMemFree(pProfilePath);

                // 建立目錄
                WCHAR szDir[MAX_PATH];
                StringCchCopy(szDir, MAX_PATH, szPath);
                PathRemoveFileSpec(szDir);
                CreateDirectory(szDir, NULL);

                std::vector<std::wstring> lines;
                BOOL found = FALSE;
                
                // 讀取舊檔
                FILE* fp = nullptr;
                if (_wfopen_s(&fp, szPath, L"r, ccs=UTF-8") == 0 && fp)
                {
                    WCHAR line[1024];
                    while (fgetws(line, 1024, fp))
                    {
                        std::wstring strLine(line);
                        if (!strLine.empty() && strLine.back() == L'\n') strLine.pop_back();

                        if (!found)
                        {
                            // 搜尋: [字] [字根]
                            std::wstring searchKey;
                            searchKey.assign(_sourceText.Get(), _sourceText.GetLength());
                            searchKey += L" ";
                            searchKey.append(_notifyText.Get(), _notifyText.GetLength());
                            
                            if (strLine.find(searchKey) == 0) 
                            {
                                found = TRUE;
                                // 更新計數
                                size_t lastSpace = strLine.find_last_of(L' ');
                                if (lastSpace != std::wstring::npos)
                                {
                                    int count = _wtoi(strLine.substr(lastSpace + 1).c_str());
                                    count++; 
                                    wchar_t countStr[16];
                                    _itow_s(count, countStr, 10);
                                    strLine = searchKey + L" " + countStr;
                                }
                            }
                        }
                        lines.push_back(strLine);
                    }
                    fclose(fp);
                }

                // 若沒找到則新增
                if (!found)
                {
                    std::wstring newLine;
                    newLine.assign(_sourceText.Get(), _sourceText.GetLength());
                    newLine += L" ";
                    newLine.append(_notifyText.Get(), _notifyText.GetLength());
                    newLine += L" 1"; // 初始計數 1
                    lines.push_back(newLine);
                }

                // 寫回檔案
                if (_wfopen_s(&fp, szPath, L"w, ccs=UTF-8") == 0 && fp)
                {
                    for (const auto& l : lines)
                    {
                        fputws(l.c_str(), fp);
                        fputws(L"\n", fp);
                    }
                    fclose(fp);
                }
            }
            // 點擊後隱藏視窗
            _Show(FALSE, 0, 0); 
        }
    }
    else
    {   
        _Show(FALSE,0,0);
    }
}

4. UI管理器 (UIPresenter)

目標: 修改 ShowNotifyText 函式,讓它能往下傳遞「來源文字」。

4.1 修改 Header (UIPresenter.h)

// g:\App\DIME\UIPresenter.h

// [修改] 函式宣告,新增 pSourceText 參數
void ShowNotifyText(_In_ CStringRange *pNotifyText, _In_opt_ UINT delayShow = 0, _In_opt_ UINT timeToHide = 0, _In_opt_ NOTIFY_TYPE notifyType  = NOTIFY_TYPE::NOTIFY_OTHERS, _In_opt_ CStringRange *pSourceText = nullptr);

4.2 修改實作 (UIPresenter.cpp)

// g:\App\DIME\UIPresenter.cpp

// [修改] 函式定義,新增 pSourceText 參數
void CUIPresenter::ShowNotifyText(_In_ CStringRange* pNotifyText, _In_opt_ UINT delayShow, _In_opt_ UINT timeToHide, _In_opt_ NOTIFY_TYPE notifyType, _In_opt_ CStringRange *pSourceText)
{
    // ... 前面原本的程式碼 ...

    // 找到以下這段,加入傳遞 SourceText 的邏輯
    if (SUCCEEDED(pContext->GetActiveView(&pView)) && pView)
    {
        // [新增] 如果有 pSourceText,就傳給視窗
        if (_pNotifyWnd && pSourceText) _pNotifyWnd->SetSourceText(pSourceText); 

        pView->GetWnd(&parentWndHandle);
        // ...
    }
    // ...
}

5. 反查邏輯 (ReverseConversion.cpp)

目標: 在送出反查結果時,把「原本的字」一起送出去,並指定類型為 NOTIFY_REVERSE_CONVERSION

// g:\App\DIME\ReverseConversion.cpp

// 找到 _AsyncReverseConversionNotification 函式

// [修改] 
// 1. 建立 sourceText (原本的 _commitString)
// 2. 呼叫 ShowNotifyText 時傳入 sourceText
// 3. 通知類型改為 NOTIFY_REVERSE_CONVERSION

if(SUCCEEDED(reverseConversionList->GetString(0, &bstrResult))  && bstrResult && SysStringLen(bstrResult))
{
    CStringRange reverseConvNotify;
    WCHAR* pwch = new (std::nothrow) WCHAR[SysStringLen(bstrResult)+1];
    StringCchCopy(pwch, SysStringLen(bstrResult)+1, (WCHAR*) bstrResult);
    
    // [新增] 準備來源文字
    CStringRange sourceText;
    sourceText.Set(_commitString, wcslen(_commitString));
    
    // [修改] 傳入參數
    _pUIPresenter->ShowNotifyText(&reverseConvNotify.Set(pwch, wcslen(pwch)), 0, 0, NOTIFY_TYPE::NOTIFY_REVERSE_CONVERSION, &sourceText);
}