Recent

Author Topic: Canvas.Line not appearing on TPageControl tabs?  (Read 9643 times)

JoshM

  • Jr. Member
  • **
  • Posts: 57
Canvas.Line not appearing on TPageControl tabs?
« on: September 23, 2013, 07:16:54 pm »
How do I get this working? I had a big chunk of code where everything was working fine, except for this one problem of trying to use the canvas on the TPageControl tabs...even the SendToBack function doesn't work :(

The canvas is being placed behind the PageControls...is there anyway I get around this problem and place it above the page controls?

Thanks :)
« Last Edit: December 13, 2013, 08:18:13 pm by JoshM »

howardpc

  • Hero Member
  • *****
  • Posts: 3487
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #1 on: September 23, 2013, 08:13:33 pm »
There's not really enough to go on in what you've written so far. Best to paste some (perhaps stripped-down) code that 'doesn't work' so someone can suggest what you might do to achieve whatever effect you are after.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6462
    • wiki
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #2 on: September 23, 2013, 08:28:01 pm »
Look at package LazControls TExtendedNotebook.

You need GetTabRect.

The tabs can have negative coordinates. (WS dependent)

IIRC on GTK GetTabRect only works if PageControl is at Top/Left of form. Otherwise it returns incorrect...

JoshM

  • Jr. Member
  • **
  • Posts: 57
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #3 on: October 11, 2013, 10:33:30 pm »
There's not really enough to go on in what you've written so far. Best to paste some (perhaps stripped-down) code that 'doesn't work' so someone can suggest what you might do to achieve whatever effect you are after.

Well I've created a blank program just to try and get this working...here's all I have:

Code: [Select]

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExtendedNotebook1.ActivePage := TabSheet2;
  Canvas.Pen.Color := clRed;
  Canvas.Pen.Width := 3;
  Canvas.Line(0, 0, Form1.Width, Form1.Height);
end; 


And the canvas still stays behind the extendednotebook (previously tabsheets). I'm not really sure what Martin was saying about the GetTabRects function...how would I use that?

Thanks again :)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6462
    • wiki
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #4 on: October 12, 2013, 01:26:54 am »
The PageControl(as every WinControl) has ins own canvas.

It is not transparent, so it hides the form.

Look at the source of extended notebook. It does the drawing.

----------
Also, all drawing should be done in paint handlers. All else will probably end up in trouble

JoshM

  • Jr. Member
  • **
  • Posts: 57
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #5 on: November 12, 2013, 09:38:53 pm »
Sorry Martin...neither me nor my teacher understand what you mean. Would you mind posting a few lines of code or telling me what I need to research?

I've tried TabSheet1.Canvas which is what I thought you meant, but Lazarus doesn't allow this so I'm obviously mis-interpreting what you're saying. I get the "identifier idents no member "Canvas"" error...

As you can tell, I'm a beginner, so I'd be incredibly grateful for any help. Over the past month I've finalised the rest of the program, but just need to get this working :)
« Last Edit: November 12, 2013, 09:42:05 pm by JoshM »

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #6 on: November 12, 2013, 10:02:54 pm »
he means that the canvas reference in your button1click procedure references the form1.canvas and not the pagecontrol1.canvas which you need to access in order to paint on the page control instead of the form.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6462
    • wiki
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #7 on: November 12, 2013, 10:15:18 pm »
Your code
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
begin
  ExtendedNotebook1.ActivePage := TabSheet2;
  Canvas.Pen.Color := clRed;
  Canvas.Pen.Width := 3;
  Canvas.Line(0, 0, Form1.Width, Form1.Height);
end; 

**************************
Issue 1
This paint will be lost at random. because it is not persistent.
The window can get repainted for lots of reason, and then the line is lost.

Things like that must be done in OnPaint, or an inherited class, that overwrites one of the methods used in the paint event.

In this case the paint event of the PageControl, not of the Form

**************************
Issue 2

That is a method of TForm.
Canvas is Tform1.Canvas

However a TPageControl (and each page, IIRC) have there own canvas

On most OS a form with components is not a simple bitmap. Instead many (but not all)  of the components on the form are actually windows of them own (child windows of the form)

SO it has its own canvas.

You do need to use
  PageControl1.Canvas
or
  Form1.PageControl1.Canvas

------------------
But that is not all:

The coordinate y=0, X= 0 in a page control is not actually at the top left of the control.

It is at the top left of the embedded page. So right below the tabs.

So the first visible tab (they may be scrolled) is within for example
Y = -22 to Y =0
X = 0 to X = 100

That is where your line needs to go. (I have to check if it all applies to QT and GTK too)

There is an example that does this
components\lazcontrols\extendednotebook.pas

look at procedure TExtendedNotebook.PaintWindow(DC: HDC);

Maybe there is a PageControl.OnPaint that you can use. But I do not know, if it would work.

If not, you have to inherit a new class.

The Rectangle in which a certain tab can be found is returned by
   TPageControl.TabRect(index_of_tab);

BUT "TabRect" is buggy. It only works if the tab control is at x/y=0/0 of the form.





howardpc

  • Hero Member
  • *****
  • Posts: 3487
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #8 on: November 12, 2013, 11:55:37 pm »
Here's a very simple project showing a pagecontrol descendant that does some useless custom drawing on its tabs to get you started, based on the hints Martin gave.

JoshM

  • Jr. Member
  • **
  • Posts: 57
