Jump to content
Janek.d

Load form icon while using styles

Recommended Posts

I try to load form icon in run-time (in 'FormCreate'):

 

    main_form.Icon.LoadFromFile(ico_file);

It works fine if default windows style is selected for application.

It fails if any custom style is selected (not any error raising...)

 

Is this function disabled while custom styles is used?

Any experiences?

I use Delphi 10.2

Thanks in advance...

Share this post


Link to post

The problem is that TFormStyleHook uses a cached version of Icon(See TFormStyleHook .GetIconFast ). Once the StyleHook is attached to a form it makes a cached copy of its icon. However it does not update the cache when you change the icon.

 

Quote

Is this function disabled while custom styles is used?

This is a bug !

Until we have a fix, you may need to recreate the window handle in order to change the icon.

  main_form.Icon.LoadFromFile(ico_file);
  main_form.Perform(CM_RECREATEWND, 0, 0);

 

Share this post


Link to post
Posted (edited)
6 hours ago, Mahdi Safsafi said:

Until we have a fix, you may need to recreate the window handle in order to change the icon.


  main_form.Icon.LoadFromFile(ico_file);
  main_form.Perform(CM_RECREATEWND, 0, 0);

 

Just FYI, you should call the form's RecreateWnd() method instead of issuing the CM_RECREATEWND message manually.

 

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post
2 hours ago, Remy Lebeau said:

Just FYI, you should call the form's RecreateWnd() method instead of issuing the CM_RECREATEWND message manually.

 

For Main form that's not necessary. RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

 

 

Share this post


Link to post
6 hours ago, Mahdi Safsafi said:

For Main form that's not necessary. RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

This doesn't make sense to me. I don't see the argument for sending a private implementation specific message rather than calling the RecreateWnd method. 

Share this post


Link to post
1 hour ago, David Heffernan said:

This doesn't make sense to me. I don't see the argument for sending a private implementation specific message rather than calling the RecreateWnd method. 

We have plenty of private implementation specific message (CM_XX) should we make XX() for each ?

FYI, there is no concept of private/protected for messages. Messages are public !

I'd understand if the logic was implemented in RecreateWnd but that's not the case here !

Share this post


Link to post
3 hours ago, Mahdi Safsafi said:

FYI, there is no concept of private/protected for messages. Messages are public !

Not so. For sure the language doesn't stop you using any message you like. But that doesn't mean that it is reasonable to do so. Oftentimes messages are used in the private implementation detail for a class.  As a broad principle, you should not be looking to work with Windows messages when consuming VCL controls.  Sometimes one is forced into it because the control provides no official mechanism.  But when we do that, it is brittle, and subject to future implementation detail changes.

 

3 hours ago, Mahdi Safsafi said:

I'd understand if the logic was implemented in RecreateWnd but that's not the case here !

And there it is.  There's the point where you take a dependency on on implementation details.

 

The implementation of RecreateWnd is:

procedure TWinControl.RecreateWnd;
begin
  if WindowHandle <> 0 then Perform(CM_RECREATEWND, 0, 0);
end;

There is a difference between this code and yours. Your code does something unconditionally. But RecreateWnd does nothing if the window handle has not already been created.

 

I'm quite sure that you've got this wrong.  I mean, it won't have any material impact on things, but one may as well do things the right way.

  • Like 1

Share this post


Link to post
Quote

As a broad principle, you should not be looking to work with Windows messages when consuming VCL controls.  Sometimes one is forced into it because the control provides no official mechanism.  But when we do that, it is brittle, and subject to future implementation detail changes.

I wish if you were right ... but things are much much more complex than that. E.g : sometimes there is an official mechanism but you choose message instead because you don't want the official mechanism to perform a paint for example ... there is a lot of those examples.

Quote

And there it is.  There's the point where you take a dependency on on implementation details.

I didn't take any dependency (please read my example again) !

Quote

RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

When you know that the handle is allocated, its just pointless to call RecreateWnd instead of CM_RECREATEWND. 

procedure Main.StyleChanged;
begin
// I won't be here if handle is empty.
// Perform(CM_RECREATEWND, ...);

// VCL core is using the same Principle too ... take a look at Vcl.Forms,... (there are call to Perform(CM_RECREATEWND) instead of RecreateWnd). 
end;

Share this post


Link to post
3 hours ago, Mahdi Safsafi said:

I wish if you were right ... but things are much much more complex than that. E.g : sometimes there is an official mechanism but you choose message instead because you don't want the official mechanism to perform a paint for example ... there is a lot of those examples.

I also talked about such examples. This isn't one of them. 

 

3 hours ago, Mahdi Safsafi said:

I didn't take any dependency (please read my example again) !

You said, "I'd understand if the logic was implemented in RecreateWnd but that's not the case here". You literally talk about making a choice based on the implementation details.

 

I still can't see why you are set against calling RecreateWnd. That seems perverse to me. 

Share this post


Link to post
17 hours ago, Mahdi Safsafi said:

For Main form that's not necessary. RecreateWnd is useful when creating dynamic controls as you don't know when there would be the handle available.

RecreateWnd() is used when ANY control, even a MainForm, needs a new HWND for ANY reason.  This is most commonly used when applying new property values that are applied only when a new HWND is created, rather than using SetWindowLong() or similar API to update an existing HWND.  But ReceiveWnd() is not limited to just those use cases, and is not specific to dynamic controls alone.

 

And yes, you do know exactly when the HWND will be available - when the control's Handle property is accessed.  RecreateWnd() merely signals a control to destroy its current HWND.  A new HWND is then created the next time the Handle property is accessed afterwards.

Share this post


Link to post

total pointless debate, doesn't matter a thing which one you call, and the implementation won't change in the next 40 years, nor the bug will be fixed.

 

  • Like 1

Share this post


Link to post
Quote

You said, "I'd understand if the logic was implemented in RecreateWnd but that's not the case here". You literally talk about making a choice based on the implementation details.

Yes, I make a lot of choice based on implementation details ! don't you ? 

Quote

I still can't see why you are set against calling RecreateWnd.

 

Simply you didn't convince me (it requires more than words to convince someone) !

Quote

That seems perverse to me. 

Do you use "perverse" each time you disagree with someone ? 

Share this post


Link to post
3 hours ago, Mahdi Safsafi said:

Yes, I make a lot of choice based on implementation details ! don't you ? 

I think the point is that you are violating the API contract; You are supposed to call the API but instead you are circumventing the API and calling the implementation directly - for no good reason. Sometimes there are good reasons to do so but this isn't one of them so it seems you are doing so just because you can, because you don't know better or because you are stubborn.

 

3 hours ago, Mahdi Safsafi said:

Do you use "perverse" each time you disagree with someone ?

There are multiple definitions of perverse. In this case I think David meant obstinate in opposing what is right, reasonable, or accepted (from Merriam-Webster).

  • Like 1

Share this post


Link to post
4 hours ago, Attila Kovacs said:

the implementation won't change in the next 40 years

And you can see the future ... how, exactly?

4 hours ago, Attila Kovacs said:

nor the bug will be fixed.

If nobody reports it, and nobody votes on it, then that is a likely certainty.

  • Like 1

Share this post


Link to post
Quote

I think the point is that you are violating the API contract ... blablabla....

Prove it ! FYI, the vcl core is calling CM_RECREATEWND directly.

Quote

it seems you are doing so just because you can, because you don't know better or because you are stubborn.

You're not the judge here ! 

Quote

There are multiple definitions of perverse. In this case I think David meant obstinate in opposing what is right, reasonable, or accepted (from Merriam-Webster).

 

Don't speak on his name. He is definitely able/free to explain what he means ! 

David tell your friends there is no need to interfere ... I really started thinking you guys are making a kind of gang here. 

Share this post


Link to post
32 minutes ago, Mahdi Safsafi said:

Prove it ! FYI, the vcl core is calling CM_RECREATEWND directly.

That's pretty easy: RecreateWnd is part of the documented public API. CM_RECREATEWND is undocumented.

The VCL core is the implementation of the API so there's no surprise there.

 

33 minutes ago, Mahdi Safsafi said:

You're not the judge here

No I am not. I said "it seems" so I'm talking about appearances. I have no idea about why you do what you do so I can only guess.

 

37 minutes ago, Mahdi Safsafi said:

Don't speak on his name. He is definitely able/free to explain what he means ! 

David tell your friends there is no need to interfere ... I really started thinking you guys are making a kind of gang here. 

Calm down. I'm free to state what I think he means since it seems you misunderstood what he said.

There is no conspiracy here and we're not all out to get you. We just disagree with you.

  • Like 1

Share this post


Link to post

Mahdi - again: calm down now. This is not the first time I have to tell you to calm down.

it is pretty simple: if you feel unable to have a focused discussion on a topic, just don’t do it. You must stop personal attacks against other members.

we come from all over the world, many of us are not native English speakers. So, well, yes, we might understand the wording of another member in different ways. Please keep this in mind. But there is a consensus that some(!) of your posts tend to be personal against other members. So, please step down a little. Soon.

  • Like 3

Share this post


Link to post
Quote

Mahdi - again: calm down now. This is not the first time I have to tell you to calm down.

And that's not your first time when you show un-professionalism behavior(remember last time) !

Quote

You must stop personal attacks against other members.

I believe that I never showed disrespect for anyone here. All what I did is argumenting. So I really don't know why you think that disagree with someone is an attack !

And telling someone that he is not a judge, I think that's not an attack ... is it ?

Quote

if you feel unable to have a focused discussion on a topic, just don’t do it.
But there is a consensus that some(!) of your posts tend to be personal against other members.

Go on all those posts, I challenge you to prove that its me who started a discussion !

For this post, I gave an explanation to the bug, as well as an answer, I was argumenting with some people peacefully ... until some people started provocating me! 

So please don't be driven by your subjectivity and try to view things neutrally.

Peace.

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×