Page 1 of 1

RVFontComboBox and RVFontSizeComboBox association not workin

Posted: Wed Aug 07, 2013 8:09 am
by PioPio
Hello,

I am developing a component acting as a frame and containing several functions buttons bold, italic, foreground colour, Font selection and relevant size etc.
The idea is to drop this component in a form and then drop one of the TCustomRichView descendents. This way you can pilot all TCustomRichView descendants by one component.

My component is a TFrame descendant and the following is the object declaration:
type
TRVEditFrame = class(TFrame)
.....
private
{ Private declarations }
FRVEditor:TCustomRichView;
public
{ Public declarations }
FButtonSaveClick:TNotifyEvent;
protected
procedure notification(
acomponent:TComponent;aoperation:TOperation);override;
published
end;


I started developing the component and when it comes to associate RVFontComboBox1.Editor and RVFontSizeComboBox1.Editor to the TCustomRichView dropped the component crashes.

Below you will see the code. If I comment the two lines, as below, the component works fine but I don't have RVFontComboBox1.Editor and RVFontSizeComboBox1.Editor associated to TCustomRichView. That means you cannot see the list of the fonts and size as soon as the component is shown.

Code: Select all

procedure TRVEditFrame.notification(acomponent: TComponent;
  aoperation: TOperation);
begin
	inherited;
	if acomponent is TCustomRichView then
		if aoperation=opRemove then begin
			if acomponent=FRVEditor then
				FRVEditor:=nil;
		end
		else begin
  			FRVEditor:=TCustomRichView(acomponent);
//			RVFontComboBox1.Editor:=FRVEditor;
	//		RVFontSizeComboBox1.Editor:=FRVEditor;
		end;

How can I solve this ?

Many thanks
Pio Pio

Posted: Wed Aug 07, 2013 10:59 am
by Sergey Tkachenko
Are you sure, that at this line

Code: Select all

 FRVEditor:=TCustomRichView(acomponent); 
acomponent is always TCustomRichView? This code is called for all components inserted at the frame.

Posted: Wed Aug 07, 2013 7:38 pm
by PioPio
Sergey Tkachenko wrote:Are you sure, that at this line

Code: Select all

 FRVEditor:=TCustomRichView(acomponent); 
acomponent is always TCustomRichView? This code is called for all components inserted at the frame.
Hi Sergey,

Just to make sure, I have amended the procedure this way:

Code: Select all

procedure TRVEditFrame.Notification(acomponent: TComponent;
  aoperation: TOperation);
begin
   inherited;
   if acomponent is TCustomRichView then begin
      if aoperation=opRemove then begin
         if acomponent=FRVEditor then
            FRVEditor:=nil;
      end
      else begin
         FRVEditor:=TCustomRichView(acomponent);
         RVFontComboBox1.Editor:=FRVEditor;
         RVFontSizeComboBox1.Editor:=FRVEditor;
      end;
  end
end;
Now I am 100% sure the part you point out is executed if acomponent is TCustomRichView or any descendant only.

I compiled the new version and made a test. The result is the same error First chance exception at $00405460. Exception class $C0000005 with message 'access violation at 0x00405460: read of address 0x00000000'. Process Project2.exe (5812)

Posted: Thu Aug 08, 2013 7:15 am
by Sergey Tkachenko
Yes, now this line is called when FRVEditor is created.
But it may be created before RVFontComboBox1 and/or RVFontSizeComboBox1, so they may be nil at this point.

Posted: Thu Aug 08, 2013 7:56 am
by PioPio
Sergey Tkachenko wrote:Yes, now this line is called when FRVEditor is created.
But it may be created before RVFontComboBox1 and/or RVFontSizeComboBox1, so they may be nil at this point.
So I should move the RVFontComboBox1 and/or RVFontSizeComboBox1 assignments where they are not nil. Problem is I don't know where as the container is a TFrame and there is no onshow method in TFrames.

What do you suggest ?

Pio Pio

Posted: Thu Aug 08, 2013 7:57 am
by Sergey Tkachenko
Where are these compobox placed? Are they on the same frame?

