SumatraPDF代碼結構不完全解讀

因爲SumatraPDF在基本使用方面非常的好用,但一些別的功能不是很完善,因此就想通過修改一下它的源碼來實現我想要的功能(比如說分窗口啊,註釋啊之類的),大概讀了三天吧…稍微有了一點感覺,就覺得這個工程量確實有點大…打了退堂鼓,但這幾天的解讀不能白白浪費,網上也沒有很好的解讀,於是就稍微寫一些,留給以後想擴展其源碼的人吧233.

編譯

編譯需要VS2017,我不知道更早的版本是否可行,但2019應該是不行的,因爲它應該是已經移除了對xp的支持
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
然後需要安裝WIN SDK8.1+10,需要安裝141和xp支持,如果都安裝了,沒有意外應該還會編譯失敗,會報兩個錯誤,我沒有截圖,就是編碼錯誤,據說把錯誤級別調低就可以,但我沒去查怎麼調低,去把錯誤的編碼重新換了一下,然後就編譯成功了。

這個框架我不清楚是直接使用的WindowsAPI還是用的MFC,在我的查閱過程中很多聲明都是混着用的感覺。

入口函數.\src\SumatraStartup.cpp:535

int APIENTRY WinMain(...){
	...
	CreateAndShowWindowInfo()//742
	...
}

一直到調用CreateAndShowWindowInfo方法前,都是初始化方法,在CreateAndShowWindowInfo方法(位於.\src\SumatraPDF.cpp)裏,通過調用WindowsAPIShowWindow()方法來顯示主窗體(變量爲win->hwndFrame)。

在調用完CreateAndShowWindowInfo方法後,會存儲或讀取一些歷史信息,並將當前目錄改到c:\windows\system32下(爲了不佔用目錄)

隨後進入信息接收循環體(retCode = RunMessageLoop();//783),不斷的接收窗口事件並分發事件,直到關閉窗體,之後釋放內存。

文檔界面信息類:\src\WindowInfo.h

class WindowInfo

裏面保存了頁面的縮放、offset、目錄/書籤是否顯示等各種信息,每一個文檔都會有一個這樣的信息,最終所有的WindowInfo類會被保存到SumatraPDF.cpp:109std::vector<WindowInfo*> gWindows;中。

事件分發
事件分發與WindowsAPI有關,分發方法定義在\src\SumatraStartup.cpp:450,通過不斷的調用GetMessage方法用MSG結構體(定義在\Microsoft SDKs\Windows\v7.1A\Include\WinUser.h中,結構如下)來接收可能存在的信息。

typedef struct tagMSG {
    HWND        hwnd;//接收消息的窗口句柄
    UINT        message;//消息標識符。這是一個數值,用以標識消息。
    WPARAM      wParam;//一個32位的「message parameter(消息參數)」,其含義和數值根據消息的不同而不同
    LPARAM      lParam;//一個32位的消息參數,其值與消息有關。
    DWORD       time;//消息放入消息隊列中的時間。
    POINT       pt;//消息放入消息隊列時的鼠標座標。
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

接收到信息後,會進行相應的轉換,並分發到各自的窗口中去處理事件,處理事件的方法是事先定義好後,在創建窗口的時候指派的,具體可以查看CreateWindowExW()方法的參數,該方法指定所創建窗口的標識符、父窗口和事件處理方法(以及其他屬性,如風格,查看 創建一個簡單窗口 )。

這裏的窗口是廣義的窗口,即按鈕啊這些都算是一個窗口。

文件讀取:\src\SumatraPDF.cpp:1427

WindowInfo* LoadDocument(LoadArgs& args)

參數args中包含文件路徑,所展示窗口(當前焦點所在的,可能會在之後被新創建的窗口信息替換)等信息,用於讀取並顯示文檔。如果沒有其他問題,那麼就會創建一個Controller類來裝載全部的文檔信息,在Controller內,實際上裝載了一個BaseEngine類,它是真正的讀取各個文檔並抽取信息的類。Controller又在BaseEngine之上加上了窗體信息(如zoom倍率)。

在創建完成文檔信息後,就會創建一個Tab用於切換窗口,最後,使用static void LoadDocIntoCurrentTab()//945來真正的在UI界面中顯示。

創建窗口信息\src\SumatraPDF.cpp:1230
該方法單純的創建一個窗體信息,但是並沒有顯示出來,等待其他方法來將該窗體顯示出來

static WindowInfo* CreateWindowInfo()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章