Software
Delphi and Lazarus
Trekking and Events
Blog and Forum
Delphi and Lazarus
 KControls Component Suite KGrid KHexEditor KIcon KMemo
 KGrid (23598x) KControls Component Suite (17236x) KHexEditor (5278x) KIcon (2584x) CAN Event Manager (437x)

# KControls Component Suite

KControls is a freeware distribution, a flagship of tkweb. It contains all of my published components for Delphi and Lazarus. All controls have been written with the aim to become both cross-IDE compatible (Delphi/C++Builder VCL and Lazarus LCL) and cross-platform compatible in Lazarus. There are some exceptions to this scheme, see below.

Components included
TKGrid - powerfull control for working with table data, replacement for TStringGrid and TDrawGrid - full compatibility and lot of new features
TKDBGrid - control for working with database tables, possible replacement for TDBGrid
TKMemo - native replacement for TMemo/TRichEdit - written from scratch, great features, full RTF support etc.
TKHexEditor - another useful control for binary file editing
TKIcon - powerfull component for working with icons and cursors (files *.ico and *.cur, works only on Windows)
TKPrintPreview - control for displaying print preview, it is part of KControls built in printing capabilities, every visual control supports printing and previewing
TKPrintPreviewDialog - nonvisual component - dialog - for an easy print preview implementation
TKPrintSetupDialog - nonvisual component - dialog - for an easy implementation of printing preferences
TKCustomControl - a base for your visual controls, for which you want to implement e.g. printing and previewing capabilities in Delphi or Lazarus (just 2 short functions to write).
TKNumberEdit - edit control to input numbers in various formats
TKFileNameEdit - edit control to input file names
TKLog - component for event logging
TKPercentProgressBar - custom drawn progress bar which shows actual percentage of the progress
TKBrowseFolderDialog - wrapper for the standard Windows API browse for folder dialog (works only on Windows)
TKBitBtn - like TBitBtn - draws PNG and alpha channel correctly in Delphi, has WordWrap property, works in Lazarus as well
TKColorButton - just another button to pick color
TKPageControl - page control written from scratch with custom painted tab panel, has tab icons and close button icon

## Notes

All controls support Delphi and Lazarus IDEs fully. But there are some exceptions: TKIcon and TKBrowseFolderDialog work only on Windows and printing and previewing might not work in some widgetsets in Lazarus.

Note about cross-platform development in Delphi: I strongly disagree with the way Embarcadero took with the FMX library to allow cross-platform development, so FMX will never be supported. As Lazarus has become very good IDE, in many aspects better than Delphi, I recommend you try it if you need cross platform features.

## Donations

If you want to donate for further development of KControls just think about building your own photovoltaics and using the WATTrouter device produced by our company. You will save lots of energy and it will be the best donation to me you can make!

## Repository - development versions

Important note: When installing the packages in Delphi XE2 and later you must add "Vcl;Vcl.Imaging" to Unit Scope Names in Delphi Options/Library! Otherwise the packages won't compile!

