?
Solved

cusomizable tables in Delphi

Posted on 2005-03-27
9
Medium Priority
?
238 Views
Last Modified: 2011-04-14
Hi

How to create totally cusomizable tables on Form (or Memo)?
I want something like Microsoft Word has.
----------------------------------------------------------------------
For e.g. user type in edit boxes count of rows and columns, click on the button and table appear on the Form;
When user roll over column or row, cursor will change (crHSplit) and then user can resize columns and rows one by one...

Thanks in advance
0
Comment
Question by:prevarant
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
9 Comments
 
LVL 15

Expert Comment

by:mikelittlewood
ID: 13640236
You can limit the number of rows you display/ bring back from the database by just changing your SQL

ADOQuery.SQL.Text := 'SELECT TOP 10 * FROM YourTable';

if you wanted to get this value from an edit box you could

ADOQuery.SQL.Text := 'SELECT TOP ' + Trim(Edit1.Text) + ' * FROM YourTable';
0
 
LVL 15

Expert Comment

by:mikelittlewood
ID: 13640259
If you use an DBGrid, you can resize the columns just by selecting the title column splitter of the table.

I dont think you can alter the height of the rows though

You could alter row heights if you used a stringgrid
0
 
LVL 2

Author Comment

by:prevarant
ID: 13640273
I didn't mean database tables.
I want to build tables on Form's canvas (with canvas.lineTo and so on...);
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Author Comment

by:prevarant
ID: 13640409
Hi again

For e.g

when I create table 10 x 10 like this
//////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var
x,y,x_count,y_count:integer;
i,j:integer;
begin
x:=20;
y:=20;
x_count:=10;
y_count:=10;


        for i:=0 to x_count do begin
        form1.Canvas.MoveTo(x,Form1.Canvas.PenPos.Y+20);
        form1.Canvas.LineTo(300,form1.Canvas.PenPos.Y);
        end;
        form1.Canvas.MoveTo(x-28,y);
        for j:=0 to y_count do begin
        form1.Canvas.MoveTo(form1.Canvas.PenPos.x+(280 div y_count),y);
        form1.Canvas.LineTo(form1.Canvas.PenPos.x,220);
        end;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////This is not general example for creating tables on this way - just 10x10


How to, when click on column or row, change x or y position with mouse(when drag)?
And how to change cursor to crHSplit when I am over row or column?

If You still not understand, just try to build table with MIcrosoft Word...

Regards
Marko
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 13640533
Why don't use TStringGrid (or TListView) component ?
0
 
LVL 2

Author Comment

by:prevarant
ID: 13640892
It is complicated to explain...
0
 
LVL 15

Expert Comment

by:mikelittlewood
ID: 13641182
Use a TStringGrid
0
 
LVL 2

Author Comment

by:prevarant
ID: 13642816
Hi again

I know that is easy way to use TStringGrid but I must do like I wrote before...
>>It is complicated to explain...

Regards
Marko
0
 
LVL 34

Accepted Solution

by:
Slick812 earned 2000 total points
ID: 13664341
hello  prevarant , Here is some code for a form that has a TPaintBox on it, instead of doing the Grid Drawing on the Form, I used a TPaintBox, however if you require a Form to draw the grid on, then a TForm has the same methods (OnPaint, OnMouseDown, OnMouseUp, OnMouseMove) that the TPaintBox does. so you can just use the form's events.
I used two arrays of TRect for my grid line mouse position hit test containers. I set up the grind line array of TRect in the Forms OnCreate event, I have a grid cell height of 42 and a cell width of 63, with 8 Rows and 7 Columbs. The PaintBox1 size is height = 409, , width = 545, there are no other controls on the Form. The PaintBox1 OnMouseMove event will do a hit test in the 2 array of TRect to see if the mouse is over a grid line. In the Paint box OnMouseDown there is code to set the DragR record with info used to drag a grid line

code for form - -



unit EETest2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TDragRec = record
  // this carries info needed for grid line drag Operations
    Drag, Horz, First: Boolean;
    Index: Integer;
    movPt, Ext, Limit: TPoint;
    end;

  TForm2 = class(TForm)
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
   
  private
    { Private declarations }
    Rows, Cols: Integer;
    aryHRect: Array of TRect;
    aryVRect: Array of TRect;
    DragR: TDragRec;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.FormCreate(Sender: TObject);
var
rHeight, cWidth, i, amt, std: Integer;
begin
{I need to set up arrays of Rectangles for hit test areas used to detect mouse
 over for the grid lines in the PaintBox1 OnMouseMove Event.
 I have two rectangle arrays, one for vertical grid lines and one
 for horizontal grid lines}
