Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

possible bug in Delphi's drag and drop implementation?

62 views
Skip to first unread message

djsm...@pacbell.net

unread,
Sep 30, 2003, 8:24:44 PM9/30/03
to
I'm Running D6 over Win98SE with both Delphi
updates applied.

I have a stringGrid based component that I drag
onto from a DBGrid based
component. OnDragDrop causes a secondary edit form to
popup (Form.ShowModal)
with a memo field pre-filled with text from the drag
source (a field from
the DBGrid-like component). So far so good.

Now, while the secondary form is
showing, if I do any dragging and dropping between
components on this form,
when I exit the form, I get a hard crash (sometimes
two) that takes down the primary
form too. The only consistent thing between crash
scenarios is :

1) I have created the secondary form from a drag and
drop operation (dragging over from the DBGrid as
described).

2) I do a drag and drop operation in the secondary
form between any
components, not necessarily the one that had the text
placed into it by the
previous drag operation.

I also have different problems based on whether I
click "OK" or "Cancel"
on my secondary form.

Clicking "OK", I see the error message "Invalid
pointer operation"

Clicking "Cancel", I see the hard crash.

Without supplying pages of code, I'm thinking that
the drag operation has left a
dangling pointer that needs to be cleared. Is this a
known problem in
Delphi's Drag and Drop implementation, perhaps under
certain conditions
(like a secondary form being opened and closed)? I
have done quite a bit of debugging to eliminate any
obvious errors and programmer stupidity (I think). has
anyone seen this kind of thing?

Thanks for any help.

Dave

Florent Ouchet

unread,
Oct 1, 2003, 2:29:29 AM10/1/03
to
Hi,

Do you have freeandnil the second form?

Do you have a reference to any form that is not nil after the instance
destruction?

How do you declare the second form : local variable, global variable or
property of the first form?

Regards,

Florent

<djsm...@pacbell.net> a écrit dans le message de
news:3f7a1ec9$1...@newsgroups.borland.com...

djsm...@pacbell.net

unread,
Oct 1, 2003, 3:01:35 PM10/1/03
to
The secondary form is declared as a Global variable (Delphi's default
declaration for a form that remains in memory). The secondary form is not
created or destroyed at runtime, just ShowModal and hides when ShowModal
returns. I'm not sure what you mean by the second question.. Referencing
from where?

I can't reproduce this problem with a very simple project yet.. the real
project is pretty complex. So far I have discovered that the invalid pointer
crash ocurrs rigtht after the DoDrag event returns which is after the
secondary form closes of course since it is a ShowModal from within the
OnDragDrop.


"Florent Ouchet" <florent...@supelec.fr> wrote in message
news:3f7a7521$1...@newsgroups.borland.com...

djsm...@pacbell.net

unread,
Oct 1, 2003, 4:29:33 PM10/1/03
to
Okay. I have created a very simplified project that does exhibit the same
crash symptoms. It uses all Borland basic components and two forms.

To reproduce:

Create a project, add unit1 and unit2 to it (save the two dfm files as
unit1.dfm and unit2.dfm first in project directory). Make unit1 the
mainForm. The other autoloads into memory as well.

1) Ctrl drag from the edit component over to Memo on mainform

2) the secondary form will automatically popup with the dragged text loaded
into the 2nd forms Memo.

3) drag from the 2nd forms edit control over to memo and the text of the
Memo will be replaced.

4) click on OK or Cancel, either will give a general protection fault. Also,
you get GPF by closing the form from the x on the corner

If you have a clue as to why this is happening, I would be grateful. The
project files are included plus dfm files to reproduce the forms.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, Richedit, ActiveX, ComObj, RxRichEd,
DBRichEd, CSrxDBRichEdit, CSrxrichEdit, Menus;

