McScotty 0 Posted October 26, 2019 I have come across an issue with Delphi and Windows 10. I have an old app done in Delphi 2007 and although the application appears to work fine in Windows 10, if you create a modal dialog from your main form and then close down, the dialod but not main form, then hover your mouse over the task preview, you see the main form, but you also see the dialog windows as well even though it was already closed. Clicking on the preview brings the window to be the fore, and the dialog disappears again. Other than that, there does not appear to be any issue, it just looks very unprofessional, especially if you have a lot of dialogs within an app. To see this you have to hover over the taskbar icon, this works fine, but then move your mouse into the thumbnail windows. It is only at this point you see the dialog you previously had open, along with other rectangular windows outlines. I did not have the MainFormOnTaskbar := true set (My app was originally ported from D2006) but I have set it before the creation of the main form in the .dpr file and it has absolutely no impact at all. However if I move this line to be run immediately after the main form creation, it looks like it works. I read online that this line must be run before the main form, so looking for some advise please. This issue seems to persist across different Delphi versions, and I am also seeing it in 10.3 Rio. I can understand D2007 as it pre-dates Win10 but how come this get through QC testing in 10.3 Rio and has not largely been reported elsewhere. I found another work-around. If I put Params.WndParent:=application.Handle; into the dialog, this seems to fix this issue in D2007 at least. Is this safe to use in this mannor, not sure why it works as the handle is the same handle it would have if I had never put this code in, but it does seem to work. Would appreciate some advise from anyone who can help. Thanks David. Share this post Link to post
pyscripter 689 Posted October 26, 2019 I do not see this issue with Delphi applications created with Delphi Rio. Application.MainFormOnTaskbar := True; is called before the creation of the main form in the dpr file. Share this post Link to post
McScotty 0 Posted October 26, 2019 That is interesting. Here is my code if you care to look at it. Open up application and then click on the button. Close down the dialog box then put hover mouse over taskbar icon, then move mouse into thumbnail image. It is only the latter part that things look wrong. DRioExample.zip Share this post Link to post
McScotty 0 Posted October 26, 2019 (edited) And here is the output I am getting. Note the dialog on the left is closed down, and this is only visible when you hover over the small square thumbnail above the taskbar that Windows creates. if you then click on this thumbnail, the application comes to the fore, but the dialog is no longer there. Edited October 26, 2019 by McScotty Share this post Link to post
pyscripter 689 Posted October 26, 2019 I could reproduce the problem. However I would suggest that you do not auto-create dialog forms. In Project, Options, Forms remove the OKRightDlg from the list of auto-created forms (move it to the right). Replace TForm1.Button1Click with something like this: procedure TForm1.Button1Click(Sender: TObject); begin with TOKRightDlg.Create(Self) do begin PopupParent := Self; ShowModal; Release; end; end; Share this post Link to post
McScotty 0 Posted October 26, 2019 I can get the above code to work without issue as well, but the only reason it appears to be working is due to the release at the end. If you want to create a dialog just once within the application so do not release it, you still have the same problem. I normally create the dialogs on demand when I need them, but do not release them so that I can run code once in the creating of the dialog which could be slow in some areas, keeping the dialog after creatinon speeds up the app. So this issue still exists. Any other ideas? I have found that if I override the creation of the dialog as follows.... protected procedure CreateParams(var Params: TCreateParams); override; (under public declarations) then the below in the implementation section of the dialog... procedure TOKRightDlg.CreateParams(var Params: TCreateParams); begin inherited; Params.WndParent:=application.Handle; end; That this code appears to make the dialog work. but if you modify the code to be Params.WndParent:=application.MainForm.Handle; it stops working again. It would appear to be some issue regarding Delphi and the MainFormHandle in 10.3 Rio. Interestingly, in D2007 using the same code on Win 10 avoids the problem like in 10.3 Rio, but changing the parms to application.maiform.handle or just application.handle works either way, they both result in the same value. Anyone have some idea what is going on? Share this post Link to post
David Heffernan 2347 Posted October 26, 2019 Destroy the form when you close it. It's as simple as that. If you want to preserve some state between invocations, put that in a separate object. Forms should just present views anyway, and not be part of your apps business logic. 5 Share this post Link to post
McScotty 0 Posted October 26, 2019 The reason I use the OnCreate in some forms is to fill comboboxes with names from a database for example. I only want to do this once per invocation of the form so I just re-use the existing form rather than destroy it and having to go through the same process again every time I want to show the dialog. Is there a better way to do this that I am not aware of? Share this post Link to post
Uwe Raabe 2059 Posted October 26, 2019 You can create the instance on first use and then reuse it when needed. 1 Share this post Link to post
David Heffernan 2347 Posted October 26, 2019 What is the downside of creating the form when you need it and destroying it when it is closed? 1 Share this post Link to post
Attila Kovacs 629 Posted October 26, 2019 2 hours ago, McScotty said: The reason I use the OnCreate in some forms is to fill comboboxes with names from a database for example and what if the db changes in the meantime? 1 Share this post Link to post
Anders Melander 1795 Posted October 26, 2019 9 hours ago, pyscripter said: with TOKRightDlg.Create(Self) do begin PopupParent := Self; ShowModal; Release; end; There's generally no need for TForm.Release when you destroy the form from the outside. Just call Free directly. Share this post Link to post
aehimself 396 Posted October 26, 2019 You can actually reproduce the issue (on 10.2) by dialog.Visible := Not dialog.Visible. I suppose the issue is that since the window object is not actually closing (default closing action is to hide only), the preview is not getting refreshed automatically. If you really would like to keep it this way, use the MainFormOnTaskbar or the .Handle workaround which you discovered. I suspect this is only an other bug though. I agree with everyone else though - do not auto-create windows. If you want to load data only once, load it into an object in your main form (like a DataSet or a TStringList) and send that to your dialog form with a reintroduced .Create or an additional .Init method. As all forms of your application are running in the same thread, passing any object should be safe - if you are 100% sure that only one form is using them, at least, a time. Share this post Link to post
McScotty 0 Posted October 26, 2019 5 hours ago, David Heffernan said: What is the downside of creating the form when you need it and destroying it when it is closed? The downside is simply speed. If you have to fill a combobox with names for instance, doing this only once per application session is advantageous rather than destroying and having to fill the combo boxes again and again... So this appears to be a specific bug in Delphi regarding Windows 10 and no know official fix other than closing the dialog so it can't be used again unless re-created. If this is the official response, then it means there is little point in ever using the oncreate event in a dialog, which to be fair, I thought was the whole purpose of doing something only once, not every time you show the dialog. I have to say I am a bit disappointed that this is the case in 10.3 Rio. I can however understand why it happens in D2007 as it predates Windows 10. Share this post Link to post
McScotty 0 Posted October 26, 2019 7 hours ago, Uwe Raabe said: You can create the instance on first use and then reuse it when needed. Indeed that is what I have been doing, by not releasing the dialog, and just re-using. However by doing so, this bug surfaces in Windows 10, hence the original question. Share this post Link to post
David Heffernan 2347 Posted October 26, 2019 1 hour ago, McScotty said: The downside is simply speed. If you have to fill a combobox with names for instance, doing this only once per application session is advantageous rather than destroying and having to fill the combo boxes again and again... Not so. Populating a combo takes no discernible time. Try measuring it. 1 Share this post Link to post
McScotty 0 Posted October 26, 2019 10 minutes ago, David Heffernan said: Not so. Populating a combo takes no discernible time. Try measuring it. It depends where the data comes from, connecting to a DB will take a bit of time and it depends on how much data you are getting in the first place. Also if you want a dialog to remember your last selection this is easy to do by simply not releasing the dialog. Also it avoids unnecessary processing, if you can do it once, that should be the best way to do it, rather than multiple times Anyway, this thread is about a bug that appears to be in Delphi since at least D2007 up to current version that is only exposed in Windows 10 and if/what are the possible solutions/work-arounds that can be achieved without having to release the dialog. Share this post Link to post
David Heffernan 2347 Posted October 26, 2019 So store the data in a collection and populate from that. Instant. And it's better not to use visual controls as data stores. They should just present views. Destroying the form when you close it solves your problem. And the performance issue is easily dealt with as I have described. 1 Share this post Link to post
McScotty 0 Posted October 26, 2019 Well I agree destroying the dialog does indeed solve the problem, but it does not resolve the issue that has surfaced with Windows 10. I still stand by populating the combobox once for any instance of an application is better because you only need to populate once, not every time, regardless of where you get the data from. To me that seems like unnecessary processing. Share this post Link to post
David Heffernan 2347 Posted October 26, 2019 OK. Carry on the way you are doing it, and accept the preview oddity. I'm just trying to describe how to avoid that. But maybe it's less important to you. 1 Share this post Link to post
McScotty 0 Posted October 26, 2019 Thanks for your advice, as I said I agree that releasing the dialog will do the trick and I am able to do this easily on some of the dialogs, others I would prefer I could populate once and then re-use so I would have liked it if there was a solution. Perhaps it is the one I have already suggested myself, I just want to know that I am not doing something stupid that will cause issues later on. I wish the they had fixed this bug in 10.3 though, its not very good that this issue persists now that W10 has been around for a few years. Share this post Link to post
McScotty 0 Posted October 27, 2019 I have reported this to Embarcadero and I see that other people have reported similar issues back on 2008 and as yet still no fix or further information. Hopefully someone can comment on my possible solution and say if they think it is safe to do what I proposed as a possible work-around rather than having to release the dialog. Thanks everyone for your comments so far. Share this post Link to post
David Heffernan 2347 Posted October 27, 2019 It's worth pointing out that this preview is drawn by the system. It's entirely plausible that there's nothing that Embarcadero could do to change the behaviour. Share this post Link to post
McScotty 0 Posted October 27, 2019 Yeah that is entirely possible but I have only heard of it with Delphi apps. It might be there is a simple solution that can be invoked such as forcing the thumbnail to redraw, I am not aware how to do that but I would be interested in if its possible, and if it will be another work-around. Share this post Link to post
David Heffernan 2347 Posted October 27, 2019 (edited) FWIW it is less nasty if you pass the main form as the owner of the dialog when you create it. You pass Application as the owner. Actually, I'm not sure that's true having played around a bit more. Edited October 27, 2019 by David Heffernan Share this post Link to post