Recent

Author Topic: Confused ? - You will Be! - (well I am!)  (Read 467 times)

J-G

  • Hero Member
  • *****
  • Posts: 1198
Confused ? - You will Be! - (well I am!)
« on: June 19, 2026, 12:20:16 pm »
This problem has been driving me nuts for more than a day!

In my Triangle Program - or more specifically the Printer set up display - I had determined to show the position of the Tabs on the page with red lines at appropriate locations along the top of the Paper display. Because I can only use interger values and considering that the distance between tabs is small it was less than ideal but I was also confused by the fact that on first showing the MTF_Panel, the Tabs did not appear.

I tried various ways to stop this even thinking that because the TPanel was not 'visible' when I handled the 'drawing' - I made it visible, but still the tabs did not show until such time as I modified any of the parameters (Number of tabs, size of margins).

My next attempt to address both issues was to create a larger image (TShape) in the [Tabs] section of the display. This did make the position of the tab marks better but again on first show - nothing.

The attached .PNG file should make the problem clear.

By 'stepping through' the code I know that the procedure for drawing the Tabs image IS being executed prior to the MTF_Panel being shown so I cannot fathom why the first display is blank ????

Here is the code that draws the tab (and margin) lines :

Code: Pascal  [Select][+][-]
  1. procedure Show_Tabs(T,L,R,S : single);
  2. var
  3.   TM,LM,RM,TS,CurTab : word;
  4.   I : byte;
  5.   M : single;
  6. begin
  7.   TriangleSolution.Debug.Append('- Show Tabs');
  8.   if prPgOrient = 0 then             // scaling factor between full sheet
  9.     M := 290/105                     // display and page header display
  10.   else
  11.     M := 290/148;
  12.  
  13.   TM := trunc(T * M + 0.5);
  14.   LM := trunc(L * M + 0.5);
  15.   RM := trunc(R * M + 0.5);
  16.   TS := trunc(S * M + 0.5);
  17.   if TM > 20 then TM := 20;           // to account for top margin being large
  18.   CurTab := LM+TS;
  19.  
  20.   with TriangleSolution.Margin_Display.Canvas do
  21.    begin
  22.      Clear;
  23.      Pen.Color:=clBlack;
  24.      Pen.Width:=2;
  25.      MoveTo(0,40);                    // Draw Page outline
  26.      LineTo(0,0);
  27.      LineTo(290,0);
  28.      LineTo(290,40);
  29.  
  30.      Pen.Color:=clBlue;
  31.      MoveTo(LM,TM);LineTo(LM,35);     //  show margins
  32.      MoveTo(290-RM,TM);LineTo(290-RM,35);
  33.      MoveTo(LM,TM);LineTo(290-RM,TM);
  34.  
  35.      Pen.Color:=clRed;
  36.      Pen.Width:=1;
  37.      TM := TM+3;
  38.      for I := 1 to MaxTab do          //  show Tabs
  39.        begin
  40.          CurTab := Trunc(LM+I*TS);
  41.          MoveTo(CurTab,TM);LineTo(CurTab,TM+12);
  42.        end;
  43.    end;
  44.   Application.ProcessMessages;
  45. end;
  46.  

I added the  Application.ProcessMessages; at the end in case it was a matter of Windows being lazy, but it made no difference.

The proc is called with the Margin & Tab sizes (in mm) precalculated.

Without making any changes to the variables on the MTF_Panel, if I click on the button to show the panel a second time then the tabs DO appear. 

To try to solve this issue, I created a [Debug] TMemo and wrote the details of each proc called to that - just to make sure that I hadn't missed a call to draw the tabs - that's why the first line in the proc is   TriangleSolution.Debug.Append('- Show Tabs');


FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

paweld

  • Hero Member
  • *****
  • Posts: 1691
Re: Confused ? - You will Be! - (well I am!)
« Reply #1 on: June 19, 2026, 02:43:41 pm »
Is the Show_Tabs procedure executed before the panel is displayed?
What is the component type of Margin_Display?
Best regards / Pozdrawiam
paweld

Thaddy

  • Hero Member
  • *****
  • Posts: 19606
  • Glad to be alive.
Re: Confused ? - You will Be! - (well I am!)
« Reply #2 on: June 19, 2026, 04:03:31 pm »
I think there is just 1 (one)_ invalidate missing.
Any "programmer" that knows only one programming language is not a programmer

J-G

  • Hero Member
  • *****
  • Posts: 1198
Re: Confused ? - You will Be! - (well I am!)
« Reply #3 on: June 19, 2026, 04:15:11 pm »
Is the Show_Tabs procedure executed before the panel is displayed?
What is the component type of Margin_Display?

Yes - BUT I have also tried it with the Panel visible as well - and get the same result.
In addition, all the other components are sized/positioned prior to the Panel being made 'visible'  -  and they are all in place as expected, it's just the 'Tabs'.