DragR.Drag := False; // DragR.Drag is set to true when dragging a grid line
Rows := 8; // number of Rows
Cols := 7; // number of Columbs
rHeight := 42; // height of gird cell
cWidth := 63;  // wkidth of grid cell
SetLength(aryHRect, Rows+1); // hozizontal array
SetLength(aryVRect, Cols+1); // vertical array

amt := 14;// amount starts with the "Margin" of the grid, distance from border of PaintBox
std := amt+3+(Cols*cWidth); //  width of all Rectangles
for i := 0 to Rows do
  begin
{ I add Six to the amt, so there is a 3 pixel mouse over hit test on
  each side of a grid line}
  aryHRect[i] := Rect(17,amt,std,amt+6);
  // change the position of each Rect by the Height of a cell
  Inc(amt, rHeight);
  end;

amt := 14;
std := amt+3+(Rows*rHeight); // height of all rects
for i := 0 to Cols do
  begin
  aryVRect[i] := Rect(amt,17,amt+6,std);
  // change the position of each Rect by the width of a cell
  Inc(amt, cWidth);
  end;
end;

procedure TForm2.PaintBox1Paint(Sender: TObject);
var
i: Integer;
begin
// this will draw all of the grid lines based on the Rectangle positions in the 2 arrays
PaintBox1.Canvas.Pen.Color := clBlack;
PaintBox1.Canvas.Brush.Color := $FFF3E2;
PaintBox1.Canvas.Rectangle(PaintBox1.ClientRect);

for i := 0 to High(aryVRect) do
  begin
  // need to add 3 to rect Left for Vertical grid line pos
  PaintBox1.Canvas.MoveTo(aryVRect[i].Left+3,aryVRect[i].Top);
  PaintBox1.Canvas.LineTo(aryVRect[i].Left+3,aryVRect[i].Bottom);
  end;

PaintBox1.Canvas.Pen.Color := clRed;
for i := 0 to High(aryHRect) do
  begin
  // need to add 3 to rect Top for Horz grid line pos
  PaintBox1.Canvas.MoveTo(aryHRect[i].Left,aryHRect[i].Top+3);
  PaintBox1.Canvas.LineTo(aryHRect[i].Right,aryHRect[i].Top+3);
  end;
end;

procedure TForm2.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
i: Integer;
Pnt1: TPoint;
defCursor: Boolean;
begin
Pnt1 := Point(X, Y);
// get current cursor Pos in Pnt1
if DragR.Drag = True then // Now Dragging a grid line
  begin
  PaintBox1.Canvas.Pen.Mode := pmNot; // make Pen visible and eraseable
  if DragR.Horz then // Horizintal grid line drag
    begin
    // test for a Limit of drag movement, stay out of adjoining grid cells
    if (Pnt1.y < DragR.Limit.x) or (Pnt1.y > DragR.Limit.y) then Exit;
    if not DragR.First then  // do not erase on first drag move
      begin
      PaintBox1.Canvas.MoveTo(DragR.Ext.x,DragR.movPt.y);
      // this erases the drag line
      PaintBox1.Canvas.LineTo(DragR.Ext.y,DragR.movPt.y);
      end;
    DragR.First := False;
    DragR.movPt := Pnt1;  // reset move Point to current cursor Pos
    PaintBox1.Canvas.MoveTo(DragR.Ext.x,DragR.movPt.y);
    // draw new drag line
    PaintBox1.Canvas.LineTo(DragR.Ext.y,DragR.movPt.y);
    end else
    begin
    if (Pnt1.x < DragR.Limit.x) or (Pnt1.x > DragR.Limit.y) then Exit;
    if not DragR.First then
      begin
      PaintBox1.Canvas.MoveTo(DragR.movPt.x,DragR.Ext.x);
      PaintBox1.Canvas.LineTo(DragR.movPt.x,DragR.Ext.y);
      end;
    DragR.First := False;
    DragR.movPt := Pnt1;
    PaintBox1.Canvas.MoveTo(DragR.movPt.x,DragR.Ext.x);
    PaintBox1.Canvas.LineTo(DragR.movPt.x,DragR.Ext.y);
    end;
  Exit;  // if Dragging then Exit
  end;

//////  below is the test to see if cursor is over a Grid Line mouse Rectangle
defCursor := True;

for i := 0 to High(aryVRect) do // loop through all vertical grid line mouse Rects
  begin
  if PtInRect(aryVRect[i], Pnt1) then // PtInRect is fast test for cursor over grid line
    begin
    PaintBox1.Cursor := crSizeWE; // change cursor to indicate drag available
    defCursor := False; // set to False so cursor not changed to default
    Break;
    end;
  end;

