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

[CListCtrl]欄位顯示多行文字

由於MFC提供的CListCtrl並無輸入多行文字功能,因此也需要從繪圖的部分下手。
由於ClistCtrl一次也只能顯示一行文字,因此在進行顯示多行文字之前,需先讓CListCtrl的欄位可以隨著文字段數變動。這邊可以參考[CListCtrl]改變行高 。(參考文獻在上述連結內都有)

在顯示多行文字部分,則是透過改寫DrawItem()來讓文字可以斷行。

使用前,需先將CListCtrl的Owner Draw Fixed屬性打開(坊間流傳的SetExtendedStyle(LVS_OWNERDRAWFIXED)並無效果)。(PS.在這邊浪費了好幾個小時@@,果然跑不起來還是要先查設定@@)

在.h部分
 afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);  

在.cpp部分
 void CXListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)   
 {  
     TCHAR lpBuffer[256];  
     LV_ITEM lvi;  
     lvi.mask = LVIF_TEXT | LVIF_PARAM ;  
     lvi.iItem = lpDrawItemStruct->itemID ;       
     lvi.iSubItem = 0;  
     lvi.pszText = lpBuffer ;  
     lvi.cchTextMax = sizeof(lpBuffer);  
     VERIFY(GetItem(&lvi));  
     LV_COLUMN lvc, lvcprev ;  
     ::ZeroMemory(&lvc, sizeof(lvc));  
     ::ZeroMemory(&lvcprev, sizeof(lvcprev));  
     lvc.mask = LVCF_WIDTH | LVCF_FMT;  
     lvcprev.mask = LVCF_WIDTH | LVCF_FMT;  
     for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)  
     {  
         if ( nCol > 0 )   
         {  
             // Get Previous Column Width in order to move the next display item  
             GetColumn(nCol-1, &lvcprev) ;  
             lpDrawItemStruct->rcItem.left += lvcprev.cx ;  
             lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left ;      
         }

         // Get the text   
         ::ZeroMemory(&lvi, sizeof(lvi));  
         lvi.iItem = lpDrawItemStruct->itemID;  
         lvi.mask = LVIF_TEXT | LVIF_PARAM;  
         lvi.iSubItem = nCol;  
         lvi.pszText = lpBuffer;  
         lvi.cchTextMax = sizeof(lpBuffer);  
         VERIFY(GetItem(&lvi));  
         CDC* pDC;  
         pDC = CDC::FromHandle(lpDrawItemStruct->hDC);  
 //--------------- Full selection - highlight -----------------------  
         if ( lpDrawItemStruct->itemState & ODS_SELECTED )  
         {  
             pDC->FillSolidRect(&lpDrawItemStruct->rcItem, GetSysColor(COLOR_HIGHLIGHT)) ;   
             pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) ;  
         }  
         else  
         {  
             pDC->FillSolidRect(&lpDrawItemStruct->rcItem, GetSysColor(COLOR_WINDOW)) ;  
             pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) ;   
         }  
 //--------------- Full selection - highlight -----------------------  
         pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));  
         UINT        uFormat  = DT_LEFT ;  
         ::DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer),   
              &lpDrawItemStruct->rcItem, uFormat) ;  
         pDC->SelectStockObject(SYSTEM_FONT) ;  
 //Enable measureitem().  
         this->OnSetFont(NULL, NULL);  //配合MeasureItem()用的        
     }  
 }  

目前這個範例裡面還看不出是怎麼讓文字斷行的,但可確定的是,由於這個function會重新變更欄位的字體與背景顏色。因此當同時還有使用到OnNMCustomdrawLst()的話,OnNMCustomdrawLst()所繪製的顏色會被DrawItem()所覆蓋掉(因OnNMCustomdrawLst()比DrawItem()早執行),所以這邊要注意。
如有找到換行的方法,之後再補上。
PS.測試結果,DrawText似乎會在遇到newline時,就會把後面的文字自動輸出到下一行。

