Borland Delphi

[ City Zoo | Announcements | Aritcles | Tips & Tricks | Bug List | FAQ | Sites ]


The Delphi Bug List

Visual Component Library (VCL)

TApplication
TComboBox
TCustomGrid
TDBGrid
TFileDialog
TListBox
TMaskEdit
TOutline
TSpeedButton
TSpinEdit
TStringList
TTabbedNotebook
TTable
TWinControl

TApplication.Run method does not honor the Run Minimized/Maximized setting.

Description:

Delphi applications do not honor the Windows shell settings for running the program in a minimized or maximized state. This happens because the TApplication object creates a hidden "application" window which is receiving the the minimize/maximize setting instead of the main form.

Solution:

If you have the source to the VCL, modify the TApplication.Run method (FORMS.PAS) to account for these settings:

procedure TApplication.Run;
begin
  AddExitProc(DoneApplication);
  if FMainForm <> nil then
  begin
    ShowWindow(FMainForm.Handle, CmdShow);
    FMainForm.Visible := True;
    repeat
      HandleMessage
    until Terminated;
  end;
end;

If you do not have, or prefer not to modify, the VCL source, add the following to your main form's OnCreate event handler:

  ShowWindow(Handle, CmdShow);

TComboBox.DropDownCount property does not work correctly in certain cases with owner drawn controls.

Description:

TComboBox controls with the Style property set to csOwnerDrawFixed or csOwnerDrawVariable do not correctly calculate the size of the drop down list in certain cases. The DropDownCount property is used to specify how many items are to be displayed when the ComboBox is "opened." This property works fine as long as the size of the item you are displaying is based on the font assigned to the control. If you look at the TCustomComboBox.AdjustDropDown method in the VCL source code (STDCTRLS.PAS), you will see that to calculate the size of the dropdown window, the DropDownCount property is multiplied by the height of the control's font. This calculation should be using the ItemHeight property. This can cause problems which draw items that are not based on a font, such as icons.

Solution:

The simplest way to fix this is to just ensure that Font.Height is equal to ItemHeight. Note that you should probably use a TrueType font for Font.Name so that it can cover a wide range of sizes.

The best way is to fix the VCL source code so that AdjustDropDown does the calculation properly using ItemHeight.


TCustomGrid descendant components cause run-time error 210.

Description:

Creating a descendant component from TCustomGrid will cause a RTE 210 when you drop the new component onto a form.

Solution:

This is not actually a VCL bug, as there is nothing wrong with the code. The problem lies in Delphi's handling of abstract methods. The real error is that TCustomGrid has a method called DrawCell that is responsible for drawing each cell in the grid. Because a TCustomGrid neither knows nor assumes anything about how you want the data to appear, it implements DrawCell as an abstract method, meaning you MUST override it in descendant components. The real problem here is that the documentation for TCustomGrid.DrawCell does not point this out, and crashing Delphi with an RTE 210 does not help matters at all. To worsen the situation, the documentation for a RTE 210 (and all runtime errors) is listed only in the Object Pascal Language Guide, which you must purchase separately from Borland. However, you can obtain a free electronic copy of this manual in Acrobat Reader format from Borland's FTP site (objlang.zip ~2MB).

Add this to your TCustomGrid descendant to prevent the RTE 210 error:

protected
  { Protected declarations }
  procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;

{ ..... }

procedure TMyGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
begin
  { Print Column, Row in each cell }
  Canvas.TextOut(ARect.Left, ARect.Top, IntToStr(ACol)+', '+IntToStr(ARow));
end;

TDBGrid.FixedColor property does not work.

Description:

The FixedColor property of this component does not work as documented, and as it does work in TStringGrid and TDrawGrid. Changing this value at either design or run-time has no effect. It should set the color that is used to draw the fixed column and row backgrounds.

Solution:

Hallvard Vassbotn originally reported this bug on the comp.lang.pascal newsgroup and included the following fix for the problem. I have not confirmed that it works, but it appears that it should.

Derive a new component from TDBGrid and add the following functionality:

