giomach 1 Posted June 17, 2022 A rather basic question, sorry. In the middle of a fairly large program, I want to put some items in a TListBox, display it, click on an item, and continue the program taking account of the item clicked. My code is like this: FocalForm.LemmaListBox.Clear; FocalForm.LemmaListBox.Show; for i := nwordfirst to nwordlast do begin getword (i, jstoretmp, jhmgrphtmp, whead, nheadlast); FocalForm.LemmaListBox.Items.Add (jstoretmp); end; {x} nwordfirst := nwordfirst + FocalForm.LemmaListBox.ItemIndex; etc. When this is run, the ListBox is displayed correctly, but there is no opportunity to click it, and the program carries on with ItemIndex = -1. I've tried setting focus to the ListBox but it makes no difference. I can get the desired result by inserting the following code at point {x}: repeat Application.ProcessMessages until Focalform.LemmaListBox.Visible = false; and having the ListBox OnClick set Visible to false. But I am uneasy with that technique — is there a better way? Thank you. Share this post Link to post
corneliusdavid 220 Posted June 17, 2022 You need to give control back to Windows to let it send your application an OnClick event. So instead of handling the selected item within the same procedure, load the ListBox and that's all; move the rest of the code to your OnClick event handler--it will be called once the ListBox is clicked. This book might be useful: https://dalija.prasnikar.info/delphiebap/index.html Share this post Link to post
giomach 1 Posted June 17, 2022 Thanks, that clarifies things. Unfortunately the suggested solution would be difficult given the program structure — the code snippet occurs in one branch of an if statement, and the bulk of the rest of the code comes outside that if statement, after the branches re-unite. Rather than undertake a large-scale program restructure, I think I'll regretfully stick with application.processmessages. Share this post Link to post
corneliusdavid 220 Posted June 17, 2022 I'm re-reading your post and realize you're accessing a different form, FocalForm. So if that's on a different form than the posted code, use ShowModal instead of Show and call that after you've loaded the items. ShowModal will show the form and wait for it to be closed before continuing: begin ... else if ChooseFocalForm then begin FocalForm.LemmaListBox.Clear; for i := nwordfirst to nwordlast do begin getword (i, jstoretmp, jhmgrphtmp, whead, nheadlast); FocalForm.LemmaListBox.Items.Add (jstoretmp); end; FocalFormResult := FocalForm.LemmaListBox.ShowModal; // <--waits for Windows to handle form and return if FocalFormResult = mrOK then nwordfirst := nwordfirst + FocalForm.LemmaListBox.ItemIndex end else ... Share this post Link to post
Remy Lebeau 1436 Posted June 17, 2022 4 minutes ago, corneliusdavid said: use ShowModal instead of Show and call that after you've loaded the items. ShowModal will show the form and wait for it to be closed before continuing That is what I was thinking, too. Share this post Link to post
giomach 1 Posted June 18, 2022 Thanks for your replies. FocalForm is the only form in my application. The code snippet occurs in the implementation section of the form, but in a procedure which is not declared as a member of the TFocalForm class.(Perhaps the procedure could/should be so declared, if that would make any difference in this case.) At present, the statement FocalFormResult := FocalForm.LemmaListBox.ShowModal; produces the error undeclared identifier:'ShowModal'. I'm guessing that I would have to create a second form/unit just to hold the TListBox before I can use ShowModal on it. If that's so, I think I prefer my present method which keeps the TListBox integrated with the rest of the form, so that eg. I can control its placement, and I can allow some of the other controls to remain accessible while the TListBox is waiting to be clicked. Share this post Link to post
corneliusdavid 220 Posted June 19, 2022 I mistyped; that line should've been: FocalFormResult := FocalForm.ShowModal; Share this post Link to post