I had also the same problem in Delphi 2007,
with a TEdit placed in a modal form called by double-clicking in a Grid.
I made some tests launching the same Form from a TSpeedButton.
I noticed that the problem with the TEdit appears only when the grid is focused.
after more tests the problem appears to be a bug in the VCL.
in TCustomGrid.paint there is a Call of SetCaretPos, even if the grid is not on an active Form.
../..
Focused := IsActiveControl;
if Focused and (CurRow = Row) and (CurCol = Col) then
begin
SetCaretPos(Where.Left, Where.Top);
Include(DrawState, gdFocused);
end;
../..
the code above is from TCustomGrid.paint in Grids.pas
in this code, Focused is set to true if the grid is the "activeControl" of the parent form, the code don't take into account if the form is active or not.
then, if the grid need to be repaint, setCaretPos is called with grid coordinates, causing the bug mentioned in the question.
The bug is very difficult to notice because, most of the times, the caret simply disappear from the active form instead of blinking near the middle of a TEdit.
steps to reproduce the bug :
- start new VCL form app.
- add TStringGrid into it.
- add a second form to the app with just a TEdit in it.
- return in main form (unit1) and call form2.showmodal from the grid DblClick event.
that's all : you can launch the application and double click on a grid cell.
if you drag the modal form away of the main form, the grid will need to be repaint, then causing the caret to disappear from the modal form (or to appear in the middle of the TEdit if you are very lucky)
So, I think a fix is needed in Grids.pas.
in the excerpt of grid.pas above, I suggest replacing the call of the function IsActiveControl by a call of a new function called IsFocusedControl :
// new function introduced to fix a bug
// this function is a duplicate of the function IsActiveControl
// with a minor modification (see comment)
function TCustomGrid.IsFocusedControl: Boolean;
var
H: Hwnd;
ParentForm: TCustomForm;
begin
Result := False;
ParentForm := GetParentForm(Self);
if Assigned(ParentForm) then
begin
if (ParentForm.ActiveControl = Self) then
//Result := True; // removed by DamienD
Result := ParentForm.Active; // added by DamienD
end
else
begin
H := GetFocus;
while IsWindow(H) and (Result = False) do
begin
if H = WindowHandle then
Result := True
else
H := GetParent(H);
end;
end;
end;
this fix (made in Delphi2007) worked well for me, but is not garanteed.
(also, do not modify directly units of the VCL).