The Delphi Bug List

Visual Component Library (VCL)

Win32


The color codes indicate in which version(s) of Delphi the bug occurs and what its status is.
Latest update: 27 December 1998
Bug # Delphi versions Description
37 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TCustomListView
See TListView
38 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDateTimePicker
Problems with Year=00..09 and with property MinDate
39 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDateTimePicker
The TDateTimePicker component in Delphi 3.0 has no TabOrder property
40 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDateTimePicker
If you choose any date of the year 1899 or backwards, the day that you chose is incremented by one.
469 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TDateTimePicker
Can't get the TDateTimePicker.OnUserInput event to fire.
47 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 THeaderControl
Using a THeaderControl you cannot change the color of the font but you can change everything else about the font. (Maybe black is a standard but why not the font NOT being bold or italic etc). Please read the comments from Martin Scott on this.
49 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TImageList
TImageLists in form templates are not loaded properly in inherited forms.
50 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TImageList
TImageList drag & drop does not finish
57 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TListItem/TListView
If the EditCaption method is called when the list view is not focused, the in-place editing does not take place.
58 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TListItem/TTreeView
There is a bug in TListView and TTreeView concerning drag & drop operations.
59 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TListItem/TTreeView
The bug in TListView and TTreeView concerning drag & drop operations. can also be fixed by fixing TCustomListView.Delete.
409 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TListView
If you select an item (in code) which is not visible, the TListView does not scroll that item into view.
443 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TListView
When you add an item to a ListView which has checkboxes, all checkboxes are cleared.
480 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TPageControl
TPageControl's Tabsheets do not respond to accelerator keys
75 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
The default value of zero for the MaxLength property limits the number of characters to 65536, while the Help promises 'no limit'. Setting it to a high number (e.g. 200000000) works as expected.
76 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
In some cases when loading RTF files into TRichEdit, FirstIndents of paragraphs disappear or display incorrectly
77 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
Exception or wrong return value on EM_POSFROMCHAR message.
78 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
After resizing (enlarging), part of the client area will not be painted anymore. This seems to occur under NT 3.51 only.
79 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
TRichEdit.Visible := False fails if the RichEdit contains text at design-time
80 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TRichEdit
Documentation bug: the PageRect property contains co-ordinates in pixels, not twips
83 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TStatusBar
TStatusBar seems to ignore color changes in the font (both at design time and at run time.
84 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TStatusBar
Setting Bevel to None does not redraw the control immediatly
474 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TToolBar
The TToolButton.Visible property is not persisted between sessions. Specifically, it gets reset back to "True" when a project gets reloaded.
482 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TToolBar
Captions of buttons on TToolBar don't get the ToolBar's font color
93 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TToolBar/TToolButton
Buttons classes derived from TToolButton don't display properly on a TToolBar.
94 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TToolBar/TToolButton
A button on a TToolBar disabled in the parent form's OnCreate event causes all the toolbar buttons to be invisible
95 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
DoEndDrag in TTreeView does not seem to be executed.
96 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
Having nodes that are wider than the window may cause nasty problems
97 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
The Help button does nothing.
98 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
You cannot change the color of the font.
Please read the comments from Martin Scott on this.
99 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
If you change 'Color' property (background) to anything besides white you will see that the text background is ALWAYS white.
100 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
Bug when editing the Items
101 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
Bug in MoveTo method
Only occurred in Delphi 2.0
487 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView
The TTreeNode.MoveTo procedure does not work if you specify naAddChild or naAddChildFirst.
404 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 TTreeView/TListView
TTreeView's OnDeletion event occurs "too late": it may occur AFTER form's OnDestroy

Bug #38; last modified: 25-Oct-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A N/A Unknown Unknown Unknown Unknown Fixed Fixed
Win32 - TDateTimePicker

Problems with Year=00..09 and with property MinDate

Description
Reported by ... Meade; confirmed by Chuck Garvey
Meade:
Has anyone tried TDateTimePicker? Have they tried typing in a year between 00 and 09 and then clicking the down button? If you haven't, I'm not sure I would recommend doing it. The subclassed control continues to generate a datetimechange event until you run out of stack. Not very pleasant.

Chuck Garvey:
Meade is correct. I have the same problem. I also have a problem with the MinDate property of this component. It returns an error whenever I enter a year other than 12/31/99. HELP!!


Bug #39; last modified: 25-Oct-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A N/A Exists Unknown Unknown Fixed Fixed Fixed
Win32 - TDateTimePicker

The TDateTimePicker component in Delphi 3.0 has no TabOrder property

Description
Reported by Raf Paredis; checked by Arjen Broeze
The TDateTimePicker component in Delphi 3.0 has no TabOrder property. It seems that Borland has made a glitch.
Solution / workaround
Code fixes:
If you have the source-code for the VCL, you can modify the declaration of the TDateTimePicker component. You'll have to add the following line in the published section of the class declaration:
property TabOrder;
Alternatively you can create a new component derived from TDateTimePicker:
type
  TDateTimePicker2 = class(TDateTimePicker)
  published
    property TabOrder;
  end;

Bug #40; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A N/A Exists Exists Unknown Unknown Unknown Unknown
Win32 - TDateTimePicker

If you choose any date of the year 1899 or backwards, the day that you chose is incremented by one.

Description
Reported by Jean Carlos; checked by Glenn Crouch
Comment from checker:
This bug is reproducible both using Long and Short Dates (I thought the problem might only be when using 2 digit years).
Using the DateTimePicker control inside Outlook Express (part of IE4) which uses the same COMCTL32.DLL calls, the problem is not there.
I believe that there is enough evidence to suggest that this is a Delphi Bug, relating to how Borland converts the DateTimePicker's Date into Delphi's TDateTime for TDateTime values < 0. Anything prior to December 30, 1899 is one day out...
Solution / workaround
The following seems to fix everything except December 29, 1899 which we have no way of distinguishing from December 30, 1899 :-[
procedure TForm1.DateTimePicker1CloseUp(Sender: TObject);
begin
  if DateTimePicker1.Date < -1.0 then
    DateTimePicker1.Date := DateTimePicker1.Date - 1;
end;

Bug #469; last modified: 27-Dec-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A N/A Exists Exists Exists Exists Exists Exists
Win32 - TDateTimePicker

Can't get the TDateTimePicker.OnUserInput event to fire.

Description
Reported by Anthony Steele; checked by Erik Berry
Problem: I cannot get the TDateTimePicker.OnUserInput event to fire. The documentation says that "If ParseInput is True, the OnUserInput event occurs whenever the user types into the component's edit box."

To reproduce the bug

  1. File | new application
  2. drop a TDateTimePicker control on the form
  3. Set the control's "ParseInput" property to true. Other properties stay at the default values (DateFormat = dfShort, dateMode=dmComboBox)
  4. Put an event handler on the control's "onUserInput" event - any code, so long as you can put a breakpoint on it.
  5. Run the project, play with the control and your breakpoint will never be hit unless you
    a) have a 2-digit year set in the control panel.
    b) Click the calendar button directly after typing your changes.