type
TForm1 = class(TForm)
StatusBar: TStatusBar;
OlePup: TPopupMenu;
Appointment1: TMenuItem;
oDo1: TMenuItem;
Edit1: TEdit;
Editor: TMemo;
procedure Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure editorDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure editorDragDrop(Sender, Source: TObject; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
If SSCtrl in Shift Then Edit1.BeginDrag(false);
end;

procedure TForm1.editorDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := true;
end;

procedure TForm1.editorDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
If Source is TEdit Then
begin
Editor.Lines.Text := (Source as TEdit).Text;
Form2.Editor.Lines.Text := (Source as TEdit).Text;
end;
If Form2.ShowModal = mrOK Then
begin
Editor.Lines.Text := Form2.Editor.Lines.Text;
end;
end;

end.


object Form2: TForm2
Left = 536
Top = 221
Width = 402
Height = 382
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Edit1: TEdit
Left = 48
Top = 24
Width = 121
Height = 21
TabOrder = 0
Text = 'Blado Puptate'
OnMouseDown = Edit1MouseDown
end
object OKB: TButton
Left = 200
Top = 32
Width = 75
Height = 25
Caption = 'OK'
TabOrder = 1
OnClick = OKBClick
end
object Editor: TMemo
Left = 48
Top = 96
Width = 289
Height = 169
Lines.Strings = (
'Editor')
TabOrder = 2
OnDragDrop = EditorDragDrop
OnDragOver = EditorDragOver
end
object CancelB: TButton
Left = 296
Top = 32
Width = 75
Height = 25
Caption = 'Cancel'
TabOrder = 3
OnClick = CancelBClick
end
end


unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, RxRichEd, CSrxrichEdit;

type
TForm2 = class(TForm)
Edit1: TEdit;
OKB: TButton;
Editor: TMemo;
CancelB: TButton;
procedure Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure EditorDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure EditorDragDrop(Sender, Source: TObject; X,
Y: Integer);
procedure OKBClick(Sender: TObject);
procedure CancelBClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
If ssCtrl in Shift Then Edit1.BeginDrag(false);
end;

procedure TForm2.EditorDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := true;
end;

procedure TForm2.EditorDragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
If Source is TEdit Then Editor.Lines.Text := Edit1.Text;
end;

procedure TForm2.OKBClick(Sender: TObject);
begin
ModalResult := mrOK;
end;

procedure TForm2.CancelBClick(Sender: TObject);
begin
ModalResult := mrCancel;
end;

end.

object Form2: TForm2
Left = 536
Top = 221
Width = 402
Height = 382
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Edit1: TEdit
Left = 48
Top = 24
Width = 121
Height = 21
TabOrder = 0
Text = 'Blado Puptate'
OnMouseDown = Edit1MouseDown
end
object OKB: TButton
Left = 200
Top = 32
Width = 75
Height = 25
Caption = 'OK'
TabOrder = 1
OnClick = OKBClick
end
object Editor: TMemo
Left = 48
Top = 96
Width = 289
Height = 169
Lines.Strings = (
'Editor')
TabOrder = 2
OnDragDrop = EditorDragDrop
OnDragOver = EditorDragOver
end
object CancelB: TButton
Left = 296
Top = 32
Width = 75
Height = 25
Caption = 'Cancel'
TabOrder = 3
OnClick = CancelBClick
end
end

djsm...@pacbell.net

unread,
Oct 1, 2003, 5:51:42 PM10/1/03
to
Hello,

I have found a workaround to this problem. Instead of calling Formshow
from within the Dragdrop event (which seems to be a no-no if you plan on
doing drag and drop within the secondary form since it loses the pointer to
the original dragDrop event and when Formshow returns and the original
dragEvent closes.. kaboom). I have posted a message to the queue where I run
the Formshow code from there and now it works fine.. If anyone needs source
code on this fix, please e-mail me.

Dave

djsm...@pacbell.net


<djsm...@pacbell.net> wrote in message
news:3f7b...@newsgroups.borland.com...

Marc Rohloff

unread,
Oct 2, 2003, 8:59:17 AM10/2/03
to
On Wed, 1 Oct 2003 19:32:45 -0700, <djsm...@pacbell.net> said ...
> Overquoting? I'm not following.
You included the whole of you rprevious message even though your comments
referred to none of it.

Basically the dragdrop mechanism uses a global object to store the
current drag object. You must make sure the first one is finished before
starting a new one. In your case if you use showmodal then the dragdrop
event is still in-process for the first object while the second drag
starts.

Using the postmessage method gives the first event handler a chance to
terminate and therefore to finish the first drag. Finding a way to show
the second form non-modally would be another way to achieve this.

DId you try calling CancelDrag before calling showmodal?

Marc

0 new messages