PenelopeSkye 1 Posted April 20, 2022 I must have performed the search incorrectly because I did not find anything like this, so please point me to wherever I should be looking for answers to this question. I am a newbie to both Delphi\pascal and the forum. I have an app that brings up a search dialog box that leads to a result dialog box. When the result dialog box appears the focus is always on the last button pushed when last in the result dialog box. How do I get a specific button (the OK button) to always have focus no matter what button was last pushed? I tried clicking on the button in the IDE (Delphi 10.3) to see if there was an ActiveControl property in the object inspector but there is not. How can I set focus to the OK button? Thanks! Share this post Link to post
Anders Melander 1783 Posted April 20, 2022 Set it in code: ButtonOK.SetFocus; The ActiveControl property is a property of the form but that is only applied when the form is first created and it sounds like you are only doing that once. Share this post Link to post
PeterBelow 238 Posted April 21, 2022 13 hours ago, PenelopeSkye said: I must have performed the search incorrectly because I did not find anything like this, so please point me to wherever I should be looking for answers to this question. I am a newbie to both Delphi\pascal and the forum. I have an app that brings up a search dialog box that leads to a result dialog box. When the result dialog box appears the focus is always on the last button pushed when last in the result dialog box. How do I get a specific button (the OK button) to always have focus no matter what button was last pushed? I tried clicking on the button in the IDE (Delphi 10.3) to see if there was an ActiveControl property in the object inspector but there is not. How can I set focus to the OK button? Thanks! In addition to Anders' reply: note that (VCL) buttons have two useful properties for dialog boxes: Default - if you set that to true the button will "click" if the user hits the Enter or Return key, regardless of whether the button has focus or not. Cancel - if that is set to true the ESC key will click the button. If the button's ModalResult is set to mrCancel that will close the dialog. Share this post Link to post
PenelopeSkye 1 Posted April 21, 2022 Thanks Anders, I had tried adding BitBtn1.SetFocus; in various places but that didn't work either. Do you see a place for it in the code below? I get to this code by selecting the OK button and then going to code. And thank you PeterBelow, I am not even sure where to check Default or Cancel! I am finding the IDE to be very confusing to find things!!! unit ChooseResult; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, Wwdbigrd, Wwdbgrid, StdCtrls, Buttons, DB, ExtCtrls; type TfChooseResult = class(TForm) wwDBGrid1: TwwDBGrid; Panel1: TPanel; dsResult: TDataSource; BitBtn1: TBitBtn; BitBtn2: TBitBtn; procedure wwDBGrid1DblClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var fChooseResult: TfChooseResult; implementation {$R *.dfm} procedure TfChooseResult.wwDBGrid1DblClick(Sender: TObject); begin BitBtn1.click; end; end. Share this post Link to post
Stano 143 Posted April 21, 2022 (edited) Not very confusing. But it provides many options. Luxury is paid for. Check the Arrange - by Category option in the Object Inspector. So it's clearer. All events begin with the prefix On. So BitBtn1.OnClick. Edited April 21, 2022 by Stano Share this post Link to post
Anders Melander 1783 Posted April 21, 2022 Assuming that you're showing this form modally from somewhere else I would do it like this: type TfChooseResult = class(TForm) wwDBGrid1: TwwDBGrid; Panel1: TPanel; dsResult: TDataSource; BitBtn1: TBitBtn; BitBtn2: TBitBtn; procedure wwDBGrid1DblClick(Sender: TObject); private public function Execute: boolean; end; var fChooseResult: TfChooseResult; implementation {$R *.dfm} procedure TfChooseResult.wwDBGrid1DblClick(Sender: TObject); begin BitBtn1.click; end; function TfChooseResult.Execute: boolean; begin BitBtn1.SetFocus; Result := (ShowModal = mrOK); end; and then display the form like this: begin ...do other stuff here... if (fChooseResult.Execute) then begin // User pressed OK end else begin // User closed dialog some other way end; end; And like Peter suggested, set the ModalResult property of the OK button to mrOK and the Default property of the same to True. If you add a Cancel button, set its ModalResult property to mrCancel and the Cancel property to True. If you're not displaying the form modally, then you'll need to call SetFocus in the forms OnShow event handler instead. This of course assumes that the form isn't visible all the time. 44 minutes ago, PenelopeSkye said: I am not even sure where to check Default or Cancel! I am finding the IDE to be very confusing to find things!!! Share this post Link to post
Anders Melander 1783 Posted April 21, 2022 2 minutes ago, Stano said: All events begin with the prefix On. So BitBtn1.OnClick. Nope. He's not calling the event handler. He's calling the Click method on the button - which emulates a click on the button. Share this post Link to post
Anders Melander 1783 Posted April 21, 2022 By the way, do yourself a favor and stop using TBitBtn. They were cute in the nineties. Not anymore. Share this post Link to post
Stano 143 Posted April 21, 2022 I learned something new again. Well thank you. Share this post Link to post
Pat Foley 51 Posted April 22, 2022 (edited) 23 hours ago, PenelopeSkye said: procedure TfChooseResult.wwDBGrid1DblClick(Sender: TObject); begin BitBtn1.click; end; Since you are working with Delphi now. There's a lot to learn about how get Delphi to speak to the Oracle or least a database. One step is learning about TDataModule. They're used in some examples. The quote has a button click inside a double click which is inside a dialog. How about enabling controls when needed. Hiding buttons are bad, better to have disabled buttons as placeholders with hints what is needed first. Pat Edited April 22, 2022 by Pat Foley Removed example Share this post Link to post
Anders Melander 1783 Posted April 22, 2022 @Pat Foley That example was really confusing - and contains so many bad practices. Share this post Link to post
PenelopeSkye 1 Posted April 22, 2022 Thank you everyone! Apologies if I seem to be ignoring some posts\bits of information, I am trying to just keep my head above water! I have located all the items in the object inspector (thank you!) and all the properties were already set to what was mentioned above. I added the Execute code mentioned above but the instructions say to then display the form, but the code to call the form has already been written and is being called elsewhere. I think one of my problems is that I don't understand where this form is being called from. The process is as follows: 1. While in the app (that has been created\finished long ago and is in constant use) the user hits the key press sequence 'ctrl-S' and a dialog box appears with a text box 2. The user types in a number to search on, and presses OK. This is the point where the dialog box with the OK button requiring focus is being called. Should I be looking for the code from the previous dialog box where the user types the search text in order to set focus or should I stick with the code I already posted? Again it is probably very annoying to deal with newbies, please hang in there, I am studying as I go and it is being very helpful!!! Thank you!!! Share this post Link to post
Anders Melander 1783 Posted April 22, 2022 4 minutes ago, PenelopeSkye said: Should I be looking for the code from the previous dialog box where the user types the search text in order to set focus Yes You can use Search->Find in files (Ctrl+Shift+F) to locate the place. Search for " fChooseResult .Show". 6 minutes ago, PenelopeSkye said: Again it is probably very annoying to deal with newbies, please hang in there, I am studying as I go and it is being very helpful!!! Thank you!!! No problem. Happy to help. Share this post Link to post
PenelopeSkye 1 Posted April 22, 2022 (edited) This is the code where the user puts in the search text (a stock number) and if it is valid the dialog box shows up with the OK button requiring focus! I tried inserting fChooseResult.showModal=mrCancel then fChooseResult.BitBtn1.SetFocus; as well as several other things and it either didn't work or it gave an error message: "Cannot focus a disabled or invisible window" Ideas? Thank you!!! procedure TfDesignMaster.FindStockNumber1Click(Sender: TObject); var stocksearch: string; did: string; begin stocksearch:=inputbox('Search','Enter Stock Number',''); //find Stock Number if stocksearch<>'' then begin did:=''; //dm.tb_design_master.locate('jmc_stock_num',stocksearch,[]); //execute query for Stock # if dm.qStockNum.active then dm.qStockNum.close; dm.qStockNum.Parameters[0].value:=stocksearch; dm.qStockNum.open; if dm.qStockNum.recordcount>1 then begin //Show list of designs fChooseResult.dsResult.DataSet:=dm.qStockNum; if fChooseResult.showModal=mrOK then did:=dm.qStockNum.fieldbyname('design_id').asstring; fChooseResult.dsResult.DataSet:=nil; end else did:=dm.qStockNum.fieldbyname('design_id').asstring; if dm.qStockNum.recordcount=0 then messagedlg('Not found',mtError,[mbOK],0) else datagoto(did); //dm.tb_design_master.locate('design_id',did,[]); dm.qStockNum.close; end; end; Edited May 20, 2022 by Sherlock Wrapped code in code tags. Share this post Link to post
Stano 143 Posted April 22, 2022 an error message: "Cannot focus a disabled or invisible window" clearly states what this is about. You need to make sure that the window where you want to target a component is visible and accessible. You don't have one of them (or both). Only debugging (with Break point) will help here. Share this post Link to post
Anders Melander 1783 Posted April 22, 2022 (edited) Replace this: if fChooseResult.showModal=mrOK then did:=dm.qStockNum.fieldbyname('design_id').asstring; with: if fChooseResult.Execute then did := dm.qStockNum.FieldByName('design_id').AsString; and then modify the TfChooseResult form like this: const MSG_AFTERSHOW = WM_USER; type TfChooseResult = class(TForm) ... protected procedure MsgAfterShow(var Msg: TMessage); message MSG_AFTERSHOW; public function Execute: boolean; end; implementation {$R *.dfm} procedure TfChooseResult.MsgAfterShow(var Msg: TMessage); begin BitBtn1.SetFocus; end; function TfChooseResult.Execute: boolean; begin PostMessage(Handle, MSG_AFTERSHOW, 0, 0); Result := (ShowModal = mrOK); end; Edit: Maybe I should explain what's going on. The PostMessage puts a custom message into the form's message queue. When ShowModal is called the form is displayed and the modal loop pumps the message queue [*]. The message pump grabs the custom message from the queue and calls the form's message handler (the MsgAfterShow method). MsgAfterShow focuses the button. [*] Pumping the message queue means that the code loops, reading one message at a time from the message queue and dispatching these messages to the "message handlers". It's "a bit" more complicated than that but hopefully you get the overall picture. Edited April 22, 2022 by Anders Melander Share this post Link to post
PenelopeSkye 1 Posted April 25, 2022 Hi Anders, this produced a a few errors that I am trying to figure out without bugging you with each one 🙂. Share this post Link to post
PenelopeSkye 1 Posted May 18, 2022 I finally had to go to a developer in my company. The issue was that the modal dialog box was being created and destroyed in the same step. She had me create a procedure that creates the modal dialog box, set the focus, then close it and it worked. Thanks Anders! Share this post Link to post