The OnUserInput event should "occur when the user types directly into the TDateTimePicker", not just under very special circumstances.

Bug #49; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Exists Unknown Unknown Unknown Unknown Unknown Unknown
Win32 - TImageList

TImageLists in form templates are not loaded properly in inherited forms.

Description
Reported by Katy Mulvey
If you are using inherited forms, the parent form contains a TImageList, and the TImageList contains images at design-time, the images will be added multiple times at run-time.

My first sign that something was wrong was when I noticed that the TImageList in the inherited form had extra images in it. This behavior couldn't be reproduced.

For example:
If you have a parent form with a TImageList containing 10 images, at run-time, the child form that inherits from this form will have 20 images.

Solution / workaround
1. Don't inherit from a form in the repository that contain a TImageList. (Copy or Use it instead).
2. Leave TImageLists empty at design-time, and load them from a .RES file or .DLL at run-time.

Bug #50; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Exists Exists Unknown Unknown Unknown Unknown Unknown
Win32 - TImageList

TImageList drag & drop does not finish

Description
Reported by Chris Rankin, confirmed by Stefan Hoffmeister
When dragging multiple icons from a TImageList, the drag & drop operation does not finish properly.
Using Delphi 2.01 or Delphi 3 (5.53), create a new project, and drop a TImageList, a TListView and a TButton on a form.
Set the ListView's properties as follows:

DragMode := dmAutomatic
LargeImages := ImageList1
MultiSelect := True (very important!)
ViewStyle := vsIcon (that is the default)

Add the following code to the Button's OnClick handler:

procedure TForm1.Button1Click(Sender: TObject);
var
  NewItem: TListItem;
begin
  NewItem := ListView1.Items.Add;
  NewItem.Caption := 'Item!';
  NewItem.ImageIndex := ImageList1.AddIcon(Application.Icon)
end;
Now compile and run the application. Create some icons in the ListView by clicking the button several times, and then select them all (hence the MultiSelect = True). Drag them somewhere; drop them anywhere. Now click on an icon on the desktop (e.g. "My Computer") and drag that. Instead of a "My Computer" drag-cursor you will see the Delphi application icon.
Solution / workaround
By Chris Rankin
This bug can be fixed by modifying Controls.pas (both Delphi 2 and Delphi 3, 5.53):
Controls.pas:
procedure DragDone(Drop: Boolean);
var
  ...
begin
  DragSave := nil;
  DragControl := nil;
  try
    DragObject.ReleaseCapture(DragCapture);
    DragSave := DragObject;

    if DragImageList <> nil then
      DragImageList.EndDrag
    else
    begin
{$IFDEF FixImagelistDDBug}
      ImageList_EndDrag;
{$ENDIF}
      Windows.SetCursor(DragSaveCursor)
    end;

    try
      ...    
end;
A possible work around is to add a corresponding line to the TImageView's EndDrag event handler:
procedure TForm1.ListView1EndDrag(...);
begin
  ImageList_EndDrag;
end;
after manually adding "ComCtrl" to the uses clause.

Bug #57; last modified: 25-Oct-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Exists Unknown Unknown Unknown Unknown Fixed Fixed
Win32 - TListItem/TListView

If the EditCaption method is called when the list view is not focused, the in-place editing does not take place.

Description
Reported by Jani Järvinen; checked by Erik Berry
Problem example:
             ListView1.Selected.EditCaption;
The above code starts the editing only if the list view has the focus. If the method was called for example from a button OnClick handler, nothing would happen. This is true even if HideSelection is False.

I'm sorry that I cannot decide if this is a TListItem or a TListView bug: the two classes are linked too strongly to be sure. ;-) Because EditCaption is a method of TListItem, I think it should be listed as such.

