如何在Delphi中用滚动条求网格构件的实际宽度

如何在Delphi中用滚动条求网格构件的实际宽度,delphi,datagridview,scrollbar,width,dbgrid,Delphi,Datagridview,Scrollbar,Width,Dbgrid,我有一个网格组件(DBGrid),上面有很多列。因为有大量的列,所以创建了一个滚动条,因此网格的某些部分仍然是隐藏的。我需要找出DBGrid的实际宽度,包括由于滚动条而未显示的部分。但是Width属性只提供组件本身的宽度。有人知道吗?TDBGrid有一个列属性。每列都有自己的宽度属性。因此,您可以循环遍历所有列并总结它们的宽度 像这样: function TotalColumnsWidth(var AGrid: TDBGrid); var i: Integer; begin Result

我有一个网格组件(DBGrid),上面有很多列。因为有大量的列,所以创建了一个滚动条,因此网格的某些部分仍然是隐藏的。我需要找出DBGrid的实际宽度,包括由于滚动条而未显示的部分。但是Width属性只提供组件本身的宽度。有人知道吗?

TDBGrid
有一个
属性。每列都有自己的
宽度
属性。因此,您可以循环遍历所有列并总结它们的宽度

像这样:

function TotalColumnsWidth(var AGrid: TDBGrid);
var
  i: Integer;
begin
  Result := 0;
  for i := to AGrid.Columns.Count - 1 do
    Result := Result + AGrid.Columns[i].Width;
end;

我想我已经找到了一个解决办法(尽管看起来有点奇怪)。为了找到DBgrid的列宽和实际宽度之间的差异(这意味着找到最后一列之后剩余的空白空间的宽度),我们需要跟踪左侧现在显示的列(滚动到的当前列是什么)。我们可以使用OnDrawColumnCell事件来实现这一点,因为它将只绘制现在滚动的列。然后我们需要计算所有可见列的宽度之和,并从DBGrid的宽度中减去它。顺便说一句,很抱歉英语不好

Ex代码:

     For i:=0 to Last do
     if Vis[i] then
     Begin
      Sum:=Sum+DBG.Columns[i].Width;
      Inc(Cnt);
     End;

     if dgColLines in DBG.Options then
     Sum := Sum + Cnt;

  //add indicator column width
    if dgIndicator in DBG.Options then
    Sum := Sum + IndicatorWidth;
    Dif:=DBG.ClientWidth - Sum;

以下是我们过去使用过的函数。它考虑了基于字体的数据宽度,还补偿了可见的垂直线

function GridTextWidth(fntFont : TFont; const sString : OpenString) :
  integer;
var
  f: TForm;
begin
  try
    f:=TForm.Create(nil);
    f.Font:=fntFont;
    result:=f.canvas.textwidth(sstring);
  finally
    f.Free;
    end;
end;




function CalcGridWidth(dbg : TDBGrid { the grid to meaure }): integer; { the "exact" width }
const cMEASURE_CHAR   = '0';
      iEXTRA_COL_PIX  = 4;
      iINDICATOR_WIDE = 11;
var i, iColumns, iColWidth, iTitleWidth, iCharWidth : integer;
begin
  iColumns := 0;
  result   := GetSystemMetrics(SM_CXVSCROLL);

  iCharWidth := GridTextWidth(dbg.font,cMeasure_char);

  with dbg.dataSource.dataSet do begin
    DisableControls;
    for i := 0 to FieldCount - 1 do with Fields[i] do
      if visible then
      begin
        iColWidth := iCharWidth * DisplayWidth;
        if dgTitles in dbg.Options then begin
          ititlewidth:=GridTextWidth(dbg.titlefont,displaylabel);
          if iColWidth < iTitleWidth then
            iColWidth := iTitleWidth;
        end;
        inc(iColumns, 1);
        inc(result, iColWidth + iEXTRA_COL_PIX);
      end;
      EnableControls;
    end;

  if dgIndicator in dbg.Options then
  begin
    inc(iColumns, 1);
    inc(result, iINDICATOR_WIDE);
  end;
  if dgColLines in dbg.Options then
    inc(result, iColumns)
  else
    inc(result, 1);