Re: Canvas.Line not appearing on TPageControl tabs?
« Reply #9 on: December 08, 2013, 08:49:10 pm »
Thanks for the solutions guys. Over the past 2 weeks, I've implemented the code Howard sent as well as finishing off the rest of the program. Strangely though, I've been getting one error which I can't seem to solve. First I'll just explain what I've done (using Howard's code):

1) Declare TNewPageControl as a new class/component based off of TPageControl.

2) At run-time, create NewPageControl1 and 'transfer' all tabsheets from PageControl1 (in other words, I've copied all the tabsheets & everything on them (their children) onto the newly created, NewPageControl1. I've done this using TabSheet1.Parent := NewPageControl1 and TabSheet1.PageControl := NewPageControl1 for both tabsheets.

3) Use a dynamic array of TPoint to store the line co-ordinates for the PolyLine procedure. I'm calling the modified PaintWindow procedure using NewPageControl1.Repaint - this correctly plots the lines

However, I keep getting the "invalid floating point operation error". I've been researching this for about an hour now, but can't seem to find any solution - this error seems to be mostly caused by bugs. As I'm a novice though, it's probably because I've made some silly mistake. I'm making a projectile motion simulator, however I don't think the error is caused by any invalid calculations (eg dividing by zero etc) because the simulation aspect of my program worked absolutely perfectly. The strange thing is that I can enter the same projectile stats (launch velocity, grav strength etc) and sometimes my program will crash instantly, whereas other times the projectile will travel nearly half way across the screen before getting this error...

Dell, Windows 7, 64 bit
Lazarus Version: 1.0.10
FPC: 2.6.2
SVN Revision: 41613

Does anyone have any ideas as to what could be causing this? Here's the relevant parts of code:


Code: [Select]

unit Unit1;


{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, TAGraph, Forms, Controls,
  Graphics, Dialogs, Buttons, ExtCtrls, ComCtrls, StdCtrls, types, wincrt, math,
  Windows;

type
   { TODPageControl }

  TNewPageControl=class(TPageControl)
  protected
    procedure PaintWindow(DC: HDC); override;
  end;

  { TForm1 }

  TForm1 = class(TForm)
    StartFlight1: TButton;
    SubmitFlightVars: TButton;
    //rest of components/functions/procedures
  private
     NewPageControl: TNewPageControl;
  public
    { public declarations }
  end;   


Code: [Select]

procedure TForm1.FormCreate(Sender: TObject);
begin

  NewPageControl := TNewPageControl.Create(Self);
  NewPageControl.Left := -2;
  NewPageControl.Top :=  -5;
  NewPageControl.Height := Form1.Height + 300;
  NewPageControl.Width := Form1.Width + 300;
  NewPageControl.Parent:=Self;
  TabSheet1.PageControl := NewPageControl;
  TabSheet1.Parent := NewPageControl;
  TabSheet1.Left := 0;
  TabSheet2.PageControl := NewPageControl;
  TabSheet2.Parent := NewPageControl;
  NewPageControl.ActivePage := TabSheet1;
  PageControl1.Destroy; 


Code: [Select]

procedure TForm1.Timer2Timer(Sender: TObject);
var
  ScreenHS, ScreenVS : real;
begin
       if (ScreenHS >= RightBound) or (ScreenVS > Form1.Height-Shape1.Height) or (xtime >= time*2) then begin
       CheckBox2.Enabled := False;
       Timer2.Enabled := False;
       end;

       xtime := xtime + 0.002*SimSpeed;
       UpdateScreenTime;
       hS := xtime*hV;
       vS := (v*Sin(trig)*xtime)-((g*xtime*xtime)/2);
       If CheckBox1.Checked = true then begin
       ScreenHS := Round(hS*Scale) + LeftBound;
       ScreenVS := Form1.Height - Round(vS*Scale) - Shape1.Height;
       end
       else if CheckBox1.Checked = False then begin
       ScreenHS := Round(hS) + LeftBound;
       ScreenVS := Form1.Height - Round(vS) - Shape1.Height
       end;

       Shape1.Left := Round(ScreenHS);
       Shape1.Top := Round(ScreenVS);

  end;   


Also, if this isn't a quick fix, I think I'll start a new thread for this error. It's probably quite likely I've done something wrong though

howardpc

  • Hero Member
  • *****
  • Posts: 3487
Re: [New Error] Canvas.Line not appearing on TPageControl tabs?
« Reply #10 on: December 08, 2013, 09:29:48 pm »
An immediate observation:
your local variables screenHS and screenVS are uninitialised (unknown garbage) when you first use them in Timer2Timer.
Without seeing more of your code it is difficult to comment further (for instance xtime and time may also be suspect, but you don't show where they are declared or initialised, so one can't say for sure).

JoshM

  • Jr. Member
  • **
  • Posts: 57
Re: [New Error] Canvas.Line not appearing on TPageControl tabs?
« Reply #11 on: December 10, 2013, 08:17:32 pm »
Wow it works like a charm! Rather than initialising them at a certain value, it was more appropriate to simply make both ScreenHS & ScreenVS gloabl - they're variables associated with the scaling of the projectile's path (to ensure it doesn't go flying off the screen/only travel a tiny distance).

Honestly you don't know how much stress your solution has just relived. I was amazed that the solution was that simply, but cheers for that anyway  :D

 

TinyPortal © 2005-2018