Solution / workaround
Call SetFocus before calling EditCaption if focus is elsewhere. Solution example:
             ListView1.SetFocus; { set focus first }
             ListView1.Selected.EditCaption;
Please note that the current EditCaption implementation simply sends a Windows message to the list view, and thus this is not a real VCL bug. Still, this bug would be very easy to avoid, if the VCL developers would have included the SetFocus call in the implementation. 

Bug #58; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Exists Fixed Fixed Fixed Fixed Fixed Fixed
Win32 - TListItem/TTreeView

There is a bug in TListView and TTreeView concerning drag & drop operations.

Description
By Torsten Welches
Under certain circumstances this leads to crashes with TListView. This bug also applies to TTreeView, but - AFAICS - it causes no harm here.
Both TListView and TTreeView store the item which was their last drop target in a private variable called FLastDropTarget. However FLastDropTarget is not reset to nil if the referenced item is destroyed. If this happens FLastDropTarget is bogus during the next drag&drop operation and if the referenced "item" is used you have a crash. TListView does reference it, TTreeView does not.

 To reproduce the bug:

  • Put a TListView on a form. Its OnDragOver event handler should read "accept := true;"
  • Put a Button on the form which clears the ListView: "ListView1.items.clear;"
  • Add another control - let's say a TMemo and define its OnMouseDown event handler like "Memo1.BeginDrag(False);"
  • Add some items to the ListView using the ListView items editor or some code.
  • Run the program.
  • Drag your memo over the ListView and drop it over one of its items except the first.
  • Press the button to clear the ListView.
  • Once again drag the memo and drop it over the (now empty) ListView.
  • The location where TListView uses the bogus pointer FLastDropTarget is:
      procedure TCustomListView.SetDropTarget(Value: TListItem);
    There is a line "Value := DropTarget;" where "DropTarget" will reference FLastDropTarget under certain circumstances (for example if the Listview is empty). The next line "Value.DropTarget" then tries to assign a value to the bogus "item" which is the real location of the crash.

    TTreeView also does not reset its FLastDropTarget if the referenced item is destroyed. However it does not use it within its SetDropTarget procedure or - AFAICS - elsewhere, so it is not really a problem.

    Good news: Borland applied the patch that's given below to Delphi 3

    Solution / workaround
    To fix the bug open ComCtrls.PAS and find the destructor TListItem.Destroy. After the line:
      FDeleting := True;
    add the following two lines:
      If self = Owner.Owner.FLastDropTarget then
        Owner.Owner.FLastDropTarget := nil;
    More on the same subject:
    Received from Bert Binnenmarsch, who added: I got the fix from Scott Pinkham/QC, 70252,3410 so he deserves the credit.

    In the TCustomListView a pointer to a deleted TListItem is accessed under certain situations and results in the AccessViolation. Modify the TCustomListView.Delete method to nil the pointer if is the same item that is being deleted:
    procedure TCustomListView.Delete(Item: TListItem);
    begin
      if (Item <> nil) and not Item.FProcessedDeleting then
      begin
        if Assigned(FOnDeletion) then FOnDeletion(Self, Item);
    
        {ADD THIS LINE TO FIX BUG}
        if Item = FLastDropTarget then FLastDropTarget := nil;
    
        Item.FProcessedDeleting := True;
        Item.Delete;
      end;
    end;
    In my opinion (R.S.), this is a typical example of the kind of trouble that is caused by the fact that Free does NOT set the value of the pointer to nil.

    Bug #409; last modified: 7-May-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha
    Win32 - TListView

    If you select an item (in code) which is not visible, the TListView does not scroll that item into view.

    Description
    Reported by James J. Boswell; checked by Hallvard Vassbotn
    Lets say you select a TListBox item in code. The item gets selected, and if it was out of view, the TListBox scrolls to show that item. This doesn't seem to happen in TListView.

    I've done TListView.Selected and TListView.ItemFocused together, and sure enough the item has been selected and given a focus box, but if the item is out of view, the TListView doesn't scroll to show it.

    Solution / workaround
    We could call this a case of RTFM, although it's quite reasonable to expect the same behaviour as TListBox.
    The solution is simple: use the method that's meant to achieve the desired effect:
    TListItem.MakeVisible(PartialOK: Boolean)

    Bug #443; last modified: 17-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A N/A Absent Absent Absent Exists Exists Fixed
    Win32 - TListView

    When you add an item to a ListView which has checkboxes, all checkboxes are cleared.

    Description
    Reported by Chris Jobson; checked by Reinier Sterkenburg
    To reproduce:

    Cause:
    The cause is a change to the VCL between Delphi 3 and Delphi 4. The offending routine in ComCtrls.pas is:

    constructor TListItem.Create(AOwner: TListItems);
    begin
      FOwner := AOwner;
      FSubItems := TSubItems.Create(Self);
      FOverlayIndex := -1;
      FStateIndex := -1;
      if Owner.Owner.Checkboxes and Owner.Owner.HandleAllocated then
        SetChecked(False);
    end;
    The last two lines are new in Delphi 4. The problem is that SetChecked sets the item's checked state by
        ListView_SetCheckState(LV.Handle, Index, Value);
    but the item hasn't yet been added to the collection and so Index is -1. Thus this call clears the checked state of all existing items.

    Note:
    I've reported this to Borland. It was acknowledged as bug report 20690.

    Solution / workaround
    Greg Chapman suggested the following (8 Oct 98):
    The following hack will keep newly created TListItem's from clearing all checkboxes in a TListView (under D4):
      TExtListView = class(TListView)
      protected
        function CreateListItem: TListItem; override;
      end;
    
    {...}
    
    function TExtListView.CreateListItem: TListItem;
    {$IFDEF VER120}
    var SaveHandle: HWnd;
    begin
      SaveHandle:= WindowHandle;
      WindowHandle:= 0;
      try
        Result:= inherited CreateListItem;
      finally
        WindowHandle:= SaveHandle;
      end;
    end;
    {$ELSE}
    begin
      Result:= inherited CreateListItem;
    end;
    {$ENDIF}
    Then the call in TListItem.Create to Owner.Owner.HandleAllocatd will return false.

    I'm not sure why Inprise tries to explicitly set the check-state in the constructor. It may be because calling ListView_InsertItem results in immediate LVN_ITEMCHANGING/CHANGED notifications specifying the unchecked box as the stateImage (at least in my version of COMCTRL32.DLL -- 4.72.3110.1). I think Inprise might have been trying to suppress these notifications since in fact the TListItem hasn't really changed (new items are unchecked by default). At any rate, people should be aware that they will get these notifications. Changing the parameters to ListView_InsertItem so that they specify the unchecked box as the StateImage does not suppress the notifications; they get sent anyway with the TNMListView's uNewState = uOldState.

    One other note, this bug can have a drastic impact on performance when adding a large number of items to a ListView because, with each item added, the ListView has to iterate through all its items and uncheck them. If your ListViews under D4 are mysteriously slow, this could be the cause.


    Bug #480; last modified: 17-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Exists Exists Exists Fixed Fixed Fixed
    Win32 - TPageControl

    TPageControl's Tabsheets do not respond to accelerator keys

    Description
    Reported by Paul Scott; checked by Eivind Bakkestuen
    To reproduce:
    Create a dummy application with a TPageControl on the main form.
    Right click on TPageControl to create a couple of new Tabsheets pages.
    Click on first tabsheet and change its caption to &Test1. Click on the other tabsheet and change its caption to T&est2.
    Run the application. When the accelerator keys ALT + T for Tabsheet "Test1", and Alt + e for Tabsheet "Test2" are pressed the given tabsheet should gain focus. This does not happen.

    Causes:
    Looking through the VCL source, it is evident that both TPageControl and its ancestor TCustomTabControl, do not implement the CMDialogChar message to process the accelerator key for Tabsheet changes - as other TWinControls do. It seems the Delphi development team has completely overlooked accelerator keys for TPageControl, even though TTabsheet captions will be shown to have an accelerator if the caption contains an ampersand.

    Solution / workaround
    There are various untidy hacks to get around this, but the only two really tidy fixes are to either add the missing CMDialogChar to the TPageControl VCL source (which I prefer not to do in case Borland release a service pack) or preferably create a descendent of TPageControl and add the missing code:
    TNewPageControl = class(TPageControl);
    private
      procedure CMDialogChar(var Message : TCMDialogChar); message
    CM_DialogChar;
    end;
    
    procedure TNewPageControl.CMDialogChar(var Message : TCMDialogChar);
    var
      i : integer;
    begin
      if ssAlt in KeyDataToShiftState(Message.KeyData) then
        for i := 0 to PageCount - 1 do
          if IsAccel(Message.CharCode, Pages[i].Caption) and (CanChange)
             and (Pages[i].TabVisible) then
          begin
            ActivePage := Pages[i];
            Message.result := 1;
            Change;
            exit;
          end;
      inherited;
    end;

    Bug #76; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Unknown Unknown Unknown Unknown Unknown Unknown
    Win32 - TRichEdit

    In some cases when loading RTF files into TRichEdit, FirstIndents of paragraphs disappear or display incorrectly

    Description
    Reported by Andrew Douglas; additional comments by Nigel Hanson
    The fact is that LeftIndents are counted relative to the FirstIndents but really it must be the opposite order: FirstIndents must be counted from the LeftIndents (at least this is usual for the textprocessors I know). For example: a paragraph has LeftIndent=0 and FirstIndent=3 (in chars.) But in RichEdit, FirstIndent will be 3 and LeftIndent will be -3. This values will be saved in file, but when loading, FirstIndent will be 3 (and it's right) but LeftIndent will be 0!

    In other words: if the first line of a paragraph is indented 1 cm, then the RichEdit will display the entire paragraph indented by 1 cm. I think there are two mistakes here:

    1. FirstIndent must be counted from LeftIndent but not opposite;
  • Both negative and positive values must be loaded from file, not only positive.

  • Bug #77; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Unknown Unknown Unknown Unknown Unknown Unknown
    Win32 - TRichEdit

    Exception or wrong return value on EM_POSFROMCHAR message.

    Description
    ; checked by Duncan Murdoch and Jani Järvinen
    If you send the the EM_POSFROMCHAR message (using the SendMessage function) to a TRichEdit component you'll get an exception.
    Cause(s):
    The constant EM_POSFROMCHAR is defined twice: in the Messages unit: EM_POSFROMCHAR = 214; and in the RichEdit unit: EM_POSFROMCHAR = WM_USER+38. The definition in the RichEdit unit is wrong. Also, the documentation for the parameters to use for this message is wrong. This is due to bad information in the Win32 API documentation; there are two MS knowledgebase articles about this: Q137249 and Q137805.
    The right parameters for EM_POSFROMCHAR are:
    WPARAM should be the address of a TPoint structure; LPARAM should be the index of the character you want. The return value is not used.
     The right parameters for EM_CHARFROMPOS are:
    WPARAM should be 0; LPARAM should point to a TPoint structure. The return value is the inde of the character.
    An example:
    var
      I, J: Longint;
      P: TPoint;
    begin
      P.X := X; P.Y := Y;
      I := LongInt(@P);
      J := SendMessage(RichEdit1.Handle, Messages.em_CharFromPos, 0, I);
    end;
    Solution / workaround
    1. If you have the VCL sources:
    Remove or comment out the definition of EM_POSFROMCHAR

    2. If you don't have the VCL sources:
    Check your sources for EM_POSFROMCHAR and make sure the proper value and parameters are used. Many times one can just leave the RichEdit unit out of the uses clause.


    Bug #78; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Exists Unknown Unknown Unknown Unknown Unknown
    Win32 - TRichEdit

    After resizing (enlarging), part of the client area will not be painted anymore. This seems to occur under NT 3.51 only.

    Description
    By Reinier Sterkenburg. Not confirmed independently because NT 3.51 is getting scarce
    I've reproduced the bug on two systems running NT 3.51. Under NT 4.0 it doesn't occur.
  • Create a new project
  • Place a RichEdit (RichEdit1) on the from
  • Place a Button (Button1) on the form
  • Make an event handler for Button1Click:
  • procedure TForm1.Button1Click(Sender: TObject);
    begin
      RichEdit1.Height := RichEdit1.Height + 10;
    end;
  • Fill the RichEdit with some text
  • Click on Button1
  • Now you can see that only a part of the RichEdit is painted, i.e. the original 'Client area' of the RichEdit. The added space at the bottom stays empty.
  • The example above is the simplest form; it will mostly show up when you resize (enlarge) a window with an 'alClient' RichEdit in it. I haven't checked the VCL sources for a cause or explanation. It occurs with Delphi 2 and Delphi 3.
    Solution / workaround
    The workaround I used is quite awkward:
    In an OnResize event handler I create a new RichEdit which replaces the old one. All property values I want to keep are copied from the old to the new one before Freeing the old one.

    Bug #79; last modified: 25-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Exists Unknown Unknown Unknown Fixed Fixed
    Win32 - TRichEdit

    TRichEdit.Visible := False fails if the RichEdit contains text at design-time

    Description
    Reported by Wim Aalbers; checked and edited by ??? and Chris Rankin
    To reproduce the problem:
    Drop a TRichEdit onto a form, and set its Visible property to False in the Object Inspector. Notice that the Lines property already contains the text "RichEdit1". Now compile and run the project, and you will still see the RichEdit control. If you now go to the Object Inspector and empty the Lines property, then the RichEdit will be correctly hidden the next time you run.

    The problem doesn't so much lie in TRichEdit as in TRichEditStrings, and possibly Windows 95. When TRichEditStrings calls its SetUpdateState() method, it sends a WM_SETREDRAW message. When Windows processes this message it (somehow) sets the WS_VISIBLE bit in the TRichEdit's Window-Style. However, because this happens behind Delphi's back, the TRichEdit.Visible property is still False. This is why an explicit Visible := False;

    in the FormCreate handler has no effect- Delphi doesn't believe that the value of the property would change and so takes no action.
    Solution / workaround
    There is very interesting comment in the TMemoStrings.SetUpdateState() method:
    // WM_SETREDRAW causes visibility side effects in memo controls
    Memo.Perform(CM_SHOWINGCHANGED,0,0); // This reasserts the visibility we want
    So modifying TRichEditStrings.SetUpdateState() to
    ...
      if not Updating then begin
      {
        This is the missing line of code to make TRichEdit visible/invisible
      }
        RichEdit.Perform(CM_SHOWINGCHANGED,0,0);
        RichEdit.Refresh;
    ...
    will fix the problem. If you are using packages, then Perform() the CM_SHOWINGCHANGED message in the FormCreate handler instead.

    Bug #80; last modified: 28-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Gotcha Exists Exists Exists Exists Exists Exists
    Win32 - TRichEdit

    Documentation bug: the PageRect property contains co-ordinates in pixels, not twips

    Description
    Reported by Brad Stowers; checked by Borland (D4.02 readme)
    The D3 documention lists a property named PageRect for the TRichEdit control which claims to be the printable area in twips (1/20th of a point, or 1/1440 of an inch). The source code, on the other hand, uses a formula that converts from pixels, not twips: (from SOURCE\VCL\COMCTRLS.PAS, TRichEdit.Print method)
      else begin
        rc.left := PageRect.Left * 1440 div LogX;
        rc.top := PageRect.Top * 1440 div LogY;
        rc.right := PageRect.Right * 1440 div LogX;
        rc.bottom := PageRect.Bottom * 1440 div LogY;
      end;
    What this does is convert from pixels *TO* twips.

    The bug is in Delphi 3.0 (3.01 could not be checked yet) and Delphi 2.01, although in 2.01, PageRect was undocumented, so it's not really a bug there.

    To reproduce the bug:
    Try to manually set PageRect to a know value of twips, say for 2" margins:

      MyRichEdit.PageRect := Rect(2*1440, 2*1440, round(6.5*1440), 9*1440);
      MyRichEdit.Print('test');
    It won't work. But if you use pixels, it will:
    var
      LogX, LogY: integer;
    begin
      LogX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
      LogY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
      MyRichEdit.PageRect := Rect(2*LogX, 2*LogY, round(6.5*LogX), 9*LogY);
      MyRichEdit.Print('test');
    end;
    Also, it might be good to note that you have to manually adjust for the non-printable area, too. If you use the above, and your printer has a non-printable area of 1/2" on the left, you will really get a left margin of 2 1/2" inches. I left that out in the example to make the code a little more clear.

    Bug #474; last modified: 6-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Unknown Unknown Unknown Unknown Exists Unknown Fixed Fixed
    Win32 - TToolBar

    The TToolButton.Visible property is not persisted between sessions. Specifically, it gets reset back to "True" when a project gets reloaded.

    Description
    Reported by James Rofkar; checked by Reinier Sterkenburg
    To reproduce:
    1. Create a project that uses the TToolBar component from the Win32 component palette.
    2. Add some TToolButton's to the TToolBar.
    3. Set the Visible property of some of the buttons to "False".
    4. Save the project, rebuild, and run. No problems yet.
    5. Close the project, then reload it, and notice the Visible property of the TToolButton's which were set to "False" in step 3 above.
    Notice: All the TToolButton's Visible properties have been reset back to "True".

    Interestingly enough, after closing the project, the .DFM shows the correct values for the Visible property: False. For some reason, the error occurs during the reload of the project.


    Bug #482; last modified: 25-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A N/A Exists Exists Exists Exists Exists Exists
    Win32 - TToolBar

    Captions of buttons on TToolBar don't get the ToolBar's font color

    Description
    Reported by Matt Hamilton; checked by Erik Berry
    If you add a new TToolbar to a form, then set its Font.Color property to, say, clWhite instead of the default clWindowText, then you would expect any buttons added to the toolbar to have white captions (after you've set the ShowCaptions to true, of course).

    However, this is not the case. Try it! If you set Toolbar1.ShowCaptions to true and Toolbar1.Font.Color equal to clWhite, then add a TLabel to the toolbar, the label will be white (as expected). If you then right-click and add a new TToolButton, it's caption will be clWindowText (usually black)!!!

    Erik Berry commented on this:
    Since TToolButton doesn't have a ParentFont or a font property, this might be a limitation of the Win32 control, and not a Delphi bug.


    Bug #93; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A N/A Exists Unknown Unknown Unknown Unknown Unknown
    Win32 - TToolBar/TToolButton

    Buttons classes derived from TToolButton don't display properly on a TToolBar.

    Description
    Reported by Ken Byrd
    It appears that there is a _bug_ in the TToolBar source. In the TToolBar.UpdateItem and TToolBar.UpdateButtonStatus methods, there is code to check the ClassType of a control to see if it is a TToolbarButton. This works fine unless you are deriving a class from TToolButton.
    Solution / workaround
    Modifying the source (in comctrls.pas) to use "is TToolButton" instead of "ClassType = TToolButton" fixes the problem.

    Now I have another problem - how can I rebuild my runtime packages to include these changes? It doesn't seem that Borland shipped the package source (.dpk) files. I can use my modified version of comctrls.pas, but when I opt to use runtime packages, the .dpl without my changes is used and the problem reappears.

    Bug #94; last modified: 25-Oct-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A N/A Exists Unknown Unknown Unknown Fixed Fixed
    Win32 - TToolBar/TToolButton

    A button on a TToolBar disabled in the parent form's OnCreate event causes all the toolbar buttons to be invisible

    Description
    Reported by Xander van Alst; checked by Neil Booth
    Steps to reproduce the bug:
  • Create a new application, and on the new form drop a TToolBar.
  • By right clicking on it and using the speed menu, add two buttons.
  • In the form's OnCreate event, disable one of the buttons.
  • Run. None of the buttons are visible (though their visible properties are still True if you query them).
  • Solution / workaround
    Set the Enabled property at design time, or elsewhere such as the OnShow event.

    Bug #95; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Fixed Fixed Fixed Fixed Fixed Fixed
    Win32 - TTreeView

    DoEndDrag in TTreeView does not seem to be executed.

    Description
    Reported by Screen Consultants; checked by Chris Rankin
    I tried to build a component based on TTreeView which starts to scroll the tree view whenever a node is dragged beyond the top or the bottom of the tree view. The scrolling needs to stop when the grid is entered again or when the dragging stops. To accomodate the last, I tried to override the DoEndDrag method of TTreeView. The scrolling doesn't stop however, and if I insert a breakpoint in this method, the program never seems to reach it.
    How to reproduce the observed behaviour
  • Create an application that has FmEndDr1.pas as its main form and uses EndDrag2.pas.
  • Set the treeview's visible property to false
  • Add some 20 to 30 items to the treeview
  • Put a breakpoint on the first line of the procedure "TScrollingTreeView.DoEndDrag" in "EndDrag2"
  • Run the code
  • Start dragging an item in the treeview
  • Release the mouse button. The "EndDrag" event handler in "FmEndDr1" is executed, as the message shows, but the tree never stops scrolling because the breakpoint in "DoEndDrag" ("EndDrag2") is never reached.
  • The descriptions of the expected and observer behaviour have not been copied here; the conclusion that this is a real bug is justified. If anyone wants more info on this we can supply that on request

    Possible cause
    The problem might be that TTreeView uses the DoEndDrag method of TCustomTreeView, which is dynamic. The TCustom.DoEndDrag calls inherited DoEndDrag of TControl, which also is dynamic. The TCustom.DoEndDrag hooks on to the OnEndDrag event. I think the DoEndDrag of TCustomTreeView should have been declared with 'override' instead of with 'dynamic'. The odd thing is, if I add an event handler to the OnEndDrag event of "st", the event handler is executed while the DoEndDrag of "st" does not seem to be executed. I would expect it the other way around.

    ===============================================================
    The unit ComCtrls in the Delphi VCL library:
    ===============================================================
    interface
      TCustomTreeView = class(TTreeView)
        ...
        protected
          procedure DoEndDrag(Target: TObject; X, Y: Integer); dynamic;
        ...
      end;
    
    implementation
    
    procedure TCustomTreeView.DoEndDrag(Target: TObject; X, Y: Integer);
    begin
      inherited DoEndDrag(Target, X, Y);
      FLastDropTarget := nil;
    end;
    
    ===============================================================
    The unit Controls in the Delphi VCL library:
    ===============================================================
    interface
      TControl
        ...
        protected
          procedure DoEndDrag(Target: TObject; X, Y: Integer); dynamic;
        ...
      end;
    
    implementation
    
    procedure TControl.DoEndDrag(Target: TObject; X, Y: Integer);
    begin
      if Assigned(FOnEndDrag) then FOnEndDrag(Self, Target, X, Y);
    end;
    Solution / workaround
    By Chris Rankin
    The declaration in TCustomTreeView *should* read "override", not "dynamic". Recompile the VCL with this change and the demonstration app. work OK.
    As it happens, this bug is also present in TCustomListView.

    Bug #96; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Unknown Unknown Unknown Unknown Unknown Unknown
    Win32 - TTreeView

    Having nodes that are wider than the window may cause nasty problems

    Description
    Reported by Henk Hagedoorn
    The TreeView component can cause many nasty problems in your application when you have nodes in it that have a text that is wider than the TreeView window. This may have something to do with the WM_SETREDRAW message that the TreeView component uses to temporarily disable redrawing when adding or updating items. According to the MS knowledgebase 'this can cause the TreeView control to behave strangely'.
    So far, the bug seems to occur on NT 4.0 systems only.
    Solution / workaround
    Avoid having nodes that are too long...

    Bug #100; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Exists Fixed Fixed Fixed Fixed Fixed Fixed
    Win32 - TTreeView

    Bug when editing the Items

    Description
    When using the TTreeView object - when you select the 'Items' property a dialog appears that allows you to create the nodes you want. Well... it has a bug, in its 'Delete handler'
    Steps to reproduce: Select 'New Item' type 'Level 1', then select 'New SubItem' type 'Level 2', then select 'New SubItem' again. Type 'Level 3'. Select 'Delete' and then click on 'Level 1'. What happens is that 'Level 2' will be replaced with 'Level 3'.
    Solution / workaround
    Do it right in one time, i.e. avoid having to delete items in that dialog.

    Bug #101; last modified: before April 1998
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    N/A Fixed Fixed Fixed Fixed Fixed Fixed Fixed
    Win32 - TTreeView

    Bug in MoveTo method
    Only occurred in Delphi 2.0

    Description
    There appears to be a bug in the MoveTo method of TTreeNode. To confirm the bug start a new project, add a TreeView and assign to the DoubleClick event the following code:
    procedure TForm1.TreeView1DblClick(Sender: TObject);
    var
       TN1, TN2, TN3: TTreeNode;
    begin
       {Label1.Caption := TreeView1.Selected.Text}
       with TreeView1 
       do begin
          TN1 := Items.Add(nil, 'A');
          TN2 := Items.Add(nil, 'B');
          TN3 := Items.Add(nil, 'C');
          TN3.MoveTo(TN2, naAddChild);
          TN1.MoveTo(TN3, naAddChild);
       end;
    end;
    Run the project, doubleclick on the TreeView, then expand/contract the Tree and notice the strange effect of the TreeView having an infinite amaount of nodes. The problem is in the implementation of TTreeNode.MoveTo (COMCTRLS.PAS). MoveTo produces all sorts of other strange effects.
    Solution / workaround
    Not needed: it's fixed in version 2.01.

    Bug #487; last modified: 27-Dec-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Absent Absent Absent Absent Absent Exists Exists Fixed
    Win32 - TTreeView

    The TTreeNode.MoveTo procedure does not work if you specify naAddChild or naAddChildFirst.

    Description
    Reported by Kim Pedersen
    It worked in Delphi 3 but there there was a gotcha because if you tried to move a Node onto itself, your program would crash, that made Borland putin a check to see if the node was the same at they came in with, but they put it in the wrong place.
    Solution / workaround
    Correct the procedures TTreeNode.InternalMove and TTreeNode.MoveTo as follows:
    procedure TTreeNode.InternalMove(ParentNode, Node: TTreeNode;
      HItem: HTreeItem; AddMode: TAddMode);
    var
      I: Integer;
      NodeId: HTreeItem;
      TreeViewItem: TTVItem;
      Children: Boolean;
      IsSelected: Boolean;
    begin
    // Commented out because it makes MoveTo not work.
    //  if ParentNode = Node then Exit;
      Owner.ClearCache;
      if (AddMode = taInsert) and (Node <> nil) then
        NodeId := Node.ItemId else
        NodeId := nil;
      Children := HasChildren;
      IsSelected := Selected;
      if (Parent <> nil) and (Parent.CompareCount(1)) then
      begin
        Parent.Expanded := False;
        Parent.HasChildren := False;
      end;
      with TreeViewItem do
      begin
        mask := TVIF_PARAM;
        hItem := ItemId;
        lParam := 0;
      end;
      TreeView_SetItem(Handle, TreeViewItem);
      with Owner do
        HItem := AddItem(HItem, NodeId, CreateItem(Self), AddMode);
      if HItem = nil then
        raise EOutOfResources.Create(sInsertError);
      for I := Count - 1 downto 0 do
        Item[I].InternalMove(Self, nil, HItem, taAddFirst);
      TreeView_DeleteItem(Handle, ItemId);
      FItemId := HItem;
      Assign(Self);
      HasChildren := Children;
      Selected := IsSelected;
    end;
    
    procedure TTreeNode.MoveTo(Destination: TTreeNode; Mode:
    TNodeAttachMode);
    var
      AddMode: TAddMode;
      Node: TTreeNode;
      HItem: HTreeItem;
      OldOnChanging: TTVChangingEvent;
      OldOnChange: TTVChangedEvent;
    begin
      //Made by KFP to fix the MoveTo bug introduced by borland in D4.
      if Self = Destination then exit;
      //End Insert
      OldOnChanging := TreeView.OnChanging;
      OldOnChange := TreeView.OnChange;
      TreeView.OnChanging := nil;
      TreeView.OnChange := nil;
      try
        if (Destination = nil) or not Destination.HasAsParent(Self) then
        begin
          AddMode := taAdd;
          if (Destination <> nil) and not (Mode in [naAddChild, naAddChildFirst]) then
            Node := Destination.Parent else
            Node := Destination;
          case Mode of
            naAdd,
            naAddChild: AddMode := taAdd;
            naAddFirst,
            naAddChildFirst: AddMode := taAddFirst;
            naInsert:
              begin
                Destination := Destination.GetPrevSibling;
                if Destination = nil then AddMode := taAddFirst
                else AddMode := taInsert;
              end;
          end;
          if Node <> nil then
            HItem := Node.ItemId else
            HItem := nil;
          InternalMove(Node, Destination, HItem, AddMode);
          Node := Parent;
          if Node <> nil then
          begin
            Node.HasChildren := True;
            Node.Expanded := True;
          end;
        end;
      finally
        TreeView.OnChanging := OldOnChanging;
        TreeView.OnChange := OldOnChange;
      end;
    end;

    Bug #404; last modified: 5-May-98
    1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
    Unknown Unknown Unknown Unknown Gotcha Gotcha Gotcha Gotcha
    Win32 - TTreeView/TListView

    TTreeView's OnDeletion event occurs "too late": it may occur AFTER form's OnDestroy

    Description
    Reported by Sergey Mishkovskiy; checked by Hallvard Vassbotn
    Steps to reproduce:

    Comment from checker:
    I've looked at this bug report and can verify that the reported behavior is seen. The same problem also applies to TListView, BTW.
    However, I wouldn't call this a bug, but a documentation omission. In the documentation for OnDeletion, Borland should have mentioned that the event could be fired after the Form's OnDestroy event has run.
    Example code

    When you run the code you will see that FormDestroy runs before both TreeView1Deletion and ListView1Deletion. The reason for this is:

    In TCusomForm.Destroy you have this logic:

    destructor TCustomForm.Destroy;
    begin
      // ...
      if Assigned(FOnDestroy) then
        try
          FOnDestroy(Self);
        except
          Application.HandleException(Self);
        end;
      if HandleAllocated then DestroyWindowHandle;
      //...
      inherited Destroy;
    end;
    The FOnDestroy calls the user defined FormDestroy event handler. Then the DestroyWindowHandle will destroy the Windows handle of the form and all other handles owned by the form, including the handles for TreeView and ListView. This will trigger notification messages that will eventually call the OnDeletion events. Finally the VCL components owned by the form will be freed in the inherited destructor.

    As Sergey says, this behavior can cause problems if the OnDeletion event handler depends on a resource freed by the OnDestroy event handler. In addition to his workaround (below), we could add a sanity check in the OnDeletion event handler. Either:

      if Assigned(MyResource) then
        ....
    or
      if not (csDestroying in ComponentState) then
        ...
    I wouldn't call this a bug, because there is no good way to fix it at the VCL level. The problem is rather that we see unexpected and undocumented behavior. Fixing this in VCL (by not calling OnDeletion after the forms OnDestroy has run) could be worse than the current behavior, depending on the needs of the programmer.
    Solution / workaround
    Just free TreeView in form's OnDestroy yourself. Something like this will do the trick:
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      { ... }
      TreeView1.Free;
      TreeView1 := nil;
      { ... }
    end;

    Index page
    The Delphi Bug Lists are maintained by Reinier Sterkenburg, with help from the DeBug Team.
    All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.