TabBars代碼解讀之——Tabbar欄與其他視窗之間的關係

來源:互聯網
上載者:User

    整合式開發環境中各個視窗的行為都是事先實現的,比如,文檔編輯視窗對應著多文檔類的視圖視窗,負責對使用者的輸入進行響應,更新視窗的內容,主視窗負責調度各個視圖視窗。Visual Studio的整合式開發環境(IDE)沒有給我們提供任何介面實現在IDE中添加一個視窗,並且這個視窗能夠和IDE中其他視窗分享訊息的功能,也就是說正常情況下外掛程式無法幹涉IDE環境中視窗的正常行為。但是,這並不意味著我們只能老老實實的作些本分工作,因為通過視窗的子類化技術(Subclassing),我們一樣可以Hook視窗的訊息。Visual Studio的外掛程式是工作在IDE的進程空間的,這就給我們提供了Hook IDE內任何視窗的機會。從理論上講,我們可以使用自己的視窗訊息處理過程代替IDE中各個視窗的標準視窗訊息處理過程,完成對特定訊息的響應,甚至完全改變某個視窗的行為。著名的VC商業外掛程式軟體Visual Assist就是替換了文檔編輯的視圖視窗,從而使其比預設的文檔編輯視窗提供更多的便利功能。
    Visual Studio的IDE環境有很多視窗,我們關心的只有三個(類)視窗,一個是主架構視窗,一個是MDI子架構視窗,一個是文件視窗。TabBars的標籤欄其實並不依賴主架構視窗的訊息約束自己的行為,子類化主架構視窗主要是為了處理WM_GETTEXT訊息。當使用者在不同的文件視窗之間切換時,主架構視窗就會相應的改變視窗標題列上顯示的文字,Hook WM_GETTEXT訊息可以使Tabbars外掛程式自己建立的視窗能夠在第一時間獲得這個訊息並做出相應的處理。子類化MDI子架構視窗有兩個主要目的,一個是截獲視窗大小和位置變更的訊息以便能夠適時的調整標籤欄的大小和位置;另一個是向文件視窗報告MDI子架構視窗新的客戶區位置,新客戶區排除了標籤欄視窗佔用的位置,如果不處理這個訊息,架構視窗會將文件視窗會按照預設的位置擺放,這會遮擋標籤欄視窗。子類化文件視窗是為了處理WM_DESTROY訊息,以便能夠在使用者關閉文件視窗時有機會更新標籤欄上的按鈕。是TabBars外掛程式的視窗類別關係圖:


圖1. Tabbars視窗類別關係圖

    關係圖中的核心是CTabManagerWindow類,這個類雖然名為TabManager,但是並不直接管理標籤欄,它通過CTabBarsWnd管理標籤欄。CTabBarsWnd是一個MFC的CWnd衍生類別,他的作用有兩個,一個是周期的產生定時器事件,驅動TabBars外掛程式完成檔案自動儲存之類的工作;另一個作用就是作為容器視窗承載一個Table控制項。

    子類化視窗的關鍵是找到視窗的控制代碼,Visual Studio的內建外掛程式介面沒有提供擷取這些視窗控制代碼的方法,TabBars使用了很多小的Trick來達到這個目的,首先是hook主架構視窗,先看下面的代碼:

pApp->put_Active(VARIANT_FALSE);
pApp->put_Active(VARIANT_TRUE);
hWnd = ::GetActiveWindow();
while (hWnd  &&  hWnd != hDesktopWnd)
{
hDevStudioWnd = hWnd;
hWnd = ::GetParent(hWnd);
}
g_pDevStudioWnd = new CDevStudioWnd(hDevStudioWnd); //CWnd::FromHandle(hDevStudioWnd);

put_Active是操作IApplication介面的Active屬性,確保Visual Studio的IDE視窗是當前使用中視窗,緊跟著調用GetActiveWindow獲得這個視窗。不過,GetActiveWindow通常得到的是IDE下的活動子視窗,所以通過向上尋找父視窗最終可以得到真正的主架構視窗。

    得到主架構視窗之後就可以順藤摸瓜得到MDI子架構視窗,MDI子架構視窗使用了固定的類名:MDIClient,所以遍曆主架構視窗的所有子視窗就可以找到MDI客戶區視窗:

char cClassName[256];

hMDIWnd = g_pDevStudioWnd->GetTopWindow()->m_hWnd;
::GetClassName(hMDIWnd, (LPTSTR)cClassName, sizeof(cClassName));
while (strcmp(cClassName, "MDIClient") != 0)
{
  hMDIWnd = ::GetNextWindow(hMDIWnd, GW_HWNDNEXT);
  ASSERT(hMDIWnd);
  GetClassName(hMDIWnd, (LPTSTR)cClassName, sizeof(cClassName));
}

子類化這些關鍵視窗,使得TabBars外掛程式自己建立的視窗可以hook適當的訊息,通過響應這些訊息,TabBars外掛程式可以調整標籤欄的位置,更新標籤欄並通知其他視窗MDI客戶區的改變,從而使TabBars視窗能夠融入到Visual Studio的整合式開發環境(IDE)中。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.