3

How to automatically resize TStringGrid row (DefaultRowHeight) to match the height of the font used? I do something like

Grid.DefaultRowHeight:= Grid.Canvas.TextHeight('X') + 4;

but it is not working. For small fonts, the height of the rows is way too big.


Update:

It seems to be actually a problem with program's logic. If I change the font multiple times, the current height of the row matches the size of the font from previous font change event (it is one step behind).

I use this code to intercept font's size change:

procedure TStrGrid.CMFontChanged(var Message: TMessage);
begin
  inherited; // let TControl react first
  DefaultRowHeight:= Canvas.TextHeight('ApApM')+ 4;
end;

It acts as if the procedure will be:

begin
  DefaultRowHeight:= Canvas.TextHeight('ApApM')+ 4;
  inherited; 
end;

(like first it changes the height, then it actually sets the correct font size - therefore the height is one step behind)

2 Answers 2

5

It has nothing to do with this order: both the inherited CMFontChanged message handler and the DefaultRowHeight property setter call invalidate. It is due to the current font setting which is not yet updated:

procedure TStrGrid.CMFontchanged(var Message: TMessage);
begin
  Canvas.Font := Font;
  DefaultRowHeight := Canvas.TextHeight('Ap') + GridLineWidth + 3;
end;

Explanation:

Invalidate only flags windows to repaint the window (the grid) somewhere in future. That happens certainly after obtaining the text height. As alternative you can call Repaint prior to the request for the new text height, but that would result in a double repaint, hence setting Canvas.Font.

Sign up to request clarification or add additional context in comments.

Comments

2

When it comes to event ordering related issues then the easiest and quickest solution often was posting yourself a message via PostMessage (here from your CMFontChanged handler) and doing the update when receiving the posted message.

This has the advantage that it doesn't interfer with whatever the grids need to do to update its inner state.

5 Comments

Thanks for your solution. Even though it is the best (and proper) I used NGLN's hack as it requires a single line of code :) Even if NGLN's hack requires an extra paint, it is ok since the font is changed rarely (if ever).
@Altar I would certainly not describe my answer as a hack, and it does not require an extra paint.
@Heinrich Your suggestion indeed solves many kind of these issues. But I just tested it, and it does not work for this situation. Pity.
@NGLN I just always fear side effects when changing the "thing" in the "thing change handler". But it seems to be a quick and efficient solution in this case. So why not :)
Well, it's not the "thing" I am changing here. I simply assign the "changed thing" to Canvas.Font. Setting Canvas.Font does nót trigger CMFontChanged.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.