{...unit declaration, uses clause...}
type
  TDBGridFix = class(TDBGrid)
  private
    procedure SetFixedFixedColor(Value: TColor);
    function  GetFixedFixedColor: TColor;
  published
    property FixedColor: TColor read GetFixedFixedColor write SetFixedFixedColor default clBtnFace;
  end;

  procedure Register;

  implementation

  procedure TDBGridFix.SetFixedFixedColor(Value: TColor);
  begin
    inherited TitleColor := Value;
    inherited FixedColor := Value; { Not really needed, just to be safe }
  end;

  function TDBGridFix.GetFixedFixedColor: TColor;
  begin
    Result := inherited TitleColor;
  end;

  procedure Register;
  begin
    RegisterComponents('Data Access', [TDBGridFix]);
  end;

  end.

TOpenDialog.Files property does not handle files in root directory if ofMultiSelect option is set.

Description:

Allowing multiple files to be selected in the TOpenDialog component via the ofMultiSelect option can cause problems if selected files are in the root directory of a drive. The files will have two backslashes following the drive letter and colon. For instance, selecting AUTOEXEC.BAT and CONFIG.SYS from C:\ directory will cause Files[0] to return C:\\AUTOEXEC.BAT and Files[1] to return C:\\CONFIG.SYS.

Solution:

Use the Pos function to search each item for double backslashes (Pos('\\', Files[x])) and use the Delete procedure to remove one of the backslashes if found.


TListBox.Handle cannot be registered with DragAcceptFiles API function.

Description:

The Windows API function DragAcceptFiles that is used to register windows as able to receive files dropped from file manager applications will not work with TListBox components. To see the error, create a new form with a TListBox, TButton and TEdit control. In the form's OnCreate or OnShow event, add the following lines:

  DragAcceptFiles(Edit1.Handle);
  DragAcceptFiles(Button1.Handle);
  DragAcceptFiles(ListBox1.Handle);

Run the application and drag a file from File Manager over each of the controls. The cursor will indicate that it can be dropped on the button and edit controls, but not on the listbox. Note for PCTools for Windows users: It will appear as if the file can be dropped on the listbox, but doing so actually passes the dropped file on to the desktop window, creating a new icon on it. Very strange indeed.

Solution:

A quick glance and the VCL did not reveal any strange manipulation of the Handle property, so I am not sure what is causing this problem. If anyone has any ideas, please send them to me and I will investigate further. A viable work-around for the problem is to register the handle of the form that owns the listbox and handle the event there.


Some mask characters are not properly handled if specified as literal characters.

Description:

The / and : characters are not displayed correctly when they are specified as literal characters (prefaced by a \ character). The / character is normally interpreted as the date separator (as in 05/30/95) and : as the time separator (as in 12:39:30). These characters are determined by the international settings of Control Panel. Because most US users have their date separator set to /, they will not notice that specifying \/ does not truly insert a / character. The same is true for the \: combination.

To see the problem, start the International applet in Control Panel. Choose the Change button for Date Format. Enter any character other than / as the Separator. Close the International applet completely, as changes will not take effect until you do. Now try a TMaskEdit control that has "99\/99\:99" for it's EditMask property. According to documentation, the edit control with data in it should look like "34/12:32", but it really discards the \ literal specifier and uses the international settings, the same as it would if you had not given the literal at all. This problem is especially bad for applications that will be used outside of the US, which is becoming common with shareware programs distributed via the Internet.

Solution:

There is no solution known at this time short of fixing the bug in the VCL source code. I have not had time to do this, so cannot advise on how to. If anyone knows of a work-around, or has fixed the VCL source, please send it to me so that it can be published here.


TOutLine.OnDrawItem passes incorrect index.

Description:

The OnDrawItem event for owner-drawn TOutlines passes the index of the visible item to be drawn, not the actual item index. Also, the index is 0 based, whereas the TOutline index is 1 based. For example, if you have two nodes, each containing 5 subitems, the second node has an index of 7 (1 is the first node, 2-6 are the subnodes of 1). However, if the first node is collapsed and the second node is to be drawn, an index of 1 is passed (0 for the first node and the 5 subitems are not counted).

Solution:

The following subroutine (provided by Marc Hoffman) will convert the index passed to the actual item index:

procedure OutlineCorrectIndex(Outline: TOutline; var Index: longint): longint;
var
  x,
  visible: longint;