Margin_Display is the TShape I referenced.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

J-G

  • Hero Member
  • *****
  • Posts: 1198
Re: Confused ? - You will Be! - (well I am!)
« Reply #4 on: June 19, 2026, 04:18:29 pm »
I think there is just 1 (one)_ invalidate missing.

Thanks for the input @Thaddy, but regrettably my knowledge of Pascal/Lazarus does not extend to that of 'Invalidation'  -  ie. I have no idea where to look for such a missing control/object.
« Last Edit: June 19, 2026, 04:22:29 pm by J-G »
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12608
  • Debugger - SynEdit - and more
    • wiki
Re: Confused ? - You will Be! - (well I am!)
« Reply #5 on: June 19, 2026, 04:20:04 pm »
Is TriangleSolution.Margin_Display  a TBitMap ?  Or anything with permanent image storage?

Given the ProcessMessages call, let me guess: This is not called in a paint event?

Any canvas of any components (except TBitmap or the like) are just painting on the screen, and will be lost each time something else goes on on the screen. OnPaint is called each time they need to be redrawn.

J-G

  • Hero Member
  • *****
  • Posts: 1198
Re: Confused ? - You will Be! - (well I am!)
« Reply #6 on: June 19, 2026, 05:15:42 pm »
Is TriangleSolution.Margin_Display  a TBitMap ?  Or anything with permanent image storage?

Given the ProcessMessages call, let me guess: This is not called in a paint event?

Any canvas of any components (except TBitmap or the like) are just painting on the screen, and will be lost each time something else goes on on the screen. OnPaint is called each time they need to be redrawn.

!!  I think you have the answer @Martin_Fr.

No this is NOT in an 'OnPaint' event ! 

I can create an OnPaint Event for the Margin_Display TShape easily enough but (having just tried a number of ways to integrate such) am struggling to determine how to put the code within it.

I've tried transfering lines 20 to 43 of the published code into the procedure TTriangleSolution.Margin_DisplayPaint(Sender: TObject); but naturally the variables that are calculated prior to line 20 are not recognised and I can't see a way to add them as 'arguments' for the OnPaint Header.

I also tried putting the OnPaint event as a nested-proc inside 'Show_Tabs but the compiler complains that the [stop] before Margin_Display is a syntax error.

I would appreciate some further guidance  ::)

Here is what I've tried :

Code: Pascal  [Select][+][-]
  1. procedure Show_Tabs(T,L,R,S : single);
  2. var
  3.   TM,LM,RM,TS,CurTab : word;
  4.   I : byte;
  5.   M : single;
  6.   procedure TTriangleSolution.Margin_DisplayPaint(Sender: TObject);
  7.   begin
  8.     with TriangleSolution.Margin_Display.Canvas do
  9.      begin
  10.        Clear;
  11.        Pen.Color:=clBlack;
  12.        Pen.Width:=2;
  13.        MoveTo(0,40);                    // Draw Page outline
  14.        LineTo(0,0);
  15.        LineTo(290,0);
  16.        LineTo(290,40);
  17.  
  18.        Pen.Color:=clBlue;
  19.        MoveTo(LM,TM);LineTo(LM,35);     //  show margins
  20.        MoveTo(290-RM,TM);LineTo(290-RM,35);
  21.        MoveTo(LM,TM);LineTo(290-RM,TM);
  22.  
  23.        Pen.Color:=clRed;
  24.        Pen.Width:=1;
  25.        TM := TM+3;
  26.        for I := 1 to MaxTab do          //  show Tabs
  27.          begin
  28.            CurTab := Trunc(LM+I*TS);
  29.            MoveTo(CurTab,TM);LineTo(CurTab,TM+12);
  30.          end;
  31.      end;
  32.   end;
  33. begin
  34.   TriangleSolution.Debug.Append('- Show Tabs');
  35.   if prPgOrient = 0 then             // scaling factor between full sheet
  36.     M := 290/105                     // display and page header display
  37.   else
  38.     M := 290/148;
  39.   TM := trunc(T * M + 0.5);
  40.   LM := trunc(L * M + 0.5);
  41.   RM := trunc(R * M + 0.5);
  42.   TS := trunc(S * M + 0.5);
  43.   if TM > 20 then TM := 20;           // to account for top margin being large
  44.   CurTab := LM+TS;
  45.  
  46.   Margin_DisplayPaint(self);
  47.  
  48. end;
  49.  

