//
// 函數名: DrawProgress()
// 功能:自訂繪製進度條, 在指定HDC內的RECT內繪製進度條, 適用於清單控制項中插入進度條的應用.
// 參數:
// SourceRect --- 清單控制項中的SubItem矩形, (自己畫的進度條要小於它一個像素)
// hdc --- 清單控制項中的hdc
// nProgressPercent -- 進度步值, 從0到100. (自己看看應該懂這是什麼意思的,嘻嘻)
//
VOID DrawProgress(HDC hdc, RECT SourceRect, int nProgressPercent)
{
RECT rect; // 整個進度條的矩形, 比來源矩形小一個單位(想要小多少隨你定,呵呵)
rect = SourceRect;
rect.left += 1;
rect.top += 1;
rect.right -= 1;
rect.bottom -= 1;
RECT LeftRect, RightRect; // 左右各一個矩形, 用於進度條文字可以在每個矩形內顯示不同的顏色
LeftRect = rect;
LeftRect.left += 1;
LeftRect.top += 1;
LeftRect.bottom -= 1;
RightRect = LeftRect;
int w = ((rect.right - rect.left - 2) * nProgressPercent) / 100 ; // nProgressPercent變數,從0-100表示百分比
LeftRect.right = LeftRect.left + w ;
RightRect.left = LeftRect.right;
// 用指定顏色繪製進度條****************************************
// 邊框
HBRUSH hBrushRed=CreateSolidBrush(RGB(224, 0, 0)); // 顏色自定
FrameRect (hdc, &rect, hBrushRed);
DeleteObject(hBrushRed);
// 填充
HBRUSH hBrushGreen=CreateSolidBrush(RGB(0, 224, 0)); // 顏色自定
FillRect(hdc, &LeftRect, hBrushGreen);
DeleteObject(hBrushGreen);
// 繪製進度文字**************************************************
TCHAR szFormatStr[10];
_snprintf(szFormatStr, 10, TEXT("%d%%"), nProgressPercent); // 這裡可以知道為什麼nProgressPercent要取0到100了吧。
// 設定文字背景色透明
SetBkMode(hdc, TRANSPARENT);
RECT TextRect = rect; // 文字繪製區
HRGN hRgnLeft = CreateRectRgnIndirect(&LeftRect);
SelectClipRgn(hdc, hRgnLeft);
SetTextColor(hdc, RGB(0, 0, 255)); // 文字顏色
DrawText(hdc, szFormatStr, -1, &TextRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
DeleteObject(hRgnLeft);
HRGN hRgnRight = CreateRectRgnIndirect(&RightRect);
SelectClipRgn(hdc, hRgnRight);
SetTextColor(hdc, RGB(255, 0, 0)); // 文字顏色
DrawText(hdc, szFormatStr, -1, &TextRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
DeleteObject(hRgnRight);
SelectClipRgn(hdc, NULL);
}
2、正確的響應NM_CUSTOMDRAW訊息。
程式碼片段如下:
case WM_NOTIFY: // 清單控制項發來的通知
// Process notification messages.
switch (((LPNMHDR) lParam)->code)
{
case NM_CUSTOMDRAW: // 自繪清單控制項
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT :
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW);
return CDRF_NOTIFYSUBITEMDRAW;
case CDDS_ITEMPREPAINT:
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYSUBITEMDRAW);
return CDRF_NOTIFYSUBITEMDRAW;
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
{
int nItemSpec = lplvcd->nmcd.dwItemSpec;
int nSubItem = lplvcd->iSubItem;
// 處理第二個進度子項 (放在哪個列你可以自己定義)
RECT rect;
ListView_GetSubItemRect(hWndListView, nItemSpec, 1, LVIR_BOUNDS, &rect);
// TODO: 在適當的位置處理n, 使其在0到100範圍內,然後更新該rect的地區。
DrawProgress(lplvcd->nmcd.hdc, rect, n );
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_DODEFAULT); // 對話方塊需要這行才行。
return CDRF_DODEFAULT;
}
}
}
return FALSE; // 其他的不處理,返回給WINDOWS
處理n的範例程式碼:
// 在某個位置改變n的值後就重新整理該地區以使進度條前進,如
n++;
RECT rect;
ListView_GetSubItemRect(hWndListView, Index, 1, LVIR_BOUNDS, &rect); // index就是項目索引
InvalidateRect(hWndListView, &rect, FALSE);
UpdateWindow(hWndListView);