處理Win32的Tree-View Item主要分為三個步驟。
開始拖曳通知
當使用者開始拖曳(Drag)Tree-View Item時,Tree-View元件會經由WM_NOTIFY訊息發送一個TVN_BEGINDRAG通知給父視窗,這時應用便可以以這個通知得知使用者從什麼位置開始拖曳那一個Item,並開始進入拖曳程序。
當使用者以滑鼠左鍵開以拖曳物件時,Tree-View送出一個TVN_BEGINDRAG,接著應用程式需要處理WM_MOUSEMOVE訊息來反應使用者拖曳的動作,直到使用者將滑鼠按鍵放開產生一個WM_LBUTTONUP訊息時,才結束拖曳動作。附帶一提,如果使用者是以滑鼠右鍵開始拖曳物件,則產生的通知是TVB_BEGINRDRAG,並以對應的WM_RBUTTONUP訊息作結束訊號。
Tree-View的父視窗接收到一個WM_LBUTTONUP訊息時,表示拖曳程序終止。應用程式執行相關狀態回覆並且根據自己的定義執行拖放動作的操作。
參考連結
- 開始拖曳通知。
- 拖曳中處理。
- 拖曳結束。
開始拖曳通知
當使用者開始拖曳(Drag)Tree-View Item時,Tree-View元件會經由WM_NOTIFY訊息發送一個TVN_BEGINDRAG通知給父視窗,這時應用便可以以這個通知得知使用者從什麼位置開始拖曳那一個Item,並開始進入拖曳程序。
case WM_NOTIFY:Main_OnBeginDrag是應用程式定義的一個函式,主要的任務是設定好相關狀態表示進入拖曳程序,並由Tree-View取得一個暫時的ImageList元件,可以用來畫出拖曳中的Item。
switch (((LPNMHDR)lParam)->code)
{
case TVN_BEGINDRAG:
// ...由此進入拖曳程序
Main_OnBeginDrag();
break;
}
break;
void Main_OnBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv)拖曳中處理
{
// 取得暫時的ImageList.
HIMAGELIST himl = TreeView_CreateDragImage(hwndTV, lpnmtv->itemNew.hItem);
// 開始進入拖曳.
ImageList_BeginDrag(himl, 0, 0, 0);
ImageList_DragEnter(hwndTV, lpnmtv->pt.x, lpnmtv->pt.x);
SetCapture(GetParent(hwndTV));
g_fDragging = TRUE;
}
當使用者以滑鼠左鍵開以拖曳物件時,Tree-View送出一個TVN_BEGINDRAG,接著應用程式需要處理WM_MOUSEMOVE訊息來反應使用者拖曳的動作,直到使用者將滑鼠按鍵放開產生一個WM_LBUTTONUP訊息時,才結束拖曳動作。附帶一提,如果使用者是以滑鼠右鍵開始拖曳物件,則產生的通知是TVB_BEGINRDRAG,並以對應的WM_RBUTTONUP訊息作結束訊號。
void Main_OnMouseMove(HWND hwndParent, HWND hwndTV, LONG xCur, LONG yCur)拖曳結束
{
if (!g_fDragging)
return;
// 更新滑鼠拖曳的座標.
POINT point;
point.x = xCur;
point.y = yCur;
ClientToScreen(hwndParent, &point);
ScreenToClient(hwndTV, &point);
ImageList_DragMove(point.x, point.y);
// 暫時關閉不畫拖曳物件,讓Tree-View可以重畫它的內容.
ImageList_DragShowNoLock(FALSE);
// 取得滑鼠指標底下的Item,並將它設定成DropTarget Item.
TVHITTESTINFO tvht;
tvht.pt.x = point.x;
tvht.pt.y = point.y;
HTREEITEM htiTarget = TreeView_HitTest(hwndTV, &tvht);
if (NULL != htiTarget)
TreeView_SelectDropTarget(hwndTV, htiTarget);
// 繼續繪製拖曳的物件.
ImageList_DragShowNoLock(TRUE);
}
Tree-View的父視窗接收到一個WM_LBUTTONUP訊息時,表示拖曳程序終止。應用程式執行相關狀態回覆並且根據自己的定義執行拖放動作的操作。
void Main_OnLButtonUp(HWND hwndTV)
{
if (!g_fDragging)
return;
// 取得拖放目標.
HTREEITEM htiDest = TreeView_GetDropHilight(hwndTV);
if (NULL != htiDest)
{
// To do: 執行實際的移動或相關操作.
}
// 釋放掉暫時的ImageList物件.
ImageList_EndDrag();
// 狀態回覆.
TreeView_SelectDropTarget(hwndTV, NULL, TRUE);
ReleaseCapture();
g_fDragging = FALSE;
}
參考連結
留言
張貼留言