end;
函数GridTextWidth(fntFont:TFont;const sString:OpenString):
整数;
变量
f:TForm;
开始
尝试
f:=TForm.Create(无);
f、 字体:=fntFont;
结果:=f.canvas.textwidth(sstring);
最后
f、 免费的;
结束;
结束;
函数CalcGridWidth(dbg:TDBGrid{网格到测量}):整数;{“精确”宽度}
常量cMEASURE_CHAR='0';
iEXTRA_COL_PIX=4;
指示器的宽度=11;
变量i、iColumns、iColWidth、iTitleWidth、iCharWidth:整数;
开始
iColumns:=0;
结果:=GetSystemMetrics(SM_CXVSCROLL);
iCharWidth:=GridTextWidth(dbg.font,cMeasure_char);
使用dbg.dataSource.dataSet开始
禁用控制;
对于i:=0到FieldCount-1,使用字段[i]do
如果可见,则
开始
iColWidth:=iCharWidth*DisplayWidth;
如果在dbg.Options中有dgTitles,则开始
ititlewidth:=GridTextWidth(dbg.titlefont,displaylabel);
如果iColWidth
也许这会有所帮助。它是TDBGrid类帮助程序的一部分,该类帮助程序自动调整最后一列的大小,从而使网格没有空空间。应该很容易适应你的需要

正如您可能注意到的,CalcDrawInfo方法正是您所寻求的。由于它是受保护的,所以您可以使用类助手或常用的受保护的黑客来获得它

procedure TDbGridHelper.AutoSizeLastColumn;
var
  DrawInfo: TGridDrawInfo;
  ColNo: Integer;
begin
  ColNo := ColCount - 1;
  CalcDrawInfo(DrawInfo);
  if (DrawInfo.Horz.LastFullVisibleCell < ColNo - 1) then Exit;

  if (DrawInfo.Horz.LastFullVisibleCell < ColNo) then
    ColWidths[ColNo] := DrawInfo.Horz.GridBoundary - DrawInfo.Horz.FullVisBoundary
  else
    ColWidths[ColNo] := ColWidths[ColNo] + DrawInfo.Horz.GridExtent - DrawInfo.Horz.FullVisBoundary
end;
过程TDbGridHelper.AutoSizeLastColumn;
变量
DrawInfo:TGridDrawInfo;
ColNo:整数;
开始
ColNo:=ColCount-1;
CalcDrawInfo(DrawInfo);
如果(DrawInfo.Horz.LastFullVisibleCell
只有在数据网格末尾没有空空间的情况下才有效,这意味着只有列占用了所有空间时才有效。实际上,我需要它的真正原因正是这个问题。我想去掉列后的空白,但不知道如何找到(“DBGrid的宽度”-“列的宽度”)@Tofig,但只有当列的宽度小于DBGrid的宽度时,空白才可见?是否要调整列的大小,使其具有其所有所有者(DBGrid)的宽度?“只有当列的宽度小于DBGrid的宽度时,才会显示空白”-实际上,DBGrid仍然可以有空白,即使列比DBGrid宽。通常在运行时调整列的大小时会发生这种情况。它仍然不计算最后一列之后剩余的空白。有办法在这里张贴照片吗?我会显示困扰我的空白区域。我不太明白,从哪里可以获得此方法:“CalcDrawInfo”?如果我只是将这段代码复制到程序中,编译器就不会识别它。忽略这一点,我没有注意到它受到了保护。它真的起作用了!非常感谢:我也有这个问题,但是我使用C++ Builder XE而不是Delphi。你能告诉我如何在C++ Builder XE中使用这个过程吗?请帮帮我:(