begin
  inc(Index);  { Adjust for 1 based, not 0 based }
  Visible := 0;
  x := 1;
  while (Visible < Index) and (x <= Outline.ItemCount) do begin
    if Outline.Items[x].IsVisible then begin
      inc(Visible);
      if Visible = Index then
        Index := x;
      break;
    end;
    inc(x);
  end;
end;

TSpeedButton.OnDblClick Event is never called.

Description:

The left button double click event handler is never called for TSpeedButton components, unless the button belongs to a group (i.e. GroupIndex is non-zero). A quick look at the VCL source reveals an interesting declaration for the WM_LBUTTONDBLCLK message handler:

  procedure WMLButtonDblClk(var Message: TWMLButtonDown); message WM_LBUTTONDBLCLK;

I have not experimented with it, but am curious to know what would happen if it were declared correctly as:

  procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
Solution:

The only idea I have is to create a descendant and override the WM_LBUTTONDBLCLK handler and declare it correctly. I have not had time to test this to see if it does indeed work. If you try it, please let me know the results.


TSpinEdit control will not correctly process ENTER and ESC keys in dialogs.

Description:

If a TSpinEdit control has focus in a dialog, pressing ESC will not cancel the dialog (if there is a cancel button), and pressing ENTER will not process the default button (if there is a default button). Standard UI for Windows dialogs dictates that the ENTER be treated as the OK button and ESC as the Cancel button. TSpinEdit prevents this behavior.

Solution:

For some reason, the style ES_MULTILINE is set for this control when it is created. The control is never a multi-line control, so I have no idea why this is done. However, it is the root of this problem. To fix it, simply create a new TSpinEdit descendant and override the CreateParams method so that it does the following:

procedure TSpinEditFix.CreateParams(Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.Style := Params.Style and not ES_MULTILINE;
end;

TStringList.Find method does not always work.

Description:

The Find method of TStringList will fail for lists which are not sorted (i.e. MyList.Sorted = FALSE). A quick look at the VCL source code file (CLASSES.PAS) reveals that the Find method does not bother to determine if the list is sorted or not; it assumes that it is and starts a binary search.

Solution:

Use the IndexOf method instead of Find. The IndexOf method will automatically call Find if the list's Sorted property is true. Otherwise, it will perform a standard linear search.


Tab controls does not respond if application does not have focus.

Description:

TTabbedNotebook components in MDI child windows do not respond to mouse clicks if the MDI application does not have focus (i.e. is the active application).

Solution:

There is no workaround known other than to click on the form somewhere besides a tab control.


TTable cannot access Paradox tables on Lantastic 6.0 servers.

Description:

Borland has acknowleged an incompatibility between BDE/IDAPI 1.3 (shipping with Delphi) and Lantastic 6.0 network operating system. This bug prevents access to Paradox tables that are located on a redirected server drive. This affects not only the Delphi data-aware components, but Database Desktop as well. Attempting to access the table usually results in an error message similar to "Not initialized for accessing network files."

Solution:

The only known workaround is to use a format other than Paradox.


TWinControl.RecreateWnd is dangerous to API routines that rely on the window handle.

Description:

All components that are based on TWinControl have a method, RecreateWnd, which destroys the current window and recreates it. This is necessary for certain situations, such as if the style of a window is modified after creation. However, certain Windows functions rely on a window handle, and recreating the window will prevent these functions from working correctly. For instance, the DragAcceptFiles function takes a window handle and registers it as able to accept files dropped from the file manager. If the window were recreated, the handle you passed to DragAcceptFiles would no longer be valid.

Solution:

This isn't so much a bug as a very big gotcha. The best solution I have for the problem is to derive a new component that overrides the RecreateWnd method and re-registers the window handle after the inherited method is called. The obvious short-coming of this work-around is that you will have to do it for every component that this may happen to.

Another possibility is to simply make sure that you do not do anything that would cause the component's window to be recreated. Some conditions which cause a window to be recreated are:

This should NOT be considered a complete list. This is only about half of what I found in STDCTRLS.PAS alone. I think this illustrates very well that you probably should derive new components and override RecreateWnd rather than try to avoid the situation.


[ Home Page | What's New | About CITY ZOO | Borland Delphi | About the Authors | INDEX ]
keeper@mindspring.com
Copyright © 1995 Mark R. Johnson. This is a CITY ZOO production.
Produced in conjunction with Brad Stowers.
Last revised September 5, 1995.
Enhanced version