Dragdrop

Delphi

08/03/2005

Bom Dia,

Estou com um pouco de dificuldade na implementação de um gerador de relatorios. Este gerador é construido utilizando o quickreport porem o mesmo deve ter a possibilidade de selecionar varios componentes, redimensiona-los e arrasta-los. A minha maior dificuldade é justamente implementar os recursos de arrastar e soltar com mais de um componente selecionado usando o dragdrop, alquem conhece uma forma mais pratica de se executar está ação. Não posso simplesmente alterar as propriedades left, top dos meus componentes pois isto faz a tela piscar.

Para produzir o efeito de seleção dos objetos estou desenhndo varios paineis pintados de preto ao redor dos componentes selecionados. Alquem conhece uma maneira mais elegante de fazer isto tambem?


Leads

Leads

Curtidas 0

Respostas

Marcelo Saviski

Marcelo Saviski

08/03/2005

Pra não piscar, talvez vc pudesse fazer assim:

desenhar um retângulo na nova posição aonde o compoennte vai estar, e ó mudar o left e top depois que soltar o mouse, tipo usando essa função que copiei da RxLib, unit VclUtils

procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer);
var
  DC: HDC;
  I: Integer;
begin
  DC := GetDC(0);
  try
    for I := 1 to Width do begin
      DrawFocusRect(DC, ScreenRect);
      InflateRect(ScreenRect, -1, -1);
    end;
  finally
    ReleaseDC(0, DC);
  end;
end;


no onmousedown, vc armazenaria a posição e tamanho dos componentes

var
  Rects: array of TPoint;
  HotSpot: TPoint


no MouseDown, salvaria o tamanho dos componentes selecionados:

SetLength(Rects, NumCompsSelecionado)
HotSpot := Point(X, Y);
for ...   //faz um for em todos os comps selecionados
  with ComponenteSelecionado[X] do
  begin    
    Rects[I] := BoundsRect;
    Rects[I].TopLeft := ClientToScreen(Rects[I].TopLeft);
    Rects[I].BottomRight := ClientToScreen(Rects[I].BottomRight);
    DrawInvertFrame(Rects[I], 3);
  end;

end;

depois no MouseMove, vc movimenta os valores do array pos, mas não move os componentes, e chama o DrawInvertFrame pra desenhar um retângulo na tela, no lugar para onde os componentes estariam sendo movidos:

if ssLeft in Shift then // se o botão esquerdo do mouse está pressionado
  for I :- Low(Rects) to High(Rects) do
  begin  
    DrawInvertFrame(Rects[I], 3);
    //move de acordo com a posição do mouse
    Rects[I].Left := Rects[I].Left + X - HotSpot.X;
    Rects[I].Right:= Rects[I].Right+ X - HotSpot.X;
    Rects[I].Top := Rects[I].Top + X - HotSpot.X;
    Rects[I].Bottom := Rects[I].Bottom + X - HotSpot.X;
    DrawInvertFrame(Rects[I], 3);
  end;


o DrawInvertFrame inverte as bordas do retangulo passado como parametro, então depois tem que inverter denovo pra voltar ao normal, que é feito no 1º no MouseMove

e no MouseUp, tem que pegar os novos valores do array rects e passar para os componentes:

for I :- Low(Rects) to High(Rects) do
  with Rects[I] do
    ComponentesSelecionados[I].SetBounds(Left, Top, Right - Left, Bottom - Top);


Não garanto que isso irá funcionar já de 1º :) :P , eu não testei, escrevi o código no fórum mesmo, então teste e diga se conseguiu fazer funcionar.

acho que isso não resolve todo o seu problema, mas assim não pisca e da uma cara melhor.


GOSTEI 0
POSTAR