Problem:
1.在移動欄位title時,欄位內顯示之文字並不會像CListCtrl一樣,會加上"..."來代表有文字被遮蓋。
看來這邊是需要自行處理。(變更欄位大小時,畫面不會更新到其他地方)
2.上一次顯示文字之尾端總是會殘留在下一個欄位的開頭,這邊也需要另外再處理。
3.此範例所繪製的文字會貼齊於Cell的最左側邊界,會與CListCtrl顯示結果不同。

新找到的:Multi-line List Control
這篇提供的方法可以解決P.1、P.2、P3的問題。
差別在於,這篇提供的畫文字方法是CDC::DrawTextEx。這樣就可以讓CListCtrl自行去處理上述之問題,不然要手動處理的話,倒是挺麻煩的。如此一來,函式也變得比較乾淨了。

修改過後的函式如下:
 void CXListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)   
 {  
     LPDRAWITEMSTRUCT lpDrawHighLight = new DRAWITEMSTRUCT();  
     CString cstrSubitemText = "";  
     CRect rcSubItemRect;          
     CDC* pDC =     CDC::FromHandle(lpDrawItemStruct->hDC);        //不用釋放  
     LV_ITEM lvi;  
     rcSubItemRect.SetRectEmpty();  
     LV_COLUMN lvc, lvcprev ;  
     ::ZeroMemory(&lvc, sizeof(lvc));  
     ::ZeroMemory(&lvcprev, sizeof(lvcprev));  
     lvc.mask = LVCF_WIDTH | LVCF_FMT;  
     lvcprev.mask = LVCF_WIDTH | LVCF_FMT;  
     //lpDrawItemStruct->rcItem為目前所要畫出文字的row的邊界。  
     for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)  
     {  
         // Get Previous Column Width in order to move the next display item  
         if ( nCol > 0 )   
         {              
             GetColumn(nCol-1, &lvcprev) ;  
             lpDrawItemStruct->rcItem.left += lvcprev.cx;  
             //lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left;            //會影響到最後一個SubItem的顯示長度。  
         }  
 //--------------- Full selection - highlight -----------------------  
         //Let Drawed highlight like the CListCtrl do it.  
         ::memcpy(lpDrawHighLight, lpDrawItemStruct, sizeof(DRAWITEMSTRUCT));  
         lpDrawHighLight->rcItem.left += this->GetStringWidth(" ");        //保留開頭的空白。讓行為同CListCtrl。  
         if ( lpDrawItemStruct->itemState & ODS_SELECTED )  
         {  
             pDC->FillSolidRect(&lpDrawHighLight->rcItem, GetSysColor(COLOR_HIGHLIGHT)) ;   
             pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) ;  
         }  
         else  
         {  
             pDC->FillSolidRect(&lpDrawHighLight->rcItem, GetSysColor(COLOR_WINDOW)) ;  
             pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) ;   
         }  
 //--------------- Full selection - highlight -----------------------  
 //-------------- Draw item -------------------------  
         pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));  
         if ( !this->GetSubItemRect(lpDrawItemStruct->itemID, nCol, LVIR_BOUNDS, rcSubItemRect) ) {  
             continue;    };  
         //::DrawText(lpDrawItemStruct->hDC, lpDisplayBuf, nShowWordsLen, &lpDrawText->rcItem, uFormat) ;  
         rcSubItemRect.left += this->GetStringWidth(" ");  
         rcSubItemRect.right -= this->GetStringWidth(" ");  
         cstrSubitemText = this->GetItemText(lpDrawItemStruct->itemID, nCol);  
         pDC->DrawTextEx(cstrSubitemText, rcSubItemRect, (DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORD_ELLIPSIS), NULL);  
         pDC->SelectStockObject(SYSTEM_FONT) ;  
 //-------------- Draw item -------------------------  
 //Enable measureitem().  
         this->OnSetFont(NULL, NULL);          
     }    //End of for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)  
     if ( lpDrawHighLight != NULL )    {  
         delete lpDrawHighLight;  
         lpDrawHighLight = NULL;  
     }  
 }  

Comments

Popular Posts