1

いくつかの規則に従って、TObjectList の順序を変更する必要があります。どうすればこれを達成できますか?

したがって、ScrollBox に動的にパネルを追加します。それらを追加するときは、将来の使用のために、実行時に追加される順序で ObjectList にも追加します。次に、スクロール ボックス内のパネルをドラッグ アンド ドロップで再編成できます。ドラッグ/ドロップによって実行時に設定されるのと同じ順序を ObjectList に反映させたいと思います。

これが私のコードです:

var
  MainForm: TMainForm;
  PanelList,PanelListTMP:TObjectList;

implementation
...

procedure TMainForm.FormCreate(Sender: TObject);
begin
  PanelList:=TObjectList.Create;
  PanelListTMP:=TObjectList.Create;
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  AddPanel('0');
  AddPanel('1');
  AddPanel('2');
  AddPanel('3');
  AddPanel('4');
end;

procedure TMainForm.Addpanel(what:string);
var
  pan:TPanel;
  bv:TShape;
begin
  pan:=TPanel.Create(self);
  pan.Parent:=TheContainer;
  pan.Height:=50;
  pan.BevelOuter:=bvNone;
  pan.BorderStyle:=bsNone;
  pan.Ctl3D:=false;
  pan.Name:='LayerPan'+what;
  pan.Caption:=what;
  pan.Align:=alBottom;
  pan.OnMouseDown:=panMouseDown;
end;

procedure TMainForm.panMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
var
  i:integer;
  idu:String;
  panui:TPanel;
begin
  panui:=Sender as TPanel;
  panui.ParentColor:=false;
  panui.BringToFront;
  // DRAG DROP STUFF
  ReleaseCapture;
  panui.Perform(wm_nclbuttondown,HTCAPTION,0);

  for i := 0 to MainForm.ComponentCount - 1 do
    begin
      if MainForm.Components[i] is TWinControl then
        if TWinControl(MainForm.Components[i]) is TPanel then
        if (TWinControl(MainForm.Components[i]) as TPanel).Parent=MainForm.TheContainer then
          begin
            (TWinControl(MainForm.Components[i]) as TPanel).Align:=alBottom;
          end;
    end;
  TheContainer.ScrollInView(panui);
  ReOrderPanels;
end;


Procedure TMainForm.ReOrderPanels;
begin

end;

ReOrderPanels プロシージャで何をすればよいですか? ScrollBox のパネルを下から上に新しい TObjectList (PanelListTMP) にフィードし、PanelList をクリアして PanelListTMP から再度追加することを考えていましたが、それを行うとエラーが発生します: アクセス違反、および EInvalidPointer - 無効なポインター操作

だからこれは私が考えたことです:

procedure TMainForm.ReOrderPanels;
var
  ctrl:TControl;
  pos:TPoint;
  pan:TPanel;
  bad:boolean;
  ord,i:integer;
begin
  memo2.Lines.Add('*** new order START');
  panelListTMP.Clear;
 // scroll top
  TheContainer.VertScrollBar.Position := 0;
  // scroll down
  TheContainer.VertScrollBar.Position := TheContainer.VertScrollBar.Range;
  // get panel
  Pos:=TheContainer.ClientOrigin;
  Pos.Y:=Pos.Y+TheContainer.Height-5;
  ctrl := FindVCLWindow(pos) ;
  if ctrl is TPanel then
    if TPanel(ctrl).Parent = TheContainer then
    begin
      pan:=(ctrl as TPanel);
      panelListTMP.Add(pan);
    end;

  ord:=1;
  bad:=false;
  repeat
   repeat
       Pos.Y:=pos.Y-1;
   until (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos)<>pan);
   if (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos).Name<>'LayerPan') then
   begin
       pan:=FindVCLWindow(pos) as TPanel;
       containeru.VertScrollBar.Position := 0;
       containeru.ScrollInView(pan);
       ord:=ord+1;
       panelListTMP.Add(pan);
   end
   else
     bad:=true;
  until bad=true;

  // and now I do the swap between the ObjectLists...
  panelList.Clear;
  for i:=0 to PanelListTMP.Count-1  do
    begin
      (PanelListTMP.Items[i] as TPanel).Parent:=containeru;
      panelList.Add(PanelListTMP.Items[i]);
    end;
end;

したがって、ObjectList は実際のオブジェクトへのポインターを格納しているため、最初の ObjectList をクリアすると、実際のオブジェクトが解放されるため、2 番目の ObjectList には実行できなくなったポインターのリストが含まれていると思います...私は私が望むものを達成しますか?

したがって、ButtonClick では、次の順序でパネルを含む ObjectList を取得します。

PanelList[0] - Panel0
PanelList[1] - Panel1
PanelList[2] - Panel2
PanelList[3] - Panel3
PanelList[4] - Panel4

ScrollBox 内にパネルをドラッグ アンド ドロップした後、(ScrollBox 内で) このような順序になる可能性があります。

Panel3
panel1
Panel4
Panel2
Panel0

しかし、ObjectList では、順序は以前と同じです...

繰り返しますが、scrollBox からのパネルの順序に従って ObjectList を順序付けできるようにしたいと考えています。再注文手順では、実際にすべてのパネルを希望の順序で取得します。ObjectList で同じ順序にする必要があるだけです。

これを行う他の方法はありますか?他に、TPanel の横にインデックスを保持し、それを ObjectList で使用して順序を維持する新しいクラスを作成しますか?

4

2 に答える 2

0

I think I found my answer using a temporary ObjectList and Extract(Object)

My code that seems to work is:

procedure TMainForm.ReOrderPanels;
var
  ctrl:TControl;
  pos:TPoint;
  pan,panx:TPanel;
  bad:boolean;
  ord,i:integer;
begin

    panelListTMP.Clear;
    panelList.OwnsObjects:=false;

 // scroll top
  TheContainer.VertScrollBar.Position := 0;
  // scroll down
  TheContainer.VertScrollBar.Position := TheContainer.VertScrollBar.Range;
  // get panel
  Pos:=TheContainer.ClientOrigin;
  Pos.Y:=Pos.Y+TheContainer.Height-5;
  ctrl := FindVCLWindow(pos) ;
  if ctrl is TPanel then
    if TPanel(ctrl).Parent = TheContainer then
    begin
      pan:=(ctrl as TPanel);
      panelListTMP.Add(PanelList.Extract(pan) as TPanel);
    end;

  ord:=1;
  bad:=false;
  repeat
   repeat
   Pos.Y:=pos.Y-1;
   until (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos)<>pan);
   if (FindVCLWindow(pos) is TPanel)and(FindVCLWindow(pos).Name<>'LayerPan') then
   begin
       pan:=FindVCLWindow(pos) as TPanel;
       TheContainer.VertScrollBar.Position := 0;
       TheContainer.ScrollInView(pan);
       ord:=ord+1;
       panelListTMP.Add(PanelList.Extract(pan) as TPanel);
   end
   else
     bad:=true;
  until bad=true;
  panelList.Clear;
  panelListTMP.OwnsObjects:=false;

  i:=0;
  while (PanelListTMP.Count<>0) do
      panelList.Add(PanelListTMP.Extract(PanelListTMP.Items[i])  as TPanel);

  panelList.OwnsObjects:=true;
  panelListTmp.Clear;
end;
于 2015-07-21T23:09:53.417 に答える