FileVersionNumber of
Available for:Changes
kcontrols_1.7.zip1.74738Delphi 7+,Lazarus 1.2.2+, C++Builder 2007+support for RAD Studio XE8, major work on TKMemo which is already usable, bugfixes...
kcontrols_1.6.zip1.62618Delphi 6+,Lazarus 1.2.2+, C++Builder 2007+support for RAD Studio XE6, Columns property in TKDBGrid, bugfixes...
kcontrols_1.5.zip1.5341Delphi 6+,Lazarus 1.2.2+, C++Builder 2007+new components TKMemo, TKBitBtn, TKColorButton, some bugfixes...
kcontrols_1.4.zip1.4984Delphi 6+, Lazarus 0.9.29(SVN#21827)+, C++Builder 2007+support for RAD Studio XE3-XE5, new components etc.
kcontrols_1.3.zip1.32710Delphi 6+, Lazarus 0.9.29(SVN#21827)+, C++Builder 2007+support for RAD Studio XE2
kcontrols_1.2.zip1.23077Delphi 6+, Lazarus 0.9.29(SVN#21827)+, C++Builder 2007+cumulative update (KGrid 1.7, KHexEditor 1.5, KIcon 2.2)
kcontrols_1.1.zip1.11086Delphi 6+, Lazarus 0.9.29(SVN#21827)+, C++Builder 2007+cumulative update (KGrid 1.6, KHexEditor 1.4, KIcon 2.1)
kcontrols_1.0.zip1.01682Delphi 6+,Lazarus 0.9.29(SVN#21827)+initial release (KGrid 1.5, KHexEditor 1.4, KIcon 1.9)

If you have a question you may ask below and I will probably answer it, after some time.

From: см
Hi,
I am trying to create a hypelink containg an image.
While doing it I got to troubles with LoadFromRTFStream.
The coded from snippet 1 works fine, but the one from snippet 2 is not.
Is it me who is doing something wrong or is there problem in the implementation of LoadFromRTFStream?

//Snippet 1
var
ImageMemo: TKMemo;
begin
ImageMemo := TKMemo.Create(Self);
ImageMemo.Blocks.Clear;
ImageMemo.SaveToRTF ('c:\tempimg.rtf');

KMemo1.Blocks.Clear;
end;

//Snippet 2
var
ImageMemo: TKMemo;
ImageStream: tstream;
begin
ImageMemo := TKMemo.Create(Self);
ImageStream := TStringStream.Create('');
ImageMemo.Blocks.Clear;
ImageMemo.SaveToRTFStream (ImageStream);

KMemo1.Blocks.Clear;
ImageStream.Free;
end;
From: tk

But you won't be able to save the image as hyperlink to rtf stream because it is not yet supported! Modifications are required in units kmemo as well as kmemortf.

From: см
Děkujem,
The solution with ImageStream.Seek(0, soFromBeginning);
works.
I realized, that I actually do not need hyperlinked images, since I need to display the contents of the image in another place.

So I did:
1.
procedure TForm1.KMemo1BlockClick(Sender: TObject; ABlock: TKMemoBlock; var Result: Boolean);
begin
if ABlock is TKMemoImageBlock then
begin
KMemo2.Blocks.Clear;
end;
end;

It ocurred that the KMemo1BlockClick does not get fired when an image is clicked. It seems like a bug to me?

2. I decided to try if copying a block to another memo will work. So I did:
procedure TForm1.KMemo1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
myblock: TKMemoImageBlock;
begin
if KMemo1.BlockAt(point(x,y)) is TKMemoImageBlock then
begin
myblock:=TKMemoImageBlock(KMemo1.BlockAt(point(x,y)));
KMemo2.Blocks.Clear;
myblock.ExplicitWidth:= 500;
end;
end;

When I did a mouse down:
1. The event fired
2. The image was displayed in the other TKMemo2
3. The image in TKmemo2 was selected just like in TKMemo1.
4. Images in both blocks got resized. Obviously the block is passed as a variable.
So here comes the second issue: How to copy the block, instead of referencing him? Maybe this is a general FPC question, I could ask in the Lazarus forum.
5. When I clicked on the image in TKMemo1 the application threw an exception (while the KMemo1MouseDown procedure was executed).
I guess there is some bug here or there is somethig which is not fully implemented?

I also wonder if there is way to prevent images from being selected? I tried myblock.Select(0,0,false); to diselect it, but in vain.
From: tk
1. Is true, images don't fire OnBlockClick - this feature is not implemented yet. There was conflict with selecting/dragging the images which must be resolved.

2. Ough this is a very wrong way! You must create a new TKMemo...Block, assign the properties using Assign method, then insert it to another Kmemo! Just like you would have to do it with any other similar object list member in Object Pascal!

From: см
Thanks, I googled „Assign‟, but it told me nothing else but „assign with :=‟.
I did

procedure TForm1.KMemo1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
SourceBlock: TKMemoImageBlock;
TargetBlock: TKMemoImageBlock;
begin
if KMemo1.BlockAt(point(x,y)) is TKMemoImageBlock then
begin
// KMemo2.LockUpdate;
SourceBlock:= TKMemoImageBlock(KMemo1.BlockAt(point(x,y)));
KMemo2.Blocks.Clear;
TargetBlock:= TKMemoImageBlock.Create;
TargetBlock.Image:= SourceBlock.Image;
targetblock.ExplicitWidth:= 200;
targetblock.ExplicitHeight:= 200;
// KMemo2.unLockUpdate;
end;
end;

but this method is extremely slow (188 ms, while the other method took 16 ms only).
Using KMemo2.LockUpdate; slowed performance even much more.

I tried to use TargetBlock.Image.Assign (SourceBlock.Image); and SourceBlock.Image.Assign (TargetBlock.Image); instead of TargetBlock.Image:= SourceBlock.Image; but in both cases the app crashes.
I also tried TargetBlock.Assign(SourceBlock);. In this case behaviour is okay, but performance is the same (188 ms).

Probably TargetBlock.Image:= SourceBlock.Image; does some convertions like Bmp->Pdf->Bmp?
Could there be a faster way?
From: tk
I am afraid you cannot speed this up. The image is always entirely copied (compressed to stream and decompressed) and does not use the default reference counted mechanism. It was introduced in r215 because of DPI dependent image scaling. Originally there was Image.Assign(TKMemoImageBlock(ASource).Image) but that did not work well in some cases, apparently due to bugs in LCL in some widgetsets.
It might be revisited later but now this will stay.

To (maybe!) speed this up you would need to copy the image directly to paint it somewhere else than in a second KMemo, eg. in a TImage component:

procedure TMainForm.Memo1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Block: TKMemoBlock;
Pict: TPicture;
begin
Block := KMemo1.BlockAt(Point(X, Y));
if Block is TKMemoImageBlock then
begin
Pict := TPicture.Create;
try
Pict.Assign(TKMemoImageBlock(Block).Image);
// do something with the image, eg.
Image1.Picture := Pict;
finally
Pict.Free;
end;
end;
end;
From: см
Podivuhodný! Execution took 0 ms.
I was ecpecting this to be the slower way, but obviously I was infinitely wrong.
From: RusMikle
Hi!
Problem misalignment in TKGrid by halCenter, valCenter and Font.Orientation:=900:

KGrid1.CellSpan[0, nT] := MakeCellSpan(1, 10);
KGrid1Cells[0, nT] := '0123456789';

with TKGridAttrTextCell(KGrid1.Cell[0, nT]) do
begin
Font.Assign(KGrid1.Font);
Font.Orientation:=900;
Font.Style := [fsBold];
VAlign := valCenter;
HAlign := halCenter;
.........
See result:
http://www.superbasis.de/2017_01_18_16_39_03_.jpg

(Lazarus 1.7, Windows 10, 7 kcontrols 1.7)
From: tk
Font orientation other than default is not supported! You have to paint your cell in OnDrawCell.
From: см
Hi,
I am trying to do some manipulation on a hyprlink when I click on it (in TKMemo).
I tried to add an OnMouseMove event in kmemo.pas but it just won't fire.
Probably there is some other way to achieve it?
OnBlockClick won't do, because it handles only left mouse button.
From: см
Actually I need to handle both cases: when the mouse is over a hyperlink and when a hyperlink is clicked.
Maybe the most forward method would be to add a variable, which would store the Hyperlink when the TKMemoHyperlink.WordMouseAction event is triggered, but I still see some possible problems there.
From: tk
Well this would require OnBlockMouseDown, OnBlockMouseMove and maybe also OnBlockMouseUp. I'll see what can be done.
From: см
Or maybe if there is a function to return the selected block at given coordinates (X and Y) of the TKMemo? This way general TKMemo events could be used
... OnKMemo1MouseMove/Up/Down... GetBlockAtXY(X_from_mouse_move,X_from_mouse_move)... ?
From: tk
Or in case of the table, a combination of PointToBlocks and PointToBlock?

PointToBlocks should give the innermost Blocks (here Cell.Blocks)
and PointToBlock then the block (hyperlink) at given position.

This would need some playing though as there is not yet a high level method directly implemented in the TKCustomMemo class...
From: tk
Have you tried TKMemoBlocks.PointToBlock?
From: см
So far I have tried the code below, but none of the
if .... is TKMemoTextBlock then
cases got fulfilled.

procedure TForm1.Button4Click(Sender: TObject);
var
ParentTable: TKMemoTable;
imgblock: TKMemoImageBlock;
debprn: integer;
row, clm: integer;
celltop: integer;
begin
ParentTable.ColCount:=3;
ParentTable.rowCount:=150;
for row:=0 to ParentTable.RowCount-1 do
for clm:=0 to ParentTable.colCount-1 do
ParentTable.CellStyle.BorderWidth:=1;
ParentTable.ApplyDefaultCellStyle;

debprn:= ParentTable.Cells[2,1].Left;
celltop:= ParentTable.Cells[1,21].top;
debprn:= ParentTable.Cells[1,20].Height;
debprn:= ParentTable.Cells[1,20].Width;
end;

procedure TForm1.KMemo1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
mypoint:TPoint;
myblock: TKMemoBlock;
myblocktext: String;
begin
begin
mypoint.x:= x;
mypoint.y:= y;
myblock:= KMemo1.Blocks.PointToBlock(mypoint);
if myblock is TKMemoTextBlock then
begin
label1.Caption:=myblock.Text;
end;
if TKMemoTextBlock(myblock.Parent) is TKMemoTextBlock then
begin
label1.Caption:=myblock.Text;
end;
if TKMemoTextBlock(TKMemoTextBlock(myblock.Parent).Parent) is TKMemoTextBlock then
begin
label1.Caption:=myblock.Text;
end;
end;
end;
From: tk
Again it was far more playing than I expected.
Use the new TKMemo.BlockAt method.
It returns the innermost block at given position.
It works even for relative and absolute positioned containers and their innermost blocks.

procedure TMainForm.Memo1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Block: TKMemoBlock;
begin
Block := KMemo1.BlockAt(Point(X, Y));
if Block is TKMemoTextBlock then
Label1.Caption:= TKMemoTextBlock(Block).Text;
end;
From: см
Thanks, I trying and it seems to work just fine!
From: см
... but I wonder if a name like BlockAt wont be confusing?
Maybe GetBlockAt is better?
From: tk
I don't like Get/Set prefixes for other methods than property getters and setters. Even somewhere I've read an article about it but don't know where anymore.
From: СМ
Hi Tk,
A few days ago I mentioned that I had no problems with nested tables but now it occurs, that content of nested tables overlap neighbouring cells (on the right).
Actually this is the result of the parent table NOT self resizing- it stays with the size of the KMemo in which it is located.
I have explicitly set MyKmemo.ScrollBars:=ssBoth; and ParentTable.FixedWidth:=false; but it still does not get resized out of the KMemo. Horizontal scrollbar is not shown, only a vertical one.

I tried to reproduce standalone with a simpler case, but the problem is not occuring there.
Do you have an idea what might be the reason for this and how to get around it?
From: СМ
I have sucessfully reproduced it in a standalone test.
There is something wrong in merged cells. The source which demontrates the issue follows below:

uses
...kfunctions...

procedure MergeCells(var aTable: TKMemoTable; aLeft: integer; aTop: integer; aRight: integer; aBottom: integer);
var
MergeSpan: TKCellSpan;
begin
MergeSpan.ColSpan:=aRight-aLeft+1;
MergeSpan.RowSpan:=aBottom-aTop+1;
aTable.CellSpan[aleft,atop]:=MergeSpan;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
row, col: integer;
aMemoTable: TKMemoTable;
ParentTable: TKMemoTable;
imgblock: TKMemoImageBlock;
begin
ParentTable.ColCount:=2;
ParentTable.rowCount:=4;
MergeCells(ParentTable,0,1,1,1);
ParentTable.CellStyle.BorderWidth:=1;
ParentTable.ApplyDefaultCellStyle;

aMemoTable.ColCount:=20;
aMemoTable.rowCount:=5;
aMemoTable.ColWidths[2]:=20;
for row:=0 to trunc((aMemoTable.rowCount -1)/2)-1 do
for col:=0 to aMemoTable.ColCount -1 do
begin
aMemoTable.Cells[col,row*2].Blocks.AddTextBlock ('Row' + IntToStr(row) + 'Column1'+IntToStr(col)) ;
end;
aMemoTable.CellStyle.BorderColor:=clBlue;
aMemoTable.CellStyle.BorderWidth:=1;
aMemoTable.ApplyDefaultCellStyle;

end;
From: tk
Thanks for the sample (had to adapt it a bit, again it used unsupported empty cells). There was a bug indeed - merged cells were measured incorrectly. The problem occured not only for nested tables but for long words as well. I've fixed some other minor problem with table layout calculation.
From: СМ
Hi, I have not tested all the previous cases yet, but since now I see the following problem: The rightmost column is cropped from the left, but no horizontal scroll bar is shown.
This happens in tables in which there is no long words so there is no reason to make the columns so wide and it seems like a regression to me.
In cases where tables is wider and horizontal scrollbars are shown, still the rightmost column is cropped.
Could this be due to to having spacing on the left side of the table. I also wonder, is there a way to remove this spacing between the tables and the borders of the memo?
From: tk
I cannot reproduce the cropping with the above sample and any of my other test tables.

Column widths for columns participating in a merged cell are now set equally to merged_cell_width/number_of_merged_column. That maybe causes your non-merged cells to be wider than they should be. To fix this, more 'clever' algorithm would be needed but I have no time for this now. So either use simpler tables or provide a patch to me.
From: СМ
I have done some other testing, I have reproduced it without merging and withiut nesting tables, with the code below. It uses an image with dimensions W1300; h1712, but in some cases I see the problem without an image.
In the example the rightmost characters are not visible (actually say 10% of the last but one character is visible).
Could this be a Lazarus problem only, not happening in Delphi?
I have used the default font.
I could upload the image somewhere if you consider it useful.

procedure TForm1.Button2Click(Sender: TObject);
var
ParentTable: TKMemoTable;
imgblock: TKMemoImageBlock;
begin
ParentTable.ColCount:=2;
ParentTable.rowCount:=3;
ParentTable.CellStyle.BorderWidth:=1;
ParentTable.ApplyDefaultCellStyle;
end;
From: tk
I can confirm this is Lazarus problem only. One time resizing of the KMemo fixes this, now to find out what is the cause.
From: СМ
KMemo1.Width:=KMemo1.Width+1;
KMemo1.Width:=KMemo1.Width-1;
even *before* creating the table solves the issue. Probably dimensions are improperly stored somewhere upon creation of the form?
From: tk
Found the reason: Bad fix in kcontrols.pas made in r258: "Scrollable controls: Fixed dragging in Lazarus designer.". Hopefully now ok (it is hard to test these issues, LCL is different from VCL, then differences between LCL widgetsets etc. Found a bug in Carbon widgetset: http://bugs.freepascal.org/view.php?id=30910 and another bug in this widgetset regarding the caret, will try to isolate later).
From: СМ
Thanks for the fixes!
So far it seems okay here (Lazarus on Win 7).

Just for the record, there is just one minor flaw:
- The distance between the left border of the table and the left border of the TKMemo is 6 pixels.
- The distance between the top border of the table and the top border of the TKMemo is 6 pixels.
- The distance between the RIGHT border of the table and the right border of the TKMemo is 5 pixels.

I suppose these values are hardcoded to 6, so the distance on the reight shall also be 5 (not 6).
From: tk
Indeed there still was a glitch, the scrollbar ranges were calculated slightly incorrectly in some cases! I modified the scrollbar range calculations for KMemo.

I did not see that before because recently I always used a wide padding for the document area (it is not hardcoded to 5 but default value is 5 as you can see in TKCustomMemo.Create, note also there is some non-client area - window border - of the KMemo window that might use the same color as KMemo background color, so it might confuse when doing exact pixel calculations). You can change that padding by eg. TKMemo.ContentPadding.All := 20 and you get 20 pixels padding on all sides.

Anyway, great testing, thank you!
From: СМ
„note also there is some non-client area - window border - of the KMemo window that might use the same color as KMemo background color‟
Indeed, there is always 1 pixel at least between both borders, so actual displayed distance is 1 + ContentPadding
I have set
KMemo.BorderStyle := BsNone;
and now everything looks just as I want it to ;)
From: tk
I had to revert some things about table layout calculation back. Column scaling did not work as I needed for one my project. But your sample still works for me. I further improved the size calculation for merged cells, you may check it out. However, the algorithm still has potential for improvements, it does not yet behave eg. the way web browser table algorithms do.
From: см
I tried the latest release, there seemed to be some problems, but I have found problems in my code and now they are gone.
One of the problems was that the scrollbar moved to the middle of the table after reaching the bottom of the table (when keeping PGDown pressed).
It occurred that I had an unused row (actually the last one), for which I have not done FixEmptyBlocks. When I removed it, the scrolling issue disapeared.
But maybe it would be useful to have a FixEmptyBlocks routine applying to the entire table?
From: tk
Yes, some FixEmptyCells or so could prove useful.
From: СМ
Hi Tk,
I am adding images in table cells (in tables in TKMemo).
I need to rezise them keeping the proportions.
I try to use the code given below.
It does not work, because I use KMemo1.LockUpdate . Without it it works.
I wonder if this behaviour is proper (return ImgBlock.Width and ImgBlock.Height when the table is locked) or is this a bug?
I also wonder which is the best way to resize the images?
I could unlock the table and lock it after adding the image, but I guess it will decrease performance.

procedure TForm1.Button1Click(Sender: TObject);
var
aMemoTable: TKMemoTable;
imgblock: TKMemoImageBlock;
Ratio: integer;
debvar: integer;
begin

KMemo1.LockUpdate;

aMemoTable.ColCount:=5;
aMemoTable.rowCount:=5;
aMemoTable.ColWidths[2]:=20;

debvar:= ImgBlock.Width;
debvar:= ImgBlock.Height;

Ratio:= trunc(imgblock.Width/imgblock.height);
imgblock.ExplicitWidth:=100;
imgblock.ExplicitHeight:=100*Ratio;

KMemo1.unLockUpdate;
end;
From: СМ
It is me again. I have found a solution: use „imgblock.Image.Width‟ instead of „imgblock.Width‟.
From: tk
You did well (you could also use ImageWidth/ImageHeight). To use generic Block.Width KMemo needs to update(measure) the document first, which is blocked inside the LockUpdate/UnlockUpdate pair. Many other TKMemo...Block and/or TKMemoBlocks properties do not work here and need the document update as well.
From: СМ
It does not get clear from documentation- are images converted to RTF and then displayed or in the RTF is added a hyperlink to them?
Is it possible to use both ways?
From: tk
I do not fully understand what you want to do, or how this corresponds with the original question, but RTF streaming has nothing to do with image painting.

In RTF, images are stored at the position where they appear in the document. Furthermore, Word adds many backward compatibility tags to saved images and saves the image twice (eg. for png it saves the image as png and then as old styled wmf). This is because eg. Wordpad cannot read the png but only the old wmf (even Wordpad distributed with Windows 10, welcome to the M$world!). You would have to study RTF specification for more details but even this spec. does not say everything and you have to study saved RTF documents. inserted: 2017-01-10 15:44:03 Reply... From: СМ It is not really related to the previous thread, but since it is related to images I did not start a new one. What I meant is, that images can: Method 1. Be converted to something, then added (hardcoded) in the RTF file. This way the RTF will be displayable as a standalone file. or Method 2. Images can not be stored in the RTF, but accessed from an external resource. I googled this way of usage, which I have used some time ago: {\field{\*\fldinst{INCLUDEPICTURE "c:\\\\filename.bmp" MERGEFORMAT \\d \\w3000 \\h4500 \\pm1 \\px0 \\py0 \\pw0}}} After posting the question, I have found experimentally, what you have explained above: method 1 is used, but it would be good to be mentioned in documentation of TKMemo. When possible, I will try if method 2 is usable with TKMemo, as I assume that it would be away faster in some cases. inserted: 2017-01-10 23:07:18 Reply... From: tk I did not know about method 2. KMemo only supports method 1 now. To use method 2 RTF streaming would need some changes and KMemo as well (to store referenced image list etc.). INCLUDEPICTURE field is mentioned in the RTF specification 1.9 but no additional info is available. I am not very happy to implement something that is not specified. inserted: 2017-01-11 09:25:39 Reply... From: СМ Thanks for the info. Since no one asked before, support for linked images would not be much demanded, unlike some other feaures. inserted: 2017-01-04 10:29:20 Reply... From: СМ Hi, Is it possible to make a column in a table in a TKMEMO as narrow as possible to fit the text within? It occurs that MyTable.Cells[0,0].CurrentRequiredHeight and MyTable.Cells[0,0].RequiredHeight gives some other information, so they cannot be used to determine the required width? inserted: 2017-01-04 23:15:38 Reply... From: tk Currently not, there is no column autosizing implemented. Now it is only possible to specify fixed column width with Table.ColWidths. The fixed column width will be respected if the table fits into KMemo window. There is also possible to set fixed width of entire table but it is still somewhat buggy. inserted: 2017-01-06 08:38:37 Reply... From: СМ Thanks! I will try to find a workaround for the timebeing. inserted: 2017-01-04 08:41:02 Reply... From: СМ Hi Tk, When executing the code below, the Block Border (gray one) on the left and bottom is within the borders of the individual cells. I have found a workaround with MyTable.BlockStyle.LeftMargin:=-4; MyTable.BlockStyle.BottomMargin:=-4; but I guess there is actually a bug in this case? procedure TfrmMain.Button6Click(Sender: TObject); var MyTable: TKMemoTable; row: integer; clm: integer; begin kmMain.Blocks.clear; MyTable:= kmMain.Blocks.AddTable; MyTable.ColCount:=5 ; MyTable.rowCount:=5 ; MyTable.CellStyle.LeftMargin:=1; MyTable.CellStyle.rightMargin:=1; MyTable.CellStyle.TopMargin:=1; MyTable.CellStyle.BottomMargin:=1; MyTable.BlockStyle.BorderColor:=clLtGray; MyTable.BlockStyle.BorderWidth:=2; MyTable.ApplyDefaultCellStyle; for row:=0 to 4 do for clm:=0 to 4 do begin MyTable.Cells[clm,row].Blocks.AddTextBlock (IntToStr(row) + ';' + IntToStr(clm)); MyTable.Rows[Row].Cells[Clm].BlockStyle.BorderWidth:=1; end; end; inserted: 2017-01-04 22:55:21 Reply... From: tk Yes there was bug, I've fixed this already. inserted: 2016-12-27 15:45:46 Reply... From: Josh KGRID and OSX ? Hi, I am using latest lazarus trunk and bitbucket version of Controls, I can copile and add the kcontrols to lazarus, the problem is that I have a windows project that has a few kgrid that compile and run under windows; when I compile prject on osx; after setting compile options for osx; when I choose compile it starts to compile but then lazarus abrubptly terminates without generating an error. I cannot then open the project again; as soon as it starts to open project it then again abruptly terminates. If I remove the grids from the project on windows mahine and then open it on OSX te applicaton will open and compile and run. As soon as I add a kgrd; have major issue on OSX. Sorry for the wall of text; just trying to explain as best as I can. inserted: 2016-12-27 23:40:45 Reply... From: tk And the KGrid demo project opens/runs fine? Note 1. There is an imaging bug on OSX in the TKAlphaBitmap that is used for misc. imaging in KControls, with all relevant images painted incorrectly. Note 2. I only tested KControls on a virtual MAC with El Capitan. Don't have access to a real MAC. But except for the above problem all demos compile/run fine. inserted: 2017-01-02 20:30:21 Reply... From: tk The imaging bugs were fixed in the trunk. inserted: 2016-12-19 12:07:17 Reply... From: СМ Hi, I am trying to do the following: When a double click is done in a cell to determine the clicked cell (or row) and to do something with its contents. I actually need the row index. But I've come across 2 problems: 1. I have var ... TBL: TKMemoTable; begin ... TBL:= kmMain.Blocks.AddTable; tbl.OnDblClick:= @OnTableDblClick; With this code the OnTableDblClick is never executed. In other words the OnDoubleCLick event is not firing. For example if I do kmMain.OnDblClick:= @OnTableDblClick; the event is firing. 2. I cannot determine in which cell/row the DoubleCLick occurs. The good old way for ... if cell[x,y].active is not present. Maybe I could use something else? inserted: 2016-12-21 09:51:51 Reply... From: tk Hmm, this appears to be a little bit tricky. Because the table is basically a set of nested containers and OnDblClick is called only once and for the innermost block/container, you have to use the new TKMemo.OnBlockDblClick and search for a block of interest: ... KMemo1.OnBlockDblClick := EventBlockDblClick; ... procedure TMainForm.EventBlockDblClick(Sender: TObject; ABlock: TKMemoBlock; var Result: Boolean); var Block: TKmemoBlock; begin Block := ABlock; while (Block <> nil) and not (Block is TKMemoTableCell) do Block := Block.ParentBlocks.Parent; // Block is either nil or TKMemoTableCell here if Block <> nil then begin // do your stuff Result := True; end; end; Please also download the newest fix from trunk. The event was not firing for the cell area not occupied by the cell content. You may also use the new TKMemoTableCell's read only properties ColIndex and RowIndex to find the cell's position in the table. inserted: 2016-12-23 08:07:22 Reply... From: СМ Once again, thanks for the support! As far as I have used it t works fine. But it is tricky indeed... it occurs that if I click in a nested table I gets the cell in the nested table instead of the parent one (makes perfect sense). I still have not thought about that and if it will be a serious obstacle. Current TKMemo documentation says, that nested tables are not supported, but so far I've had no troubles with them (except that I do not know how to provide some distance between them and the parent ones). Is it because doc is not updated? inserted: 2016-12-23 11:12:33 Reply... From: tk Nested tables are supported in KMemo but you won't be able to load/save them from/to RTF. The doc is not ready by far, only the short introductory document. There are still important features to be done in KMemo so I don't want to write the doc until they're finished. You should be able to find the cell in the main table if you click on the nested table, but you have to extend the logic in EventBlockDblClick, eg. (writing from memory, haven't tried): procedure TMainForm.EventBlockDblClick(Sender: TObject; ABlock: TKMemoBlock; var Result: Boolean); var Block: TKMemoBlock; Cell: TKMemoTableCell; WeAreInNestedTable: Boolean; Row, Col: Integer; begin Cell := nil; // find nearest table Block := ABlock; while (Block <> nil) and not (Block is TKMemoTable) do begin if Block is TKMemoTableCell then Cell := Block as TKMemoTableCell; // this is the innermost cell (either in nested or main table) Block := Block.ParentBlocks.Parent; end; WeAreInNestedTable := (Block <> nil) and (Block.ParentBlocks.Parent is TKMemoTableCell); if WeAreInNestedTable then Cell := Block.ParentBlocks.Parent as TKMemoTableCell; if Cell <> nil then begin // Here Cell is always in the main table Col := Cell.ColIndex; Row := Cell.RowIndex; // do your stuff Result := True; end; end; inserted: 2016-12-23 11:46:51 Reply... From: СМ Thanks, I have just managed to do it myself by looping up once again until I reaching a higher level ;) inserted: 2016-12-23 11:49:44 Reply... From: СМ Exact solution is ... begin Block := ABlock; while (Block <> nil) and not (Block is TKMemoTableCell) do //Search up until parent is a table cell Block := Block.ParentBlocks.Parent; // Block is either nil or TKMemoTableCell here if Block <> nil then //search one level up to check if the tabel is nested begin BlockNested:= Block.ParentBlocks.Parent; while (BlockNested <> nil) and not (BlockNested is TKMemoTableCell) do //Search up until parent is a table cell BlockNested := BlockNested.ParentBlocks.Parent; end; if (BlockNested is TKMemoTableCell) then begin Block:= BlockNested; end; begin // do your stuff ... Of course, searching up until findind the topmost table could be implemented, but in my case I am sure, that I have only 1 nesting level. inserted: 2016-12-14 16:01:40 Reply... From: СМ Hi, there is some problem with scrolling and selecting lines and cell elements. After running the following code (Lazarus on Win7), I can select text or focus text from approximately first half (upper part) of the tables. When I press PageDown, the cursor and scrollen never gets to the last row, but loops between row 55 and 85 (approximately). Changing the value of ReadOnly makes no difference. procedure TForm1.FillGrid; var TSIndex: integer; RealRes: string=''; AddMat: string=''; TBL: TKMemoTable; StepBlock: TKMemoTextBlock; Mytable: TKMemoTable; clmStep: integer=0; clmInput: integer=1; clmOutput: integer=2; clmTestResult: integer=3; clmReport: integer=4; clmComment: integer=5; clmReqs: integer=6; clmStepOffset: integer=4; clrInputOutput: TColor=clWhite ; clrRealResult: TColor=clBlue; clrReqRep: Tcolor=clLtGray; begin KMemo1.Blocks.Clear; TBL:= KMemo1.Blocks.AddTable; tbl.LockUpdate; TBL.CellStyle.BorderWidth := 1; TBL.ColCount := 4; tbl.ColWidths[clmStep]:=20; tbl.ColWidths[clmTestResult]:=20; //WARNING: RowCOunt shall be defined after ColCount. Otherwise the app will crash. TBL.RowCount:= 100*3+1; tbl.ApplyDefaultCellStyle; for TSIndex :=0 to 300 do begin tbl.Rows[TSIndex].FixedHeight:=true; tbl.RowHeights[TSIndex]:=10; end; for TSIndex:=0 to 100-1 do begin MergeCells (tbl,clmTestResult,TSIndex*3+0,clmTestResult,TSIndex*3+2); TBL.Cells[clmTestResult,TSIndex*3+0].Blocks.Text :=IntToStr (clmTestResult) + '; ' + IntToStr(TSIndex); TBL.Rows[TSIndex*3+0].Cells[clmTestResult].BlockStyle.Brush.Color:= clGreen; TBL.Cells[clmInput,TSIndex*3+0].Blocks.Text:=intToStr (clmInput) + '; ' + IntToStr(TSIndex); TBL.Rows[TSIndex*3+0].Cells[clmInput].BlockStyle.Brush.Color:= clrInputOutput; TBL.Cells[clmOutput,TSIndex*3+0].Blocks.Text:=intToStr (clmOutput) + '; ' + IntToStr(TSIndex);; TBL.Rows[TSIndex*3+0].Cells[clmOutput].BlockStyle.Brush.Color:= clrInputOutput; TBL.Cells[clmInput,TSIndex*3+2].Blocks.Text:='aaa' ; TBL.Rows[TSIndex*3+0].Cells[clmInput].BlockStyle.Brush.Color:= clrReqRep; TBL.Cells[clmOutput,TSIndex*3+2].Blocks.Text:='bbb'; TBL.Rows[TSIndex*3+2].Cells[clmOutput].BlockStyle.Brush.Color:= clrReqRep; MergeCells (tbl,clmStep,TSIndex*3+0,clmStep,TSIndex*3+2); AddMat:='ccc'; StepBlock:=TBL.cells[clmStep,TSIndex*3+0].Blocks.AddTextBlock(AddMat); StepBlock.TextStyle.Font.Name:='Segoe UI Symbol'; StepBlock.WrapMode; end; //for TSIndex TBL.UnlockUpdate; end; inserted: 2016-12-14 21:04:34 Reply... From: tk Can't compile the sample: Error: Identifier not found "MergeCells" inserted: 2016-12-16 08:36:38 Reply... From: СМ Opps, my bad. Now I have put it in a separate project to make sure everything will be fine. Probably I could upload the project somewhere? Anyway, the missing source is below: uses ... kfunctions... procedure MergeCells(var aTable: TKMemoTable; aLeft: integer; aTop: integer; aRight: integer; aBottom: integer); var MergeSpan: TKCellSpan; begin MergeSpan.ColSpan:=aRight-aLeft; MergeSpan.RowSpan:=aTop- aBottom; aTable.CellSpan[aleft,atop]:= MergeSpan; end; inserted: 2016-12-17 16:06:58 Reply... From: tk Made now few bugfixes (regarding mouse selection, keyboard movement, table copy/paste behavior) because your example showed me them. Some things were broken again due to new features added to KMemo. Generally you should not use empty cells as I said plus each cell should end with a paragraph. inserted: 2016-12-16 21:33:56 Reply... From: tk Thank you it works now for me. Please don't keep empty rows/cells. As I just observed, KMemo cannot handle them properly yet (keyboard movement, mouse selection etc.). Also delete the FixedHeight/RequiredHeight stuff, since all cells will be non-empty and Kmemo can then properly calculate their heights. So modify your code as shown: ... TBL.RowCount:= 100*3; tbl.ApplyDefaultCellStyle; { for TSIndex :=0 to 300 do begin tbl.Rows[TSIndex].FixedHeight:=true; tbl.Rows[TSIndex].RequiredHeight:=10; end; } for TSIndex:=0 to 100-1 do begin ... your stuff for I := 0 to TBL.ColCount - 1 do begin TBL.Cells[I,TSIndex*3+0].Blocks.FixEmptyBlocks; TBL.Cells[I,TSIndex*3+1].Blocks.FixEmptyBlocks; TBL.Cells[I,TSIndex*3+2].Blocks.FixEmptyBlocks; end; end; ... inserted: 2016-12-19 08:34:01 Reply... From: СМ Thanks TK, It seems to work perfrectly now. By the way I understood you, there is a bug and this is a hack for it (would be useful to know for further usage)? inserted: 2016-12-19 09:49:37 Reply... From: tk I would not call that bug. Empty cells are just not supported yet. In future they might be. However, MS Word always places at least one paragraph to a table cell. You won't get empty cell when loading the table from RTF produced by Word. I kept absolute freedom for creating a document programmatically in KMemo. Downside of this freedom is you have to be extra careful about what you're doing and you have to test each new step (ie. step not shown in the demos) thoroughfully. I remember having similar problems when creating a (visually attractive) welcome page for one our project (entirely built with KMemo, normally eg. Delphi use web browser component for that). Even I don't know what everything KMemo already can do and I am the author of KMemo... inserted: 2016-12-19 11:59:43 Reply... From: СМ Thanks for the clarification, I am adding these notes in the Manual. I wonder if it would be useful to have an additional parameter for FixEmptyBlocks or for AddParagraph setting the font size. Sometimes it makes sense to have empty rowa a little it shorter. Currently, I have solved this by manually changing the font size for such lines (when necessary). inserted: 2016-12-21 10:05:35 Reply... From: tk FixEmptyBlocks only adds a paragraph block if the blocks are empty (or have only containers). The paragraph block alone should not include any additional size constraints to the blocks, ie. should not influence their measurement/painting at all. If it still does somewhere (was the case in older KMemo versions), then certainly it is a bug. inserted: 2016-12-12 13:53:36 Reply... From: СМ Hi, I wonder what would be the best way to add an image as a hyperlink? Is there some inbuilt capability? inserted: 2016-12-14 20:56:29 Reply... From: tk Not supported yet, but i think not difficult to add. inserted: 2017-01-03 08:15:15 Reply... From: СМ First of all- Happy new year! Second- is this in the todo list for the near future (just to know if I should search a workaround?) inserted: 2017-01-05 10:17:52 Reply... From: tk Thank you. This feature is nowhere near in the todo list but I am aware of it. When changes will be done in this area then there is big chance this will be implemented as well. It might be not so easy as I originally assumed, because we have RTF streaming and it must be changed there too. inserted: 2016-12-08 13:29:06 Reply... From: nosctradamus i would like to show a icon inside a row of specific column, but i dont know how to. This is my code at moment: write in DrawCell Event of TKDBGrid with TKCustomGrid(Sender) do begin Cell[ACol, ARow].ApplyDrawProperties; if (ACol = 1) then begin kgdAtend.Canvas.FillRect(R); if (Cells[1, ARow] = 'Y') then begin // resolved imgTips.Draw(kgdAtend.Canvas, R.Left + 16, R.Top + 1, 0); end else if (Cells[1, ARow] = 'N') then begin //not resolved imgTips.Draw(kgdAtend.Canvas, R.Left + 16, R.Top + 1, 1); end else begin //empty list CellPainter.DefaultDraw; end; end; end; inserted: 2016-12-08 18:51:05 Reply... From: admin Try replacing kgdAtend.Canvas with CellPainter.Canvas. inserted: 2016-12-09 11:16:37 Reply... From: nosctradamus Thanks for the answer admin. But dont work as i expected. After replacing this code, the grid was draw with icon in the specific row of column, but all grid not draw, and dont show any data. inserted: 2016-12-09 16:14:58 Reply... From: nosctradamus Could you show me an example of how to insert an image into a cell in a column. (use ImageList or Image) I can not do this at all. I use lazarus and default DBgrid works with my code, but with KDBGrid not inserted: 2016-12-10 00:48:15 Reply... From: tk I never used TImageList but for TImage I normally use this: var FImage: TImage; ... procedure TForm1.KGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; R: TRect; State: TKGridDrawState); begin if ACol = MyColumn then begin KGrid1.CellPainter.Graphic := FImage.Picture.Graphic; ... end else begin ... end; KGrid1.CellPainter.DefaultDraw; end; In TKDBGrid you should first call cell's ApplyDrawProperties as shown in the KDBGrid demo. You must always call CellPainter's DefaultDraw (or its other drawing methods if DefaultDraw does not suit your needs) otherwise any assignments to CellPainter properties won't have any effect. inserted: 2016-12-10 14:37:18 Reply... From: nosctradamus Thanks tk. It worked as I expected, cells were rendered correctly. Congratulations on working with KComponentes, it's fabulous. inserted: 2016-12-01 10:47:50 Reply... From: СМ630 There is a bug in the hyperlink handling: when the mouse is over a hyperlink and Ctrl+LeftMouseButton is pressed the mouse icon is NOT changed to a hand. When still holding Ctrl+LeftMouseButton and moving the mouse a little the mouse icon is changed to hand, as expected. inserted: 2016-12-02 11:49:09 Reply... From: tk I am not able to reproduce this. inserted: 2016-12-05 10:04:59 Reply... From: СМ Today I retested it on the latest KControls version from Bitbucket, the bug is still always observable. The code is: procedure TForm1.Button1Click(Sender: TObject); var MyStream: tstream; begin MyStream := TStringStream.Create('{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'); KMemo1.Blocks.LoadFromRTFStream (MyStream); KMemo1.Blocks.AddParagraph; end; I did it on Lazarus 1.6 (32 bit on Win 7 64 bit). inserted: 2016-12-05 21:45:14 Reply... From: tk Maybe you don't have the memo focused (with caret blinking)? Without focus pressing Ctrl does nothing and it behaves as you said but this is not a bug. There is no way to detect Ctrl press when memo is not focused... inserted: 2016-12-05 21:52:39 Reply... From: tk Well, maybe when there is not input focus the caret should not change to hand at all. And the first mouse click should set focus and nothing more (??) inserted: 2016-12-07 09:32:48 Reply... From: СМ Hi, Yes it is just you proposed- this behaviour is observed when the memo is not focused. When the memo is focused, the hand gets shown as soon as CTRL is pressed. I tried how MS Word behaves: 1. When MS Word is not the active application, the cursor does not change to a hand. 2. When MS Word is the active application but another form or field in it (i.e. Search field of box) is focused the cursor changes to a hand (disregarding the fact that the editor field is not focused). So if we consider MS Word a standard, the cursor should change to a hand. But indeed, effort for fixing this might be too hude for such a minor issue. Behaviour in ReadOnlyMode seems just fine. inserted: 2016-12-08 18:46:26 Reply... From: admin Yes. KMemo is control, Word is application itself. This is different. So if your application would notify the memo with Ctrl key presses even when not focused (eg. through SendMessage?, dont know now exactly without trying) it would IMO work as well even when memo is not focused. But true: 1. Is minor issue 2. Should we really take MS Word as reference? We are cross platform so maybe LibreOffice would be better... inserted: 2016-12-09 09:56:17 Reply... From: СМ Going this way: 2. Should we really take MS Word as reference? We are cross platform so maybe LibreOffice would be better... Maybe WPS Office would be better, because: 1. It is multiplatform. 2. It can open DOC and DOCx files 99% properly, while Libre Office open not more than 60% properly. 3. It is much faster than Libre Office. 4. Yes, WPS Office is written in Delphi. ;) inserted: 2016-11-22 09:52:51 Reply... From: СМ Hi Tk, I have two other issues: 1. I am trying to add a multiline text in a table in TKMemo: TBL.Cells[clmInput,TSIndex*3+3].Blocks.AddTextBlock(MultilineText_Separated_With_CrLf); But the CrLf gets removed text is not printed on a new line. Should I use some other line separator? 2. I run the following code: for TSIndex :=0 to tbl.RowCount -1 do begin tbl.Rows[TSIndex].FixedHeight:=true; tbl.RowHeights[TSIndex]:=14; end; My idea is to have a minimum height of the (empty) rows. But after I run the code, the size of the rows is zero. Am I missing something? inserted: 2016-11-24 10:22:41 Reply... From: СМ Hi Tk, I could not find a way to find add formatted RTF text directly. I tried kmMain.Blocks.Text :=('{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'); and kmMain.Blocks.AddTextBlock ('{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'); but none of them was displayed as a hyperlink. inserted: 2016-11-24 12:16:50 Reply... From: СМ I have come across MyMemo.RTF. But: 1. KMemo1.RTF:='{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'; KMemo1.RTF:='{\field{\*\fldinst HYPERLINK "http://www.SITE1.com/"}{\fldrslt http://www.SITE1.com}}'; displays http://www.SITE1.comhttp://www.google.com 2. KMemo1.RTF:='{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'; KMemo1.Blocks.AddTextBlock('123'); KMemo1.RTF:='{\field{\*\fldinst HYPERLINK "http://www.SITE1.com/"}{\fldrslt http://www.SITE1.com}}'; displays http://www.SITE1.comhttp://www.google.com 123 (the 123 goes in the end, instean between the hyperlinks) inserted: 2016-11-25 00:36:36 Reply... From: tk Hmm, I could see now that things were broken in the trunk. Setting RTF property should clear previous content (just like LoadFromRTF) and it did not. Moreover, new RTF content was not added to the end with LoadFromRTFStream(Stream, -1) but to the beginning. I quickly fixed this but definitely we need some unit testing for KControls... inserted: 2016-11-25 00:02:13 Reply... From: tk Writing this from memory (have not tried): a. You should assign only complete RTF document to RTF property {\rtf1\ansi...}. b. Try to create a simple document with one hyperlink with KMemoEditor and save it. Then copy the content of the saved file to clipboard and paste it to your code. It should work. inserted: 2016-11-25 11:40:37 Reply... From: СМ Thanks for the info. The way I understand you: I cannot add multiple RTF blocks. It seems to make sense, sinces colour, styles, etc are coded in the head of the RTF. My idea was to convert HTML hyperlinks to RTF ones, which is much easier than parsing the HTML content and extracting them. I will think what to do form now on. inserted: 2016-11-25 13:32:07 Reply... From: tk You can add more RTF chunks. It is actually what Paste does. Only the property RTF should not. For adding this, use LoadFromRTFStream. Maybe AddRTF or similar could be added to simplify that. The RTF chunks you will add using LoadFromRTFStream should begin with '{rtf1...'. Current implementation might not require this but for future it is safer. If the new RTF chunks don't define new colors, fonts, lists etc. never mind, default values valid for the actual document will be taken. inserted: 2016-11-30 08:01:08 Reply... From: СМ Hi Tk, I just tried this: procedure TForm1.Button1Click(Sender: TObject); var MyStream: tstream; begin MyStream := TStringStream.Create('{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'); KMemo1.Blocks.LoadFromRTFStream (MyStream); KMemo1.Blocks.AddParagraph; MyStream := TStringStream.Create('{\field{\*\fldinst HYPERLINK "http://www.google1.com/"}{\fldrslt http://www.google1.com}}'); KMemo1.Blocks.LoadFromRTFStream (MyStream); KMemo1.Blocks.AddParagraph; end; When I execute it, I get „http://www.google1.comhttp://www.google.com‟ (the second last is displayed first and no new paragraph was added). I tried to use different values of AtIndex but result was always the same. inserted: 2016-11-30 11:34:02 Reply... From: tk Works for me fine with the latest commit. inserted: 2016-11-30 12:05:12 Reply... From: СМ Thanks, I tried it with the latest commit. It seems to work fine, except in caes when the table is newly created- there is a empty paragraph in the top of the table. For example: procedure TForm1.Button1Click(Sender: TObject); var MyStream: tstream; begin MyStream := TStringStream.Create('{\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}'); KMemo1.Blocks.LoadFromRTFStream (MyStream); end; leaves an empty line in the top of the KMEMO. On next executions no empty lines are added, as expected. inserted: 2016-11-30 15:32:06 Reply... From: tk LoadFromStream with default AtIndex parameter adds the stream content after all existing blocks. Blocks in empty memo (or memo container such as table cell) have (or should have) one paragraph inserted, for misc. reasons. So you must call x.Blocks.Clear before calling LoadFromStream. inserted: 2016-12-01 07:22:03 Reply... From: СМ Seems flawless now! I think there are some other cases, when I had trouble with the leading paragraph, I believe they will be solved now. inserted: 2016-11-23 09:08:40 Reply... From: tk Not tried but this should work: 1. Use Blocks.Text := YourContent; 2. Use tbl.Rows[RowIndex].RequiredHeight := YourHeight; inserted: 2016-11-23 11:22:25 Reply... From: СМ Thanks, actually Blocks.Text := YourContent; fixed both cases. inserted: 2016-11-22 02:59:05 Reply... From: PascalDude First off, thank you for these components. The cross-platform aspect is fantastic! As I begin to use them I have a few questions. This one regards the TKLinkLabel component. At design-time setting the Font|Color property always reverts to clBlue, and at run-time the color is Blue but when the mouse passes over it then it changes and remains at the Link Color value. How can this be fixed? inserted: 2016-11-23 09:12:52 Reply... From: tk There was bug, I fixed it in the trunk. It appears I've always used blue labels so far... inserted: 2016-11-21 11:53:41 Reply... From: СМ Hi Tk, I am running the following code: TBL:=KMemo1.Blocks.AddTable; TBL.CellStyle.BorderWidth := 1; TBL.ColCount := 6; TBL.RowCount :=150; // or 300 or 600 or 1200; TBL.ApplyDefaultCellStyle; It occurs that execution time is as follows: For TBL.RowCount :=150; = 1,5 s For TBL.RowCount :=300; = 5,5 s For TBL.RowCount :=600; = 27 s For TBL.RowCount :=1200; = 109 s I did some digging trought the code and I found out that Changed is executed in procedure TKRect.SetBottom(const Value: Integer); procedure TKRect.SetTop(const Value: Integer); procedure TKRect.SetLeft(const Value: Integer); procedure TKRect.SetRight(const Value: Integer); I commented all the occurences of Changed in the aforemenetioned procedures, leaving only one FixupBorders in the end of procedure TKMemoTable.ApplyDefaultCellStyle; This way execution time decreased from 109 000 ms to only 46 ms. Possibly you could introduce some changes in the code, in order not to execute Changed when ApplyDefaultCellStyle is performed? inserted: 2016-11-21 17:52:19 Reply... From: tk I see it now, is a bug, table updating should be locked inside of those methods. I added the missing locks. You could lock the table explicitly in your code and it was the same. Despite this locking reasonable amount is about 1000 rows with simple text. When more KMemo already begins to struggle when modifying, moving&resizing. inserted: 2016-11-21 17:01:07 Reply... From: tk Did you lock your table using LockUpdate/Unlockupdate? inserted: 2016-11-22 07:49:19 Reply... From: СМ Thanks, it works a way faster now! I have not locked the table, before trying the aforementioned case (because I had no idea that I should), but I tried to do it and it work much-much faster now. But is not the concept of LockUpdate to prevent changes from manual input from the user? If so, should not it be autoenabled, when the KMemo is ReadOnly? inserted: 2016-11-23 09:24:25 Reply... From: tk With KControls, LockUpdate/UnlockUpdate pairs should always inhibit control updating when more changes are made (more properties set at a time). For old controls like KHexEditor it might not be the case yet, because I introduced this later. With KMemo, I don't know what you exactly mean, ReadOnly should alone prevent changes from user. One of the todos with KMemo is to further optimize the MeasureExtent chain, to make it faster. Eg. there is no need to re-measure blocks/containers where nothing has changed. inserted: 2016-11-20 19:10:02 Reply... From: PascalDude Hi: How to Add/Delete a Page in the TKPageControl? Using Delphi2007 and not seeing a New Page/Delete Page when I right-click on the control. Thanks in advance. inserted: 2016-11-21 16:59:19 Reply... From: tk It has been added in the trunk, download from bitbucket. However, it does not work good in Lazarus yet. inserted: 2016-11-22 22:14:51 Reply... From: PascalDude Thank you. I shall download and use. inserted: 2016-11-21 14:45:42 Reply... From: СМ Hi, I found no way to add in the IDE, but you can add during runtime: KPageControl1.AddPage(self); KPageControl1.Pages[0].Caption:='Page 0'; KPageControl1.AddPage(self); KPageControl1.Pages[1].Caption:='Page 1'; inserted: 2016-11-22 02:56:16 Reply... From: PascalDude Thank you for the prompt reply. This means it is a run-time component then? And, a way to use this would be to create forms and set the respective Page as it's Parent? Correct? I also have another question on the TKlinkLabel. Shall submit as a separate post. inserted: 2016-11-15 14:37:27 Reply... From: СМ Hi Tk, I am beating my head how to set the background of a single cell. There is no example like this inthe manual. Whatever I try, it either does nothing or crashes the app. Could you help me with that? inserted: 2016-11-16 14:06:22 Reply... From: tk For example: Table.Rows[0].Cells[0].BlockStyle.Brush.Color := YourColor; Table is of type TKMemoTable, must be created and must have at least one row and one column. inserted: 2016-11-17 09:05:13 Reply... From: СМ Thanks, it works just fine! inserted: 2016-11-14 12:26:52 Reply... From: СМ Hi Tk, Thanks for the great component! Could you consider adding OnClick and OnMouseOver events for the Hyperlinks in the KMemo? This would increase the application of HyperLinks greatly. inserted: 2016-11-16 13:46:56 Reply... From: tk OnClick has been already added, download the trunk. OnMouseOver not yet but I'll add it. inserted: 2016-11-17 10:08:47 Reply... From: СМ Hi Tk, I am not sure that you undertsood me right. My idea was about event when a HYPERLINK is pointed or clicked. The wider idea is: When a hyperlink is Pointed, Clicked or Double Clicked to generate an event and to write the address (URL) in a variable of the TKMEMO itself. This way the developer will be able to choose what to do when a hiperlink is pointed or clicked (for example: open link in an external browser/ editor; open in internal browser; choose a key to be pressed together with the mouse button, open a popup menu, etc.). For example when the TMEMO is read-only it would make more sense to open links with a single click, than with click+key. I tried to implement this myself, but the event has to be owned by TKCustomMemo, and it has to be fired from within TKMemoHyperlink.WordMouseAction. I got some troubles accessing TKCustomMemo from within TKMemoHyperlink.WordMouseAction which I have not solved yet. inserted: 2016-11-18 00:40:59 Reply... From: tk Yes but that's what we use already about a half a year. But it is not implemented in the official 1.7 release but in the trunk on bitbucket. Just simply use: var HY: TKMemoHyperlink; begin HY := KMemo1.Blocks.AddHyperlink(HyperLinkCaption, ''); HY.OnClick := MyClickCommand; end; When read only, no Ctrl key needs to be held down to call OnClick. inserted: 2016-11-18 09:01:09 Reply... From: СМ Hi, Thanks for the example. The positive side of this approach is that a custom activity per every single hyperlink. But the negative side is that when a RTF is loaded from a file (or a simply when RTF formatted strings are added), such activities cannot be done. Also, would you mind if I copy kgrid_manual.rtf to http://wiki.freepascal.org/KControls? This way me and others wouyld be able to contribute to the knowledge base? inserted: 2016-11-18 13:58:33 Reply... From: tk I/we use the TKMemoHyperLink.Onclick only for a document built in code. Basically our case is a welcome screen for a program, with links to offline and online help, sample projects etc. But even in case you load the content from RTF you can loop over the blocks and look for hyperlinks. If found then assign OnClick for them. Here I perhaps understand you. Easier it would be to assign a global TKMemo.OnBlockClick, check for a hyperlink there and perform specific action. That way you could skip the block search. I'll see what I can do. Of course you can copy the manual(s) to lazarus wiki. inserted: 2016-11-18 15:21:52 Reply... From: СМ As you wrote: „...check for a hyperlink there...‟ I am not sure what you meant by „check for a hyperlink there‟ but I suppose the an easy to use solution would be to provide a property (for example) HyperlinkPointed: string... When the OnClick/MouseOver... etc. event occurs, it would contain the name of the pointed hyperlink. Otherwise it could be empty (thought it might better not be). inserted: 2016-11-19 12:46:13 Reply... From: tk I added global OnBlockClick and OnBlockDblClick events, pull the changes from trunk. To filter hyperlinks use 'if Block is TKMemoHyperlink' as I already said. To inhibit default behavior just set Result := True in the OnBlock(Dbl)Click handler. For hyperlink just set Result := True in OnBlockClick. This will inhibit opening assigned URL in the browser. inserted: 2016-11-18 17:01:46 Reply... From: tk You would get a Block parameter in the OnBlockClick which would be the sending block. Then you just test if Block is TKMemoHyperlink then //doyourstuff. inserted: 2016-11-25 14:33:05 Reply... From: СМ Thanks, I tried these and they work. What I still cannot do is to find out the text block under the mouse cursor (i.e. the focused block). Ther is ActiveBlock and Selected block, but none of them is the one under the mouse pointer. This would be useful for: 1. Handling OhMouseOver (MouseOverHyperlink) events. 2. Popup menus (displaying the links in them, copying Hyperlink address, etc.) Could you tell me if there is a ready solution for that? If I get it right function TKMemoBlocks.MouseAction... searches all the contents to find out which is the pointed block, but it does not return the resulting block. This way coders would have to rerun the same search, in order to find the pointed block. inserted: 2016-11-08 00:24:12 Reply... From: Froggy Hi tk, great tools but noticed a bug in kmemo maybe? when using SelStart property it seems only return valid position for first line, when other lines exist do we need to use SelStart with some other property? For example: This is a line 1 This is a line 2 This is a line 3 How to move caret (SelStart) to the word "is" on the second line? inserted: 2016-11-08 21:14:46 Reply... From: tk Caret is always placed at TKMemo.SelEnd (visible when TKMemo.SelLength = 0). To move caret use TKMemo.Select. In this case easiest will be to count the characters(here it should be 22) and move the caret: KMemo1.Select(22, 0); Note: The indexes are relative to TKMemo.ActiveBlocks. Thus, if you have a container (embedded text box) in your document and it is active then these indexes are relative to its contents. inserted: 2016-11-08 12:51:44 Reply... From: Homer This cannot be bug, Kmemo returns the caret position using SelStart the same way TMemo does, it counts all previous characters from previous lines to return character index. maybe what you want is to return selstart starting from 0 for each line? maybe there built in function for that. inserted: 2016-11-08 10:20:54 Reply... From: Homer Not tried but Maybe RealSelStart can help you? inserted: 2016-11-05 23:37:12 Reply... From: Homer in kMemo how can you change the text style of words without manually selecting text but by defining a range? eg in lazarus, 3rd party control RichMemo you can use RichMemo1.SetRangeParams(), how to do similar in Kmemo? Thanks inserted: 2016-11-07 19:59:08 Reply... From: tk KMemo has/must have very different approach than Delphi/Lazarus Richedit/Richmemo since it also supports complex things like tables, embedded containers, is ready to support controls in the future etc. There is no RichEdit/RichMemo compatibility layer. Also please note KMemo is still beta - not finished. Contributions are welcome! 1. SetRangeParams (or similar) not supported now - only way now is to select text, call SelectionTextStyle property and deselect text, see TKMemoFrame.TextStyleChanged. 2. Searching for text/highlighting - this is rather special thing, not easily doable in Kmemo now, no text search implemented yet etc. 3. Blocks are not confusing. It is IMO the only viable approach for a complex rich edit document, as said above. But I admit, some text oriented helper methods are still missing. 4. Current line can be easily obtained through IndexToLine, eg.: LineIndex := KMemo1.Blocks.IndexToLine(KMemo1.SelEnd); inserted: 2016-11-07 21:10:22 Reply... From: Homer Forgot to mention i think richmemo setrangeparam internally begins line update , selects text and change format style and then ends the line updates. Similar procedure should not be so difficult to impelement in Kmemo. inserted: 2016-11-07 23:12:52 Reply... From: tk Actually it should be easy to adapt. Just call the code of SelectionTextStyle with custom SelStart and SelEnd arguments... Will try tomorrow. inserted: 2016-11-07 23:28:42 Reply... From: Homer Ok but this matter is not of great urgency. In mean time i will try to use and understand control more better as the syntax is much different to usual controls. inserted: 2016-11-18 01:09:18 Reply... From: tk Made SetRangeParaStyle and SetRangeTextStyle. Tested in KMemoFrame, worked fine for me. inserted: 2016-11-07 21:02:44 Reply... From: Homer Ok thanks for help, controls provided are wonderful addition and can become great but also confusing for first time user, difficult when always using lines and strings, blocks sound really powerful but confusing, text helpers are greatly needed because it should not be so tricky finding things like the caret.x and caret.y, current line and things etc. How to get current line text though? Form4.Caption := KMemo1.Blocks[KMemo1.Blocks.IndexToLine(KMemo1.SelEnd)].Text; inserted: 2016-11-07 21:51:47 Reply... From: Homer Never mind found KMemo1.Blocks.LineText[Line] :) inserted: 2016-11-07 23:31:17 Reply... From: tk You see I forgot this property. Don't know what exactly you want to do with this but you have to ensure there is only text (and not images etc.) on the line where you want to find some text occurences eg. with Pos function. Otherwise the indexes returned by Pos won't match the actual letter indexes in the document! That's why a more sophisticated (generous) way of finding text occurences in the document (or part of it) is necessary. Because text blocks can contain whole sentences as well as only a single letter (if it has different text style) and these blocks can even be nested, it is not trivial task to implement this. inserted: 2016-11-06 20:28:08 Reply... From: Homer var CurLine: Integer; begin CurLine := KMemo1.ActiveBlocks.LineInfo[KMemo1.CaretPos].StartIndex; ?? inserted: 2016-11-06 17:41:42 Reply... From: Homer How do you even get all the text on the current line, how to even know the current line? RichEdit1.Lines[RichEdit1.CaretPos.Y] but nothing simlar on kmemo? blocks, activeblocks its all confusing! inserted: 2016-11-06 14:05:43 Reply... From: Homer How do you even get current line index, blocks are confusing? Need to get all text typed on current line and highlight words ("user") in different style but kmemo is confusing control to use and no real documentation? Please help thanks. inserted: 2016-10-03 23:24:28 Reply... From: anor thanks you very much for the hexeditor, i need it for a some fast tool, thanks! inserted: 2016-10-03 19:30:37 Reply... From: leospb KControls_1.7 Cannot compile: [dcc32 Error] kedits.pas(708): E2010 Incompatibie types: 'SmallInt' and 'Integer' RAD St. XE4 Can you help, please? inserted: 2016-10-08 19:24:13 Reply... From: tk Go to function TKNumberEdit.UpDownChangingEx and modify its header from {$IFDEF COMPILER17_UP} to {\$IFDEF COMPILER18_UP}. Because I did not use XE4 I just guessed in which Delphi version the change was made. I'll fix this in the repo as well (in the repo somebody renumbered the COMPILERxx_UP conditionals, I don't recall anymore why).
From: krzynio
Lazarus 1.7 (svn 52880M) GTK2 FPC3.0.0
From: tk
Ok, you can use my today's commit, it should compile fine with your 1.7. I've replaced the obsolete UTF8 functions from LCLProc with equivalents from LazUTF8. The UTF8 functions were not removed from LCLProc yet, but apparently will be in the future. See http://forum.lazarus.freepascal.org/index.php?topic=28997.0.
From: tk
I don't have this version (been using the official 1.6) but someone probably removed the function from LCLProc.pas. It was marked as deprecated. Changes in KControls will be made first when it does not compile with the official stable release.

Solutions for now:
1) Either use a Lazarus version which has the function.
2) Or take the missing functions from previous versions of LCLProc.pas.
3) Or file a bug report and demand the obsolete functions to be returned to LCLProc.pas.
From: inform
Hello,
we just start to use KGrid and it works good for us. We use it as a replacement for TDrawGrid.

During the replacement process we found some points to enhance the compatibility with VCL and we have an suggestion about an enhancement (including source).

Is there any way to contact you directly by E-Mail?
From: tk
Did you send the email? I am asking because I experienced some problems with this email account few days ago. Now it seems to work fine.
From: tk
Yes use the email you see in the source headers.
From: HexUser

I see that there are exactly the first 25 MB loaded.
It happens both with x86 and x86_64 compiler in Lazarus 1.6.0
From: tk
With my new commit even files > 4GB should open fine (when compiled with 64-bit compiler). Tried with 64-bit Lazarus. However, the editor has no paging mechanism. Loading & saving is very slow and working with the file is not very fast either.
From: tk
KHexEditor is not ready to open big files. Although I am able to open files as large as you mention (when compiled with 64-bit compiler) there is unpredictable behavior due to miscellaneous arithmetic overflows. The reason for these are the Integer/Cardinal types used everywhere in the control, which are always 32 bit wide.

The control would need some work to handle big files correctly.
From: HexUser
I have a Problem, when I load large Files in the KHexEditor.

The example-file with 4.02 GB normaly ends at
0x101993FF9, but in the Hex View only a first part until

Is this a known Issue? Is there a fix or workaround?
From: RobV
Hi Tk,

How I get the exact position or rect of an container (table) ?

when I evaluate two tables the second seems to display corresponding to the correct position:

for I := 0 to LineCount - 1 do
begin
J := FLines[I].StartBlock;
Item := Items[J];
if item is TKMemoContainer then begin
x:=TKMemoContainer(item).BoundsRect.Bottom ;

end;

end;

thanks
From: RobV
sorry .. the observation that wanted to do is

...the position of a second table on the same page appears not correspond to its correct position.
From: tk
Well I don't understand this either, has it sth. to do with the print&preview issues which we've discussed below? If yes you might try the current repo download. For tables, I made page breaks to ensure table rows will be shown on next page if they don't fit to current page.
From: RobV

hi tk,

I found that this latest version you fixed the texts that were not being displayed correctly when the page change.

But in the example file http://www.sispaic.com.br/PFNSis/teste.rtf
the text after the second table is not displayed neither the first nor the second page. For you to evaluate this inconsistency this file must be loaded in the example of the program KMemoEditorLaz.

thanks
From: tk
Hmm, you're right! Still bugs there in TKMemoBlocks.GetPageCount and GetPageData. I'll fix them tomorrow.
From: RobV

see: http://www.sispaic.com.br/PFNSis/KMemo-x.pdf

From: tk
Btw. the font in the document seems to be invalid. Lazarus LCL clearly understands the font name 'default' but Delphi VCL does not. And Word does not either. How did you get this font there?
From: RobV
the texts off the table were produced by typing in your sample program "KMemoEditorLaz" (propertie font=Tahoma DEFAULT_CHARSET size 8)
compiled in lazarus 1.6 windows 10 pro version 64bits. The two tables have been copied with clipboard from example 13 "KMemoDemo.exe"
From: RobV
the file "teste.rtf" was saved using kMemoEditorLaz.
From: RobV
the problem of supply becomes evident when you begin to suspect the copy to kmemo clipboard which is another problem or bug even be repaired.
The reported issue is about texts or tables that should go out on the next page and are not displayed because of the two routines that you have mentioned.
the problem remains in other examples see

http://www.sispaic.com.br/PFNSis/teste2.rtf
http://www.sispaic.com.br/PFNSis/teste3.rtf
From: RobV
with commit e44a8bcdfc4a this works fine.

Thanks.
From: Whisper
I select a grid: N-col and M-row. How I can mark all grids of the same row? I've tried differents methods without any success. Any help code?

From: tk
Don't understand, please specify exactly what you want to do.
From: Whisper
Hi tk!
FIRST:
For example. I have this kgrid (picture 1)
The position of cursor/mouse is inside of the grid with "light grey" color (picture 1 and 2). I would like that all grids, in the same row, where the mouse is, are in the same "light grey" color (picture 3).

SECOND:
I check the first checkbox (picture 4), and then, it should be mark the rest of checkboxes of first col.

picture 1-> http://s2.subirimagenes.com/otros/9604666sin-ttulo1.jpg
2-> http://s2.subirimagenes.com/otros/9604667sin-ttulo2.jpg
3-> http://s32.postimg.org/u4cu0z32t/Sin_t_tulo3.png
4-> http://s31.postimg.org/4s4kmooez/Sin_t_tulo4.jpg

From: tk
To select entire line use goRowSelect, like in normal Tstringgrid.
To show all checkboxes checked or unchecked according to some condition you need some custom code in OnDrawCell. Here to draw the checkboxes in checked/unchecked state according to the first checkbox state. Use property TKGridCellPainter.CheckboxChecked for this. Then, you would need to call TKGrid.InvalidateCol when the first checkbox state is clicked and this will redraw entire column.
From: Whisper
Thanks for your tips. I've fixed the ISSUES!!