Lazarus

Programming => Packages and Libraries => RichMemo => Topic started by: Spoonhorse on September 18, 2021, 07:55:34 pm

Title: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 18, 2021, 07:55:34 pm
So looking through previous discussions it seems that in order to insert a picture into a RichMemo I need to pass InDelInline a TRichMemoInlinePicture. I can't find where this is defined (You'd have thought along with RichMemo but no) but I did find some suggested code for it. I stuck it in a unit (code below) but when I told the unit to compile it complained that it couldn't open a resource file rminlinepicture.lfm. This hasn't happened to me before and I don't understand it.

What's the latest advice on getting pictures to work in a RichMemo?

Thanks.

Code: Pascal  [Select][+][-]
  1. unit RMInlinePicture;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, RichMemo, Graphics, Types;
  9.  
  10. type
  11.  
  12.   { TRichMemoInlinePicture }
  13.  
  14.   TRichMemoInlinePicture = class(TRichMemoInline)
  15.     pic: TPicture;
  16.     constructor Create(Apicture: TPicture);
  17.     procedure Draw(Canvas: TCanvas; const ASize: TSize); override;
  18.   end;
  19.  
  20. implementation
  21.  
  22. {$R *.lfm}
  23.  
  24. { TRichMemoInlinePicture }
  25.  
  26.   constructor TRichMemoInlinePicture.Create(Apicture: TPicture);
  27.   begin
  28.     inherited Create;
  29.     pic:=APicture;
  30.   end;
  31.  
  32.   procedure TRichMemoInlinePicture.Draw(Canvas: TCanvas; const ASize: TSize);
  33.   begin
  34.     inherited Draw(Canvas, ASize);
  35.     Canvas.Draw(0,0, pic.Graphic);
  36.   end;
  37.  
  38. end.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 19, 2021, 03:59:15 pm
Well the unit was behaving like that because of the {$R *.lfm} thing that got in there somehow. I shouldn't try to debug when tired. I have some very nearly working code, will report back soon.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 19, 2021, 05:02:45 pm
Well, I still have nearly-working code. It will insert pictures into the text without complaint, but when it comes to *display* the memo it crashes with a SIGSEGV complaint. It does this even if I comment out the contents of the draw method so it doesn't do anything.

At this point I'm at a loss, does anyone know the authors? Or anyone who's successfully managed to make it work?

Since I know I can paste pictures into the text from the clipboard, there might be a way around it by essentially getting my app to do that. But it's terrible clumsy.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 06:29:13 pm
Hey SpoonHorse,

This is just  suggestion from a person that has not had a look at any code from either TRichMemo or anything related, but if the component is able to do it on the paste event, I would have a look at that particular region of the code and see how it does it.

I'm sorry I can't pitch in with something more substantial, but that's how I'd go about solving this problem.

Hope this can give you another avenue of enlightenment :)

Cheers,
Gus
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 19, 2021, 10:03:38 pm
Well I would but I can't figure out how. If I open up RichMemo I can find where it says procedure PasteFromClipboard; override; but there's no clue as to where the implementation is. So as far as I know it's done by magic. How does that even work?
Title: Re: Where is TRichMemoInlinePicture?
Post by: Gustavo 'Gus' Carreno on September 19, 2021, 10:43:53 pm
Hey SpoonHorse,

Well I would but I can't figure out how. If I open up RichMemo I can find where it says procedure PasteFromClipboard; override; but there's no clue as to where the implementation is. So as far as I know it's done by magic. How does that even work?

Let me introduce you to one very nifty keyboard shortcut: Ctrl+Shift+Up.

If you place the cursor on the Interface declaration of the class procedure and press that shortcut, the IDE will send you to the Implementation of said procedure, if and only if it can locate the file where it is.

Hope that helps!!

Cheers,
Gus
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 20, 2021, 08:57:01 am
Thanks. Well, I thought that knowledge would open up all sorts of things to me but no.

I tried that, I got this.

Code: Pascal  [Select][+][-]
  1. procedure TCustomRichMemo.PasteFromClipboard;  
  2. begin
  3.   if HandleAllocated then  
  4.     TWSCustomRichMemoClass(WidgetSetClass).PasteFromClipboard(Self);
  5. end;

OK, let's find where *that* PasteFromClipboard is defined:

Code: Pascal  [Select][+][-]
  1. class procedure PasteFromClipboard(const AWinControl: TWinControl); virtual;

It's another interface. Fair enough. Let's follow that method up with Ctrl + Shift + Up.

