La mia applicazione compilata con Delphi 2007 ha un trascinamento tra le griglie e funziona bene la maggior parte del tempo. Ma a volte casualmente ho avuto violazione di accesso. Ho eseguito il debug sul metodo Controls.pas DragTo in VCL.Bug in Delphi VCL Drag and Drop?
Comincia così:
begin
if (ActiveDrag <> dopNone) or (Abs(DragStartPos.X - Pos.X) >= DragThreshold) or
(Abs(DragStartPos.Y - Pos.Y) >= DragThreshold) then
begin
Target := DragFindTarget(Pos, TargetHandle, DragControl.DragKind, DragControl);
L'eccezione avviene nell'ultima riga perché DragControl è nullo. DragControl è una variabile globale di tipo TControl. Ho provato a correggere questo metodo con un assigncheck e chiamare CancelDrag se DragControl = nil, ma fallisce anche perché DragObject è anche nullo.
procedure CancelDrag;
begin
if DragObject <> nil then DragDone(False);
DragControl := nil;
end;
Per scoprire perché DragControl è nil, ho ispezionato DragInitControl. Ci sono 2 righe che escono solo se DragControl è nullo.
procedure DragInitControl(Control: TControl; Immediate: Boolean; Threshold: Integer);
var
DragObject: TDragObject;
StartPos: TPoint;
begin
DragControl := Control;
try
DragObject := nil;
DragInternalObject := False;
if Control.FDragKind = dkDrag then
begin
Control.DoStartDrag(DragObject);
if DragControl = nil then Exit;
if DragObject = nil then
begin
DragObject := TDragControlObjectEx.Create(Control);
DragInternalObject := True;
end
end
else
begin
Control.DoStartDock(DragObject);
if DragControl = nil then Exit;
if DragObject = nil then
begin
DragObject := TDragDockObjectEx.Create(Control);
DragInternalObject := True;
end;
with TDragDockObject(DragObject) do
begin
if Control is TWinControl then
GetWindowRect(TWinControl(Control).Handle, FDockRect)
else
begin
if (Control.Parent = nil) and not (Control is TWinControl) then
begin
GetCursorPos(StartPos);
FDockRect.TopLeft := StartPos;
end
else
FDockRect.TopLeft := Control.ClientToScreen(Point(0, 0));
FDockRect.BottomRight := Point(FDockRect.Left + Control.Width,
FDockRect.Top + Control.Height);
end;
FEraseDockRect := FDockRect;
end;
end;
DragInit(DragObject, Immediate, Threshold);
except
DragControl := nil;
raise;
end;
end;
Potrebbe essere la ragione ... Quindi la mia domanda.
- Qualcuno ha avuto problemi simili con il trascinamento della selezione?
- Se rilevo DragControl = nil come posso annullare il trascinamento corrente?
Edit: Attualmente ho alcuna soluzione a questo, ma posso aggiungere un po 'di informazioni su di esso. Le griglie si chiamano supergrid. Questo è un componente interno che abbiamo sviluppato per soddisfare le nostre esigenze. Eredita TcxGrid da Devexpress. Penso (ma non sono sicuro) che questo problema si presenti quando l'utente trascina una riga della griglia nello stesso momento in cui la griglia ricarica i dati. In qualche modo il riferimento alla riga corrente diventa nullo. A lungo termine abbiamo in programma di sostituire questa supergrid con una griglia Bold (come usiamo Bold for Delphi) che eredita anche da TcxGrid. Quindi la griglia viene aggiornata non appena i dati vengono modificati (nessun aggiornamento da parte dell'utente o nel codice) e si spera che questo risolva il problema.
Hai considerato l'interazione con le estensioni della Shell? Ho affrontato problemi simili usando TOpenDialog. – menjaraz
Ottima domanda. Non ho esperienza nell'uso del trascinamento della selezione VCL da controllo a controllo, ma se dovessi farlo, proverei il codice di A. Melander invece di VCL per questo argomento e vedrò se c'è una demo e alcuni inserisci qui più solido; http://melander.dk/delphi/dragdrop/ –
Ho avuto problemi simili con il trascinamento della selezione (anche delphi 2007). ma stranamente questo tipo di problema compare solo (e frequentemente) quando si esegue il programma da remoto con "netviewer". – DamienD