if defCursor then
  for i := 0 to High(aryHRect) do // loop through all horizontal grid line mouse Rects
  begin
  if PtInRect(aryHRect[i], Pnt1) then
    begin
    PaintBox1.Cursor := crSizeNS;
    defCursor := False;
    Break;
    end;
  end;

if defCursor then
  PaintBox1.Cursor := crDefault;
end;

procedure TForm2.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
i: Integer;
Pnt1: TPoint;
begin
{in the Mouse Down you need to set DragR info to start grid line dragging}
Pnt1 := Point(X, Y);
if PaintBox1.Cursor = crSizeWE then // crSizeWE cursor tells you vertical drag
  begin
  for i := 0 to High(aryVRect) do // loop Vert rects to get Index
    if PtInRect(aryVRect[i], Pnt1) then
      begin
      DragR.Index := i;
      DragR.movPt := Pnt1; // set the move Point to the current cursor Pos
      DragR.Drag := True; // True for Dragging to happen in Mouse Move event
      DragR.First := True; // True to prevent erase line Draw
      DragR.Horz := False; // False to show vertical drag
      DragR.Ext.x := aryVRect[i].Top; // set line draw extents, height here
      DragR.Ext.y := aryVRect[i].Bottom;
  { you will need to set limits so you do not go into adjoining cells. the
    DragR.Limit will hold the two low and high limits, x for low and y for high.
    I use a setting here of 14 pixels for the minimum size that the cells
    can be dragged to. . there is also the 3 pixel rectangle coverage}
      if i = 0 then
        DragR.Limit.x := 7
        else
        DragR.Limit.x := aryVRect[i-1].Right+14;  // cell to left
      if i = High(aryVRect) then
        DragR.Limit.y := PaintBox1.Width-7
        else
        DragR.Limit.y := aryVRect[i+1].Left-14; // cell to right
      Break;
      end;
  end else
  if PaintBox1.Cursor = crSizeNS then // crSizeWE cursor tells you horizontal drag
  begin
  for i := 0 to High(aryHRect) do
    if PtInRect(aryHRect[i], Pnt1) then
      begin
      DragR.Index := i;
      DragR.movPt := Pnt1;
      DragR.Drag := True;
      DragR.First := True;
      DragR.Horz := True;
      DragR.Ext.x := aryHRect[i].Left;
      DragR.Ext.y := aryHRect[i].Right;
      if i = 0 then
        DragR.Limit.x := 7
        else
        DragR.Limit.x := aryHRect[i-1].Bottom+14; // cell above
                                        // same 14 pixel cell size minimum
      if i = High(aryHRect) then
        DragR.Limit.y := PaintBox1.Height-7
        else
        DragR.Limit.y := aryHRect[i+1].Top-14; // cell below
      Break;
      end;
  end;
end;

procedure TForm2.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
i: Integer;
begin
{ in the mouse up for a drag I will need to reset the index Rectangle
  to the new position and redraw the paint Box}
if DragR.Drag and not DragR.First then
  begin
  if DragR.Horz then
    begin
    aryHRect[DragR.Index].Top := DragR.movPt.y-3;
    // set new Rectangle Position
    aryHRect[DragR.Index].Bottom := DragR.movPt.y+3;
  // if the grid line defines a border (DragR.Index = 0) then I need to reset
  // all of the boundries in the array of Rectangles
    if DragR.Index = 0 then
      for i := 0 to High(aryVRect) do
      aryVRect[i].Top := DragR.movPt.y;
    if DragR.Index = High(aryHRect) then
      for i := 0 to High(aryVRect) do
      aryVRect[i].Bottom := DragR.movPt.y;

    end else
    begin
    aryVRect[DragR.Index].Left := DragR.movPt.x-3;
    aryVRect[DragR.Index].Right := DragR.movPt.x+3;
    if DragR.Index = 0 then
      for i := 0 to High(aryHRect) do
      aryHRect[i].Left := DragR.movPt.x;
    if DragR.Index = High(aryVRect) then
      for i := 0 to High(aryHRect) do
      aryHRect[i].Right := DragR.movPt.x;
    end;
  PaintBox1.Cursor := crDefault;
  end;
PaintBox1.Canvas.Pen.Mode := pmCopy;
if DragR.Drag and not DragR.First then PaintBox1Paint(PaintBox1);
DragR.Drag := False;
DragR.First := False;
end;

end.

 - - - - - - - - - -  - - - - - - - - - - - - - -  - -

I did not model this code operations after any other program (you mention the tables in the Word program), just my own code from doing this before.
ask question if you need more info
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month13 days, 3 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question