Sunday, April 27, 2008

A not cool thing of TCoolBar

There is a demo project "coolstuf" in Delphi folder. It demonstrates how to build your own web browser with Delphi. Unfortunately it shows you how to re-procedure an issue of TCoolBar as well. "Just drag the (third) Links toolbar to top and then to bottom, repeat it for several times, you will see an extra area (roughly 40px) at bottom of TCoolBar." I call this as a "TCoolBar Bands' Position Problem". If you do not get it, please look at the snapshot.


Snapshot (Red rectangle is the extra area)

If you have read other posts in my blog, you might know, that I am very uncomfortable with such UI problems. So I did some investigation: This issue take place, when one or more bands have a fixed size. (TCoolBand.FixedSize is True) I suppose, that the height of this (fixed-size) band was not updated, when TCoolBar's height was changed. Actually, this is not the only one issue of REBAR controls. For instance: No chevron support, no whole dropdown button support, flickering problem, etc. (I will talk about them later in another post)

Solution

I have reported this issue to QualityCentral [1]. Not like other patches I have made, this time, the solution is not clean enough.

You have to:
  1. Copy ComCtrls.pas to your project folder,
  2. find and replace with the following code,
  3. and then recompile your project again.


procedure TCoolBar.CNNotify(var Message: TWMNotify);
//PATCH-BEGIN
var
I, FID: Integer;
RBBI: TReBarBandInfo;
//PATCH-END
begin
if (Message.NMHdr^.code = RBN_HEIGHTCHANGE) then
if IsAutoSized and (ComponentState * [csLoading, csDestroying] = [])
then begin
//PATCH-BEGIN
for I := 0 to Bands.Count - 1 do
if Bands[I].FixedSize then
begin
FillChar(RBBI, SizeOfReBarBandInfo, 0);
RBBI.cbSize := SizeOfReBarBandInfo;
RBBI.fMask := RBBIM_STYLE;
FID := Bands[I].FID;
Perform(RB_GETBANDINFO, FID and IDMask, Integer(@RBBI));
Perform(RB_SETBANDINFO, FID and IDMask, Integer(@RBBI));
end;
//PATCH-END

ReadBands;
BeginUpdate;
try
if AutoSize then AdjustSize;
finally
EndUpdate;
end;
end
else if IsBackgroundDirty then
Invalidate;
end;

Conclusion

As I mentioned before, REBAR controls (TCoolBar, TCoolBand, TToolBar and TToolButton) have not been implemented correctly as they should be. I did some experiments and made couple of patches. This article [2] is only the part one. There will be part two, part three...

To note that some patches must modify interface declaration and implementation both. Unfortunately Delphi cannot re-compile those modified units, when their interface declaration has been changed. The only one solution, so far as I known, is to create a copy of the whole REBAR control set and modify the new set. I will be appreciated, if someone can suggest any better ways.

References

  1. Related discuss at QualityCentral
  2. The Chinese version of this article (on my blog @csdn)
 

No comments: