WTL/MFC - Popup Menu 初心筆記 I

學 WTL 的 Control 操作,只看網路教學文章沒看標準手冊/書,就是會有繞遠路的風險...

修改前
...
BEGIN_MSG_MAP_EX(MyControl)
  MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
...

void OnContextMenu(CWindow wnd, CPoint p)
{
   CMenu menu;
   menu.LoadMenu(MAKEINTRESOURCE(IDR_MENU1);
   BOOL = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, p.x, p.y, this->GetParent());
   ...
}

遠路一 座標系不一樣

算是小遠路,因為沒有 MFC UI 的設計經驗,所以不知道要 ScreenToClient 將座標系從 event 的 screen point 轉成 control 內部的 client point。我的右鍵視窗一直亂跳,還好後來有發現跳出的位置是相對的,只花了一點點時間。

修改後 - 1
...
BEGIN_MSG_MAP_EX(MyControl)
  MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
...

void OnContextMenu(CWindow wnd, CPoint p)
{
   CMenu menu;
   menu.LoadMenu(MAKEINTRESOURCE(IDR_MENU1);
   ScreenToClient(&p); // <--
   BOOL = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, p.x, p.y, this->GetParent());
   ...
}

遠路 2 - Popup 視窗只能使用 submenu。

直接使用主 menu,它沒辦法順利 render 出我想像中的樣子。每一個 menu item 都是沒有寬度的。這個問題找了超久,後來一直 google popup menu 之類的文章,一直看到大家都會用一個 GetSubMenu ,看第一次以為是個案,想說是他想要某個子視窗當 popup,後來發現每一個文章都是用 submenu,我就死馬當活馬醫,也用 submenu,就成功啦,item 都正確秀出來。

後來聽前輩講,popup menu 本來就只能用在 submenu,這個他的 SDK 就有說...

修改後 - 2
...
BEGIN_MSG_MAP_EX(MyControl)
  MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
...

void OnContextMenu(CWindow wnd, CPoint p)
{
   CMenu menu;
   menu.LoadMenu(MAKEINTRESOURCE(IDR_MENU1);
   ScreenToClient(&p); 
   CMenu sub_menu = menu.GetSubMenu(0); // <--
   BOOL = sub_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, p.x, p.y, this->GetParent()); // <--
   ...
}

只是做個 Testbed ,UI 就如此深奧。

comments powered by Disqus