Code: Pascal  [Select][+][-]
  1. class procedure TWSCustomRichMemo.PasteFromClipboard(const AWinControl: TWinControl);
  2. begin
  3.  
  4. end;

Oh look, it's completely empty.

At this point I look up the word "virtual".

"A virtual method is a type of method where the actual method calls depends on the runtime type of the underlying object."

But ... where is the code? I am only a simple code monkey but when I write code it does something. This is just a maze. Where is the thing that does the thing?
Title: Re: Where is TRichMemoInlinePicture?
Post by: dsiders on September 20, 2021, 03:33:11 pm
"A virtual method is a type of method where the actual method calls depends on the runtime type of the underlying object."

But ... where is the code? I am only a simple code monkey but when I write code it does something. This is just a maze. Where is the thing that does the thing?

Use the file search utilities for your OS. Find or FindStr on Windows. grep on linux. I have a copy of CygWin on my windows machine just for the utilities.

Code: Bash  [Select][+][-]
  1. grep -i --include=*.{pas,pp,inc} --recursive .
  2. lcl/grids.pas:procedure TCustomGrid.DoPasteFromClipboard;
  3. lcl/grids.pas:procedure TCustomStringGrid.DoPasteFromClipboard;
  4. lcl/groupededit.pp:procedure TCustomAbstractGroupedEdit.PasteFromClipboard;
  5. lcl/include/customedit.inc:procedure TCustomEdit.PasteFromClipboard;
  6. lcl/include/dbimage.inc:procedure TDBImage.PasteFromClipboard;
  7. lcl/lclmessageglue.pas:function LCLSendPasteFromClipboardMsg(const Target: TControl): PtrInt;
  8. lcl/maskedit.pp:procedure TCustomMaskEdit.PasteFromClipBoard;
  9. lcl/stdctrls.pp:    procedure PasteFromClipboard; virtual;
  10.  
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 20, 2021, 04:46:54 pm
OK, but ... is that really the only way in? Search for mentions of it, pick out the right one by hand? How does the compiler know how to find the implementation of a method declared like that? Why can't I find it like the compiler does?
Title: Re: Where is TRichMemoInlinePicture?
Post by: zoltanleo on September 20, 2021, 10:58:46 pm
At this point I'm at a loss, does anyone know the authors?
Hi Spoonhorse.

