Antes de mirar el código, les adjuntaré una representación:
Sin más preámbulos, simplemente publicaré el código.
unidad Unidad1;interfazusaWindows, Mensajes, SysUtils, Variantes, Clases, Gráficos, Controles, Formularios,Diálogos, StdCtrls, ComCtrls, ImgList;tipoTForm1 = clase(TForm)btn1: TButton;lv1: TListView;trckbr1: TTrackBar;il1: TImageList;procedimiento lv1CustomDraw(Remitente: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean); procedimiento lv1CustomDrawItem (Remitente: TCustomListView; Elemento: TListItem; Estado: TCustomDrawState; var DefaultDraw: Procedimiento booleano); TObject);privatefunction ReDrawItem(HwndLV: HWND; ItemIndex: integer): boolean;{ Declaraciones privadas }public{ Declaraciones públicas }end;varForm1: TForm1;implementationusesCommCtrl;{$R *.dfm}//Procedimiento de barra de estado de dibujo DrawSubItem(LV : TListView Artículo: TListItem; Prosition: Single; Style: Integer; IsShowProgress: Boolean; DrawColor: TColor = $00005B00; FrameColor: TColor = $00002F00);// Obtener la función de área de SubItem GetItemRect(hWndLV: HWnd; iItem, iSubItem: Integer): TRect ;varRect: TRect;beginListView_GetSubItemRect(hWndLV, iItem, iSubItem, iSubItem, @Rect);Resultado := Rect;end;varPaintRect, R: TRect;i, iWidth, x, y: entero;S: cadena;beginwith lv dobeginPaintRect := GetItemRect( lv.Mango, Artículo.Índice, SubItem);R := PaintRect;if Prosition >= Max entoncesProsition := 100elsebeginif Prosition <= 0 thenProsition := 0elseProsition := Round((Prosition / MAX) * 100);end;if (Prosition = 0) y (no IsShowProgress ) luegoCanvas.FillRect(r) //Si es 0 , muestra directamente el espacio en blanco elsebegin//Rellena el fondo primero Canvas.FillRect(r);Canvas.Brush.Color:= Color;//Dibuja un marco exteriorInflateRect(R, -2, -2);Canvas.Brush.Color: = FrameColor;Canvas.FrameRect(R);Canvas.Brush.Color := Color;InflateRect(R, -1, -1);//InflateRect(R,-1,-1);//Calcule la descripción general del contenido de la barra de progreso en función del porcentaje iWidth := R.Right - Round((R.Right - R.Left) * ( ( 100 - Prosition) / 100));case Style of0: //Solid BeginCanvas.Brush.Color := DrawColor;R.Right := iWidth;Canvas.FillRect(R);end;1: //Relleno de línea vertical begini := r.Left; while i < iWidth dobeginCanvas.Pen.Color := Color;Canvas.MoveTo(i, R.Top);Canvas .Pen.Color := DrawColor;Canvas.LineTo(i, R.Bottom);Inc(i, 3);end;end;end //caso; end//Después de dibujar la barra de progreso, todo lo que necesita hacer ahora es mostrar el número de progreso Canvas.Brush.Style := bsClear;if Prosition = Round(Prosition) thenS := Format('%d%%', [Round(Prosition) )])elseS := FormatFloat('#0.0', Prosition);con PaintRect dobeginx := Izquierda + (Derecha - Izquierda + 1 - Canvas.TextWidth(S)) div 2;y := Arriba + (Abajo - Arriba + 1 - Canvas.TextHeight(S)) div 2;end;SetBkMode(Canvas.Handle, TRANSPARENT);Canvas.TextRect(PaintRect, x , y, S);end;//Restaurar después de pintar Canvas.Brush.Color := Color;end;end;procedimiento TForm1.lv1CustomDraw(Sender: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean);beginend;// Lo anterior es dibujar la barra de progreso. Ahora necesitamos procesar el mensaje de redibujado del elemento para TlistView. Es necesario explicar que, si desea dibujar sus propios elementos como desee, debe hacerlo todo usted mismo y ya no necesitará que el sistema lo maneje: procedimiento TForm1.lv1CustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);varBoundRect, Rect: TRect;i: integer;TextFormat: Word;LV: TListView //Este subproceso se utiliza para dibujar; Procedimiento de CheckBox e ImageList Draw_CheckBox_ImageList(r: TRect; aCanvas: TCanvas; Checked: Boolean);varR1: TRect;i: Integer;beginif Sender.Checkboxes thenbeginaCanvas.Pen.Color := clBlack;aCanvas.Pen.Width := 2;//Dibuja el marco exterior de CheckBox aCanvas. Rectángulo (R.Izquierda + 2, R.Arriba + 2, R.Izquierda + 14, R.Bottom - 2);si está marcado, entonces //Dibuja el gancho de CheckBox beginCanvas.MoveTo(R.Left + 4, R.Top + 6);aCanvas.LineTo(R.Left + 6, R.Top + 11) ; aCanvas.LineTo(R.Izquierda + 11, R.Arriba + 5);end;aCanvas.Pen.Width := 1;end;//Comenzar a dibujar el icono i := 2; //El valor de ImageIndex puede ser arbitrario si i > -1 luego comenzar//Obtener el RECT del icono si Boolean(ListView_GetSubItemRect(sender.Handle, item.Index, 0, LVIR_ICON, @R1)) luego comenzar //ImageList_Stats.Draw(LV.Canvas, R1.Left, R1.Top, i);si item.ImageIndex > -1 entoncesLV.SmallImages.Draw(LV.Canvas, R1.Right + 2, R1.Top, item.ImageIndex);end;end;end;beginLV := TListView(Sender);BoundRect := Item.DisplayRect(drBounds);InflateRect(BoundRect, -1, 0);//Puede configurar este lugar con el color deseado según sus propios requisitos para lograr resaltar LV.Canvas.Font.Color := clBtnText;//Compruebe si está seleccionado si Item.Selected luego comienza si cdsFocused en Estado y luego comienza LV. Lienzo.Brush.Color := $00ECCCB9; // //clHighlight;endelsebeginLV.Canvas.Brush.Color := $00F8ECE5; //clSilver;end;endelsebeginif (Item.Index mod 2) = 0 thenLV.Canvas.Brush.Color := clWhiteelseLV.Canvas.Brush.Color := $00F2F2F2;end;LV.Canvas.FillRect(BoundRect) ; // Inicializa el fondo para i := 0 a LV.Columns.Count - 1 dobegin//Obtener RectListView_GetSubItemRect(LV.Handle, Item.Index, i, LVIR_LABEL, @Rect);case LV.Columns[i].Alignment oftaLeftJustify:TextFormat := DT_LEFT;taRightJustify:TextFormat := DT_RIGHT;taCenter:TextFormat : = DT_CENTER;elseTextFormat := DT_CENTER;end;case i of0: //Dibujar título, 0 significa título, no Subitembegin//Dibujar primero el cuadro de selección y el icono Draw_CheckBox_ImageList(BoundRect, LV.Canvas, Item.Checked);//Luego dibujar el título TextInflateRect(Rect, -(5 + il1.Width), 0); // Retrocede 3 píxeles para evitar que se sobrescriba cuando se dibuje la estructura alámbrica más tarde //InflateRect(Rect, -(5), 0); //Mueva 3 píxeles hacia atrás para evitar que se sobrescriba cuando se dibuje la estructura alámbrica más tarde DrawText( LV. Canvas.Handle, PAnsiChar(Item.Caption), Longitud(Item.Caption), Rect, DT_VCENTER o DT_SINGLELINE o DT_END_ELLIPSIS o TextFormat);end;1..MaxInt: //Dibujar SubItem[i]beginif (i - 1) = 1 luego //Mostrar la barra de estado, este ejemplo es la visualización de la tercera columna, puede personalizar beginDrawSubItem(LV, Item, yo, StrToFloatDef(Item.SubItems[i - 1], 0), 100, 0, True);endelsebegin//Dibuja el texto de SubItemInflateRect(Rect, -2, -2);if i - 1 <= Item.SubItems.Count - 1 thenDrawText(LV.Canvas.Handle, PCHAR(Item.SubItems[i - 1]), Longitud (Item.SubItems[i - 1]), Rect, DT_VCENTER o DT_SINGLELINE o DT_END_ELLIPSIS o TextFormat);end;end;end; //end caseend; //end forLV.Canvas.Brush.Color := clWhite;if Item.Selected entonces //Dibuja el contorno de la barra seleccionada comienza si cdsFocused en Estado entonces/ /Si el control está activo LV.Canvas.Brush.Color := $00DAA07A // $00E2B598; //clHighlight;elseLV.Canvas.Brush.Color := $00E2B598; //$00DAA07A // clHighlight;LV.Canvas.FrameRect(BoundRect); //end;DefaultDraw := False //No dejar que el sistema dibuje con Sender.Canvas doif Assigned(Font.OnChange) luegoFont.OnChange(Font);end;función TForm1.ReDrawItem(HwndLV: HWND; ItemIndex: entero): boolean;beginResult := ListView_RedrawItems(HwndLV, ItemIndex, ItemIndex);end;procedimiento TForm1.btn1Click(Sender: TObject);varItem: TListItem;begin//Uso: elemento: = LV1.Items[1];if Item = nil thenExit;item.subitems[1] := '30'; //Establecer en 30%//Luego actualice este elementoReDrawItem(LV1.handle, Item.Index);end;procedure TForm1.trckbr1Change(Remitente: TObject);varItem: TListItem;begin//Uso: elemento := LV1.Items[0];item.subitems[1] := IntToStr(trckbr1.Position);// Luego actualice este elementoReDrawItem(LV1.handle, Item.Index);end;end object Form1: TForm1Left = 416Top = 301Width. = 494Altura = 170Título = 'Forma1'Color = clBtnFaceFont.Charset = DEFAULT_CHARSETFont.Color = clWindowTextFont.Height = -11Font.Name = 'MS Sans Serif'Font.Style = []OldCreateOrder = FalsePixelsPerInch = 96TextHeight = 13object btn1: TButtonLeft = 272Top = 96Width = 75Alto = 25Caption = 'btn1'TabOrder = 0OnClick = btn1Clickendobject lv1: TListViewLeft = 16Top = 8Ancho = 457Alto = 81Columnas = <itemCaption = 'Nombre'Ancho = 100enditemCaption = 'Categoría'Ancho = 100enditemCaption = 'Progreso'Ancho = 100enditemCaption = 'Recurso'Ancho = 100end>GridLines = TrueItems.Data = {5B000000020000000200000000000000FFFFFFFF02000000000000006B4F3B8BBCECC04D3CECFB70333354D01000000F FFFFFFFFFFFFFFF020000000000000008446F7461B4ABC6E604D3CECFB7043130304DFFFFFFFFFFFFFFFF}Mostrar áreas de trabajo il1: TImageListLeft = 384Top = 96Mapa de bits = {