代码如下:var
  mypanel:TPanel;
begin
  mypanel:=TPanel.Create(StringGrid1);
  mypanel.Parent:=StringGrid1;
  mypanel.Top:=100;
  mypanel.Left:=300;
end;panel创建后,滚动条来回滚动后,会留下panel绘制后的一些残留,只能通过再次点击StringGrid里的单元格才能消除掉这些残留物。于是我采用滚动后StringGrid1.Repaint的方法,这样确实能一次性消除掉这些残留物,但问题又来了,被创建的panel并不会随着滚动条的滚动而不见,而是一直留在了当前stringgrid的相对坐标点处。
请教大家此问题的两全其美的办法。

解决方案 »

  1.   

    回bdmh,甘特图,生产排程,StringGrid的第一行是时间刻度,第一列是工序,根据工序和开工时间得到panel生成的left和top,完工时间-开工时间得到panel的width
      

  2.   

    我滴天,画甘特图用stringgrid+panel???,你真不如在form上自己画呢
      

  3.   

    StringGrid1里在某个单元格画图不好吗,为啥非要加个panel
      

  4.   

    取得滚动条滚动间距,设置panel的left和top即可。
      

  5.   

    =====
    你好。加个panel自然有很多好处。这样你可以在运行期每张生产单都可以用到panel的事件
    例如说:拖拽,双击,canvas,等等。。这只是好处之一
      

  6.   

    你好,没太懂你的意思。
    再说,stringrid里也获取不到“取得滚动条滚动间距”。
      

  7.   

      新建一个工程,上面放一个button,复制以下代码即可,看效果是否OK。
      
      unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Grids, ExtCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        StringGrid1: TStringGrid;
        procedure Button1Click(Sender: TObject);
        procedure StringGrid1MouseWheelUp(Sender: TObject; Shift: TShiftState;
          MousePos: TPoint; var Handled: Boolean);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  tmystringgrid=class(tstringgrid)
      private
        procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
        procedure test(sender:tobject);
      end;var
      Form1: TForm1;
      mystringgrid:tmystringgrid;
      x:tpanel;
      flag:integer;
    implementation{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);
    begin
      mystringgrid:=tmystringgrid.Create(form1);
      mystringgrid.Parent:=form1;
      mystringgrid.RowCount:=20;
      mystringgrid.ColCount:=20;
      mystringgrid.Width:=600;
      mystringgrid.OnTopLeftChanged:=mystringgrid.test;  x:=tpanel.create(mystringgrid);
      x.Parent:=mystringgrid;
      x.Width:=40;
      x.caption:='yes';
      x.Top:=20;
      x.Left:=20;
    end;procedure TForm1.StringGrid1MouseWheelUp(Sender: TObject;
      Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
    begin
    end;{ tmystringgrid }procedure tmystringgrid.test(sender: tobject);
    begin
      if assigned(x) then
      begin
          if flag<mystringgrid.Row then
         begin
           x.Top:=x.Top-mystringgrid.RowHeights[1];
           mystringgrid.refresh;
           flag:=mystringgrid.Row;
         end
         else if flag>mystringgrid.Row then
         begin
           x.Top:=x.Top+mystringgrid.RowHeights[1];
           mystringgrid.refresh;
           flag:=mystringgrid.Row;
         end;
      end;
    end;procedure tmystringgrid.WMVScroll(var Msg: TWMVScroll);
    begin
      // extend
    end;end.
      
      

  8.   

      有一个小地方我没有完成,就是WMVScroll这里我没写东西,所以,你用鼠标点击垂直滚轮拖动的时候,
    没有效果。可能需要你去完成了。
      思路就是那样的,兄弟应该能完成的。加油。
      
      

  9.   

    实在不行的话,加上刷新界面的的代码试试,之前遇到类似的情况,执行某个动作后,界面上有殘象,只好刷新界面,刷新的知下面3先1就可以了
    1、SystemParametersInfo(SPI_SETDESKWALLPAPER,0,nil,SPIF_SENDWININICHANGE);
    2、RedrawWindow(0,nil,0,RDW_ERASE or RDW_INVALIDATE or RDW_ALLCHILDREN);
    3、SSHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST , NiL, NiL);
      

  10.   

    回ecjtu5208,兄弟,经测试,不行仍然出现我说的那的种残留物。
    回likeyrain,哥们,经测试,也不行,这样刷新界面的效果等同于panel.repaint。
      

  11.   

    var
      GCol: Integer = 5;
      GRow: Integer = 2;
      Panel1: TPanel;procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject);
    begin
      with TStringGrid(Sender) do
      begin
        Panel1.Visible := (GCol >= LeftCol) and (GCol <= LeftCol + VisibleColCount) and
             (GRow >= TopRow) and (GRow <= TopRow + VisibleRowCount);
        Repaint;
      end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
      I: Integer;
    begin
      with StringGrid1 do
      begin
        Width := 500;
        Height := 200;
        ColCount := 20;
        RowCount := 20;
        for I := 0 to ColCount - 1 do
          Cells[I, 1] := IntToStr(I);
      end;
      Panel1 := TPanel.Create(StringGrid1);
      Panel1.Parent := StringGrid1;
    end;procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    begin
      if (ACol = GCol) and (ARow = GRow) then
        with Panel1, Rect do
          if Visible then
            SetBounds(Left, Top, Right - Left, Bottom - Top);
    end;
      

  12.   

    回sz_haitao,其实并没有什么难度
      

  13.   

      兄弟,新建一个工程,Form上加一个button,其他控件不要加,然后贴我的代码,我给的代码里有StringGrid1: TStringGrid,这个不要。
      procedure StringGrid1MouseWheelUp(Sender: TObject; Shift: TShiftState;
          MousePos: TPoint; var Handled: Boolean);
      这个也不要。
      
      然后你运行,点击button,生成mystringgrid和一个panel,你用鼠标滚轮,或者上下按钮去运行时,绝对没有残留物。
      我不知道你测试具体是干什么,但我给的代码不会出现残留。
      我知道你说的残留物,滚动条移动会有残影,但我那样写是没有残影的。
      好吧,你先别把代码加到你的程序里运行,只是先看我代码是否有残影,OK?
      

  14.   

    兄弟,你测试没发现有问题?
    1:当在水平滚动条靠最左时,向右点一下,panel会马上向下移一点点
    2:当你向右移动之后,回到最左边时,panel看不到了,你要用鼠标多选几行几列,覆盖一下panel所在的地方,panel才能再次显示出来
      

  15.   

    他这个确实不会有残留物,但单纯地直接将visible:=false;,这样不太合理,因为当移动到刚好覆盖panel一半时,这样的方法就不行了。
      

  16.   

    我只针对了垂直滚动条去除残影。
    所以我写的只有top属性加减,要水平则如法炮制。
      

  17.   

    没事,我也写得简单了点。
    关键点就是一个:top:=top+rowheight和left:=left+colwidth
    我就不继续写代码,就这么个思路,肯定不会有残影,就不继续回帖了。闪了。
    楼主加油。