Posted: Thu Aug 08, 2013 8:13 am
by PioPio
Sergey Tkachenko wrote:Where are these compobox placed? Are they on the same frame?
yes they are. Here below an excerpt of the code

Code: Select all

	TRVEditFrame = class(TFrame)
		ImageList: TImageList;
		Toolbar1: TToolBar;
		tbSave: TToolButton;
		....
		RVFontSizeComboBox1: TRVFontSizeComboBox;
		RVFontComboBox1: TRVFontComboBox;
	end;

Posted: Thu Aug 08, 2013 8:25 am
by Sergey Tkachenko
Override Loaded method of your frame:

Code: Select all

procedure Loaded; override;

Code: Select all

procedure TRVEditFrame.Loaded; override;
begin
  inherited;
  RVFontComboBox1.Editor:=FRVEditor; 
  RVFontSizeComboBox1.Editor:=FRVEditor; 
end;
If you place this frame on a form at designtime, this method will be called automatically, when this frame is created and all its subcomponents and properties are loaded.
If you create this frame in code at runtime, call this method manually after creation.

Posted: Thu Aug 08, 2013 8:26 am
by Sergey Tkachenko
Hmm... If all the components on the same frame, why cannot you simply assign this property in the Object Inspector?

Posted: Thu Aug 08, 2013 10:28 pm
by PioPio
Sergey Tkachenko wrote:Hmm... If all the components on the same frame, why cannot you simply assign this property in the Object Inspector?
I didn't think to the Loaded method. This did the trick :-)

Referring to the question above. I could designate the property via Object Inspector but I was looking for something easy to use. Just drop the component and it works out of the box.

Many thanks
Pio Pio

Posted: Fri Aug 09, 2013 7:40 am
by Sergey Tkachenko
But if all the components are in the same frame, you can assign links between them when designing the frame, and they will be retained when you use this frame, am I right?

Posted: Fri Aug 09, 2013 8:35 pm
by PioPio
Sergey Tkachenko wrote:But if all the components are in the same frame, you can assign links between them when designing the frame, and they will be retained when you use this frame, am I right?
Hi Sergey,

Yes, that was the initial idea. I tried the following code:

Code: Select all

type
	TRVEditFrame = class(TFrame)
		RVFontSizeComboBox1: TRVFontSizeComboBox;
		RVFontComboBox1: TRVFontComboBox;
	private
	 { Private declarations }
		FRVEditor:TCustomRichView;
	public
	 { Public declarations }
    procedure Loaded;override;
	protected
		function GetRVEditor:TCustomRichView;
		procedure SetRVEditor(Editor:TCustomRichView);
	published
		property RVEditor:TCustomRichView read GetRVEditor write SetRVEditor;
	end;

	
	
procedure TRVEditFrame.Loaded;
begin
  inherited;
  if Assigned(RVEditor) then 
    SetRVEditor(RVEditor);
end;

function TRVEditFrame.GetRVEditor:TCustomRichView;
begin
	Result:=FRVEditor;
end;

procedure TRVEditFrame.SetRVEditor(Editor:TCustomRichView);
begin
	if Assigned(Editor) then begin
		FRVEditor:=Editor;

      RVAControlPanel1.DefaultControl:=FRVEditor;
      RVFontComboBox1.Editor:=FRVEditor;
      RVFontComboBox1.Font.Name:=RVAControlPanel1.DialogFontName;
      RVFontSizeComboBox1.Editor:=FRVEditor;
      RVFontSizeComboBox1.Font.Name:=RVAControlPanel1.DialogFontName;

	end;
end;
Then I registered the component, dropped it on a form and linked RVEditor, RVFontSizeComboBox1 and RVFontComboBox1 to a TCustomRichViewEdit descendent I dropped on the component on design time.

I ran the project but RVFontSizeComboBox1 and RVFontComboBox1 don't show the font name and relevant size as they do in your examples ActionTestRibbon for instance.

It seems RVFontSizeComboBox1.Editor and RVFontComboBox1.Editor are set to nil at runtime but I don't know why.