Skip to main content

Featured

Build docker image from multiple build contexts

Build docker image from multiple build contexts Building a docker image requires specifying a source of truth to include in the image from a local directory or a remote git repository. In the previous version, the docker BuildKit allows users to specify the build context from a single source of truth only. However, the engineers may need to have the context from different locations based on the type of files. For instance, icons, images or other resources that are not included in the same package, including the resource from other docker images. Fortunately, the Docker Buildx toolkit supports multiple build context flag for Docker 1.4. Let's learn how to use this new feature. The following list is a shortcut for jumping into a specific topic handy. What version of Docker is this tutorial targeting? How to specify the version of Dockerfile frontend? Ho

[TreeCtrl]Drag and Drop

Ref:Drag and drop

這邊需使用到CImageList來進行,D&D的圖示繪製。
由於CTreeCtrl有提供接收D&D的訊息事件,TVN_BEGINDRAG
新增的方式為,選擇於類別檢視內的CTreeCtrl衍伸類別,之後選擇屬性視窗,點選訊息,之後新增TVN_GEGINDRAG就可以了。

這邊會需要用到幾個data member,所以先宣告好。
Header:
 .....  
     protected:  
         CImageList *m_pDragImage;  
         HTREEITEM m_hDragItem;  
         HTREEITEM m_hDropItem;  
         BOOL m_IsLDragging;  
 .....  

在建立好OnTvnBegindrag()後,就可以在裡面實作按下滑鼠左鍵的行為:
 void CDSTreeCtrl::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)  
 {  
     LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);  
     // TODO: 在此加入控制項告知處理常式程式碼  
     *pResult = 0;  
   
     this->m_hDragItem = pNMTreeView->itemNew.hItem;  
     this->m_pDragImage = this->CreateDragImage(this->m_hDragItem);  
   
     if ( !this->m_pDragImage ) {  
         return; };  
   
     this->m_IsLDragging = TRUE;  
     this->m_pDragImage->BeginDrag(0, CPoint(-15, -15));        //0 = current used image. Because of this item just has one image.  
                                                             //Under cursor, (-15, -15).  
     POINT pt = pNMTreeView->ptDrag;  
     ClientToScreen(&pt);  
     this->m_pDragImage->DragEnter(NULL, pt);  
     this->SetCapture();  
 }  

此時,僅有設定拖曳的時候所要顯示的圖示,所以還要處理WM_MOUSEMOVE的事件。這個訊息一樣可以透過上述方式來新增。
 void CDSTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)  
 {  
     // TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值  
     HTREEITEM hItem = NULL;  
     UINT uFlag = 0;  
   
     if ( this->m_IsLDragging )  
     {  
         POINT pt = point;  
         ClientToScreen(&pt);  
         CImageList::DragMove(pt);  
   
         if ( NULL != (hItem = this->HitTest(point, &uFlag)) )  
         {  
             CImageList::DragShowNolock(FALSE);  
             this->SelectDropTarget(hItem);  
             this->m_hDropItem = hItem;  
             CImageList::DragShowNolock(TRUE);  
         }    //End of if ( NULL != (hItem = this->HitTest(point, &flags)) )  
     }    //End of if ( this->m_IsLDragging )  
   
     CTreeCtrl::OnMouseMove(nFlags, point);  
 }  

最後就是當滑鼠左鍵釋放時,要把選擇的item移到新的位置去。這邊的作法目前僅適用於同一個Tree的item移動。
如有要移到其他位置,那就要配合SendMessage()來處理了。
 void CDSTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)  
 {  
     // TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值  
     if ( this->m_IsLDragging )  
     {  
         this->m_IsLDragging = FALSE;  
         CImageList::DragLeave(this);  
         CImageList::EndDrag();  
         ::ReleaseCapture();  
   
         delete this->m_pDragImage;    //MUST TO DO.  
   
         this->SelectDropTarget(NULL);    //Remove drop target highlighting  
   
         if ( this->m_hDragItem == this->m_hDropItem ) {  
             return; };  
   
         //If Drag item is an ancestor of drop item then return  
         HTREEITEM hItemParent = this->m_hDropItem;  
         while ( NULL != (hItemParent = this->GetParentItem(hItemParent)) )  
         {  
             if ( hItemParent == this->m_hDragItem ) {  
                 return; };  
         }    //End of while ( NULL != (hItemParent = this->GetParentItem(hItemParent)) )  
   
         this->Expand(this->m_hDropItem, TVE_EXPAND);  
   
         //HTREEITEM hItemNew = NULL;  
         //hItemNew = CopyBranch(this->m_hDragItem, this->m_hDropItem, TVI_LAST);  
             //REF:http://www.vckbase.com/english/code/treeview/copy_item.shtml.htm  
         //this->DeleteItem(this->m_hDragItem);  
         //this->SelectItem(hItemNew);  
   
     }    //End of if ( this->m_IsLDragging )  
   
     CTreeCtrl::OnLButtonUp(nFlags, point);  
 }  

NOTE:由於TreeCtrl收到的座標原點在TreeCtrl內,所以當LButtonUp時,所得到的座標資訊,是無法用在其他的物件內。 故必須重新抓新的滑鼠座標。
處理方式有以下兩種:
1.直接用GetCursorPos()並配合ScreenToClient()來取得被當作Drop目的地的座標。
     pLDragOnGLView->pTree->ClientToScreen(&pLDragOnGLView->ptMousePos);  
     this->m_glWindow.ScreenToClient(&pLDragOnGLView->ptMousePos);  

2.將CTreeCtrl提供的point先用ClientToScreen()轉成螢幕座標,再用被當作Drop目的物件的ScreenToClient()來取得實際的座標位置。
     CPoint pt;  
     ::GetCursorPos(&pt);  
     this->m_glWindow.ScreenToClient(&pt);  
     this->m_glWindow.OnLButtonUp(pLDragOnGLView->unMouseMovementFlags, pLDragOnGLView->ptMousePos);  
   

然後由於在OnTvnBeginDrag()時,有設定SetCapture(),所以LButtonUp的訊息會先進到CTreeCtrl內,因此如有要把拖曳的物件放到別的控制項的話,必須在另外呼叫控制項的LButtonUp。

Comments

Popular Posts