Try to write to the author of this component
https://forum.lazarus.freepascal.org/index.php?action=profile;u=13884
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 21, 2021, 02:18:00 am
But ... where is the code? I am only a simple code monkey but when I write code it does something. This is just a maze. Where is the thing that does the thing?
...
Why can't I find it like the compiler does?
it's not a maze, but an amazing back bone of LCL, known as VMT-hack. It's a very old solution (back from the days when FPC didn't support interfaces), that still works.
And in fact, the compiler doesn't find the proper implementation as well.

What's happening is a run-time construction of an additional virtual class, with a mix of methods from different classes. The mix is driven by the hierarchy you're trying to search through (TWSCustomRichMemoClass -> TWSCustomMemo -> TWSCustomEdit)
However, the actual implementation is being copied over from a selected widgetset.
For Win32, you might want to search TWin32WSCustomRichMemoClass (from richmemo package), TWin32WSCustomMemo (from LCL), TWin32CustomEdit (from LCL).
(one of those should have PasteFromClipboard method)

The VMT for the virtual classes is reconstructed based on the inheritance of TWin32WSxxx classes. (the same thing is explained here (https://github.com/skalogryz/Lazarus/wiki/ws_to_intf#Current_Implementation))

However, once you find Win32 PasteFromClipboard you might find it pretty boring and uninteresting:
Code: Pascal  [Select][+][-]
  1. imptype procedure TWin32WSCustomEdit.Paste(const ACustomEdit: TCustomEdit);
  2. begin
  3.   SendMessage(ACustomEdit.Handle, WM_PASTE, 0, 0)
  4. end;
  5.  

In other words, all the "fun part" of actually pasting an image into a rich edit is implemented within the system code, and is not available for the review.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 21, 2021, 05:35:42 am
skalogryz, oh darn. Well at the very worst I could hijack the paste method, I could put whatever I want to insert on the clipboard and then send a message like that to paste it in. If I first store whatever's on the clipboard somewhere and then restore it. It's crude, but it should work.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 21, 2021, 05:36:54 am
zoltanleo, thanks, I may have to.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 21, 2021, 09:39:32 am
... wait, skalogryz is the author?

OK. In that case, skalogryz, instead of telling me how to peek into the class, can you just tell me how to get the InDelInline method to work so that I can delight my users? Thanks.
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 21, 2021, 03:45:52 pm
instead of telling me how to peek into the class, can you just tell me how to get the InDelInline method to work so that I can delight my users
are you users limited to Windows? Otherwise it won't work.

but when I told the unit to compile it complained that it couldn't open a resource file rminlinepicture.lfm
just get rid of {$R *.lfm} in rmInlinePicture.pas unit.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 21, 2021, 08:39:27 pm
Quote
just get rid of {$R *.lfm} in rmInlinePicture.pas unit.

Yes, I found that bit, but see my subsequent posts.

Quote
are you users limited to Windows? Otherwise it won't work.

For now it's Windows-only, there are a few things that Windows seems to do better than anything else and I'm leaning heavily on one of them, I don't see an easy way to replace it.

Pictures would be dispensable but my project is visually boring and it's reaching the finishing-touches stage where I care about that.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 21, 2021, 08:42:51 pm
P.S. skalogryz, there is just one other thing I've been having difficulties with. It seems like if I change the text itself (not the rich formatting, but the actual words) programmatically, rather than the user doing it by typing, then Undo can't go back beyond that point. Is there anything I can do about this? Thanks.
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 21, 2021, 09:48:14 pm
Is there anything I can do about this?
do you need to be able to undo programmatic changes?

Well, I still have nearly-working code. It will insert pictures into the text without complaint, but when it comes to *display* the memo it crashes with a SIGSEGV complaint. It does this even if I comment out the contents of the draw method so it doesn't do anything.
I did try your example and it works for me.
Code: Pascal  [Select][+][-]
  1. var
  2.   rm :  TRichMemoInlinePicture;
  3.   sz : TSize;
  4. begin
  5.   rm:=TRichMemoInlinePicture.Create(Image1.Picture);
  6.   sz.cx:=64; sz.cy:=64;
  7.   RichMemo1.InDelInline(rm, 0,0, sz);
  8.  
Title: Re: Where is TRichMemoInlinePicture?
Post by: Gustavo 'Gus' Carreno on September 21, 2021, 11:35:48 pm
Hey Skalogryz,

I did try your example and it works for me.
Code: Pascal  [Select][+][-]
  1. var
  2.   rm :  TRichMemoInlinePicture;
  3.   sz : TSize;
  4. begin
  5.   rm:=TRichMemoInlinePicture.Create(Image1.Picture);
  6.   sz.cx:=64; sz.cy:=64;
  7.   RichMemo1.InDelInline(rm, 0,0, sz);
  8.  

Is TRichMemoInlinePicture present in the version that OPM lists, or is it only present in your GitHub(Is it on GH or somewhere else, my memory fails me ATM) version of the TRichMemo?

Cuz I've done a grep -i --include=*.{pas,pp,inc} --recursive TRichMemoInlinePicture . on the folder that OPM downloads and I found nothing.

Sorry to insist on this subject.

Cheers,
Gus
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 22, 2021, 02:01:05 am
Cuz I've done a grep -i --include=*.{pas,pp,inc} --recursive TRichMemoInlinePicture . on the folder that OPM downloads and I found nothing.
TRichMemoInlinePicture is not a part of richmemo package. This is a class created by Spoonhorse, inheriting from TRichMemoInline.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Gustavo 'Gus' Carreno on September 22, 2021, 02:11:11 am
Hey Skalogryz,

TRichMemoInlinePicture is not a part of richmemo package. This is a class created by Spoonhorse, inheriting from TRichMemoInline.

OOOOPPPPSSS !!!!  :-[

I just now had a look at the first post and he lists the code for it LOL!!!!!

Ok, now I'm baffled at the subject of this thread!!
Why name it Where is TRichMemoInlinePicture? when you then post the code on the message?

Me dumb-dumb !!

Cheers,
Gus
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 05:15:47 am
I named it that because it expects such a thing to exist but I had to roll my own.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 05:21:18 am
skalogryz, I do rather need to undo programmatic changes, yes. Otherwise anything like autocorrect or autocomplete or whatever will mess things up, the user won't be able to delete past those. It would be silly for me to have to write another Undo routine on top of your code when there's already one in there.

Maybe there's something wrong with how I'm using the image insertion code, I'll try it again in a simpler environment, and with different images, etc, see if I can find where I'm going wrong. Thanks.
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 22, 2021, 07:34:24 am
It seems like if I change the text itself (not the rich formatting, but the actual words) programmatically, rather than the user doing it by typing, then Undo can't go back beyond that point. Is there anything I can do about this?
How are you changing the text?  (RichMemo1.Text := NewVersionOfText;?)
Try to use InDelText method, see if it makes any difference on the Undo behavior.
...
and you need to use the latest version for github.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 08:26:37 am
skalogryz, thanks, I'll try that, I didn't know about it. Up until now I've been changing SelStart and SelLength and then setting SelText, because doing it that way doesn't mess up the justification, I thought that that was the True Way.

I have got the pictures to work. You'll laugh at me, but I guess I was taking the notion of inserting the picture in the memo too literally, I thought once I'd done the insertion I should free up the TPicture and the TRichMemoInlinePicture like a tidy coder. It looks like I have to keep lists of them, one for each picture, instead.

Couple of questions. Is there any way to center the pictures? And is there any easy way to resize them once they've been inserted? (I can always just redo the memo, by "easy way" I mean not that.)
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 22, 2021, 08:47:01 am
Is there any way to center the pictures?
if a picture sits on its own paragraph you should be able to change the paragraph alignment to center.
There's no option for the text overflow the picture. (the just like you can see in MSWord)

And is there any easy way to resize them once they've been inserted? (I can always just redo the memo, by "easy way" I mean not that.)
no, there's no way to do that.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 08:52:43 am
Is this the right version? https://github.com/cutec-chris/richmemo

If so, I may have the wrong one, the thing I installed had a readme file but not a gitignore and this is the other way round.

Thanks.

P.S: Using the InDelText method didn't fix the Undo thing on the version I have.
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 22, 2021, 09:01:10 am
This is the one:
https://github.com/skalogryz/richmemo
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 01:21:10 pm
Thank you!

I've got the pictures working fine, but I'm concerned about memory leakage, because it doesn't like me freeing up the TPictures and TRichMemoInlinePictures even after I've cleared the TRichMemo. Can you tell me what's going on?

Thank you for all your help. It's a magnificent app now and it owes all its good looks to TRichMemo.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 22, 2021, 02:54:53 pm
skalogryz, you made that change 'cos I needed it?!?  :o First, I am very very grateful, and second it doesn't seem to work, I still can't undo past an InDelText, and also now when I press Ctrl + Z it undoes absolutely everything until it hits that wall, instead of Undo-ing things a bit at a time.
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 22, 2021, 09:00:45 pm
I still can't undo past an InDelText, and also now when I press Ctrl + Z it undoes absolutely everything until it hits that wall, instead of Undo-ing things a bit at a time.
I'm pretty sure it works.
please make sure you're compiling using the proper richmemo version

I've got the pictures working fine, but I'm concerned about memory leakage, because it doesn't like me freeing up the TPictures and TRichMemoInlinePictures even after I've cleared the TRichMemo. Can you tell me what's going on?
when you pass the Inline object to RichMemo, it passes the object on into the widgetset.
If the widgetset accepts the object, it now has the full ownership of it. It will free the object whenever it wants to free it.

Since you've said it's not freeing the object even after RichMemo has been destroy then it sounds like a bug in Windows RichMemo implementation.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 23, 2021, 03:49:32 pm
I'll try it again. I did uninstall and reinstall the thing and I *thought* I got the right version but I may have goofed.

No, I didn't say that I couldn't free the objects after destroying the RichMemo (I haven't tried), but after using the Clear method. It seemed to me that when the pictures weren't there any more I could delete them, but it gave me a runtime error. I'll see if I can pin the problem down a bit better and get back to you.
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 23, 2021, 09:55:08 pm
skalogryz, update, I uninstalled and reinstalled Lazarus completely and it worked. Thank you so much!
Title: Re: Where is TRichMemoInlinePicture?
Post by: skalogryz on September 23, 2021, 10:15:10 pm
i am happy to hear that, but reinstalling Lazarus sounds like a too big of a thing to fix the issue
Title: Re: Where is TRichMemoInlinePicture?
Post by: Spoonhorse on September 25, 2021, 04:29:21 pm
Oh I ran into all sorts of problems, I don't know why. I'm not using RichMemo directly, I subclass it a couple of ways, and perhaps that's the reason ... anyway, I ended up with Lazarus kinda borked. But a reinstall later and everything went smoothly.

I will get back to you about the pictures and memory usage but I have suuuuch a lot to do rn. But the undo stuff is working great, thanks!
TinyPortal © 2005-2018