Which I'm sure you will find hilarious but I'm way out of my depth here  :-[


FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12608
  • Debugger - SynEdit - and more
    • wiki
Re: Confused ? - You will Be! - (well I am!)
« Reply #7 on: June 19, 2026, 05:22:07 pm »
Well one thing I can tell

Quote
Code: Pascal  [Select][+][-]
  1. procedure Show_Tabs(T,L,R,S : single);
  2. var
  3.   TM,LM,RM,TS,CurTab : word;
  4.   I : byte;
  5.   M : single;
  6.   procedure TTriangleSolution.Margin_DisplayPaint(Sender: TObject);

A nested procedure can not be method of an object.

Methods (procedures that have an "TSomeClass." prefix) must be outer top-level procedures.





But, if the outer function is a method... E.g
procedure TYourForm.OnYourComponentPaint
or
procedure YourComponent.OnPaint

(the 2nd form is less likely since then you need a subclassed component on your form, which you would likely have to build at runtime..>)

Then any nested procedure inside such a method can see "self" =>self being the TYourForm (in the first example).

And since they can see the form as self, they can see YourComponent (which is part of the form).

So you can have a nested procedure, just ensure the outer method is a METHOD (it should be, if you created it from the object inspector)
« Last Edit: June 19, 2026, 05:26:13 pm by Martin_fr »

paweld

  • Hero Member
  • *****
  • Posts: 1691
Re: Confused ? - You will Be! - (well I am!)
« Reply #8 on: June 19, 2026, 05:58:36 pm »
In my opinion, the simplest solution would be to change the component type from TShape to TImage.
Steps to follow:
1. Remove the TShape component named Margin_Display from the printer settings panel
2. Drag and drop a TImage component (from the Additional palette) in its place, set its dimensions to the same values, and rename it to Margin_Display
3. Modify the code of the Show_Tabs procedure as shown below:
Code: Pascal  [Select][+][-]
  1. procedure Show_Tabs(T,L,R,S : single);
  2. var
  3.   TM,LM,RM,TS,CurTab : word;
  4.   I : byte;
  5.   M : single;
  6.   bmp: TBitmap; //from Graphics unit
  7. begin
  8.   TriangleSolution.Debug.Append('- Show Tabs');
  9.   if prPgOrient = 0 then             // scaling factor between full sheet
  10.     M := 290/105                     // display and page header display
  11.   else
  12.     M := 290/148;
  13.  
  14.   TM := trunc(T * M + 0.5);
  15.   LM := trunc(L * M + 0.5);
  16.   RM := trunc(R * M + 0.5);
  17.   TS := trunc(S * M + 0.5);
  18.   if TM > 20 then TM := 20;           // to account for top margin being large
  19.   CurTab := LM+TS;
  20.  
  21.   bmp := TBitmap.Create;             //create bitmap
  22.   bmp.SetSize(TriangleSolution.Margin_Display.Width, TriangleSolution.Margin_Display.Height); //set bitmap size to the TImage size
  23.   with bmp.Canvas do         //draw on the bitmap, not directly on the control
  24.    begin
  25.      Brush.Color := clWhite;
  26.      FillRect(ClipRect);    //draw a white background
  27.      Pen.Color:=clBlack;
  28.      Pen.Width:=2;
  29.      MoveTo(0,40);                    // Draw Page outline
  30.      LineTo(0,0);
  31.      LineTo(290,0);
  32.      LineTo(290,40);
  33.  
  34.      Pen.Color:=clBlue;
  35.      MoveTo(LM,TM);LineTo(LM,35);     //  show margins
  36.      MoveTo(290-RM,TM);LineTo(290-RM,35);
  37.      MoveTo(LM,TM);LineTo(290-RM,TM);
  38.  
  39.      Pen.Color:=clRed;
  40.      Pen.Width:=1;
  41.      TM := TM+3;
  42.      for I := 1 to MaxTab do          //  show Tabs
  43.        begin
  44.          CurTab := Trunc(LM+I*TS);
  45.          MoveTo(CurTab,TM);LineTo(CurTab,TM+12);
  46.        end;
  47.    end;
  48.   TriangleSolution.Margin_Display.Picture.Bitmap.Assign(bmp); //load image from bitmap
  49.   bmp.Free;   //free bitmap
  50. end;
Best regards / Pozdrawiam
paweld

J-G

  • Hero Member
  • *****
  • Posts: 1198
Re: Confused ? - You will Be! - (well I am!)
« Reply #9 on: June 19, 2026, 10:21:03 pm »
In my opinion, the simplest solution would be to change the component type from TShape to TImage.
Steps to follow:
1. Remove the TShape component named Margin_Display from the printer settings panel
2. Drag and drop a TImage component (from the Additional palette) in its place, set its dimensions to the same values, and rename it to Margin_Display
3. Modify the code of the Show_Tabs procedure as shown below:

!!  @paweld  -  you're a STAR - thanks for that detailed solution - worked first time!

Although I have used Bitmap images in the past they have always been created externally - as you may see from the 'Reuleaux' image which pops up when an Equilateral triangle is solved. That is a .PNG file loaded into a TImage.  I hadn't ever considered creating one 'on the fly'.  As you'll see from the attached screen-shot I've marinally modified the previous display- matching the margin line style to that of the full page margin image.

A good lesson learned - I'm sure the concept will be useful in future.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

 

TinyPortal © 2005-2018