Janek.d 0 Posted June 23, 2020 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
Mahdi Safsafi 225 Posted June 24, 2020 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
Mahdi Safsafi 225 Posted June 24, 2020 @Janek.d Remember that's not the proper way ! So please report the bug at QC. Share this post Link to post
Remy Lebeau 1396 Posted June 24, 2020 (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 June 24, 2020 by Remy Lebeau 1 Share this post Link to post
Mahdi Safsafi 225 Posted June 25, 2020 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
David Heffernan 2345 Posted June 25, 2020 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
Mahdi Safsafi 225 Posted June 25, 2020 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
David Heffernan 2345 Posted June 25, 2020 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. 1 Share this post Link to post
Mahdi Safsafi 225 Posted June 25, 2020 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
David Heffernan 2345 Posted June 25, 2020 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
Remy Lebeau 1396 Posted June 25, 2020 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
Attila Kovacs 629 Posted June 25, 2020 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. Share this post Link to post
Mahdi Safsafi 225 Posted June 25, 2020 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
Anders Melander 1783 Posted June 25, 2020 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). 1 Share this post Link to post
Remy Lebeau 1396 Posted June 25, 2020 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. 1 Share this post Link to post
Mahdi Safsafi 225 Posted June 25, 2020 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
Anders Melander 1783 Posted June 26, 2020 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. 1 Share this post Link to post
Daniel 417 Posted June 26, 2020 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. 3 Share this post Link to post
Mahdi Safsafi 225 Posted June 26, 2020 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. 1 Share this post Link to post