Yesterday I fixed a long standing bug in my IDE Auto Save (https://www.davidghoyle.co.uk/WordPress/?page_id=918) plug-in which would either lock up the IDE or as it did yesterday when working on another plug-in, crash the IDE.
What was happening was that I had created a new unit for some code and was in the middle of manually saving the code when my plug-in decided to auto save and displayed another Save As dialogue. Once this happens, and I’ve seen it many times now, you either end up not being able to save the file with the IDE locking up or as per yesterday, it crashed the IDE for the first time (I’m using 10.3.2).
So I needed a way to test whether the IDE was in a modal state before attempting to save any files. A quick web search shows the following item from Stack Overflow (https://stackoverflow.com/questions/3306260/delphi-detecting-if-my-app-has-a-modal-dialog-open) which looked promising.
The article refers to a property of the TApplication
class called ModalLevel
which should indicated whether the application is in a modal state if the level returned is greater than zero. Since the IDE is a Delphi application this should be simple to check this property however under testing I found that this did not work all the time. For instance, in my primary case of saving a file the ModalLevel
returned zero but if the Open Unit dialogue is on the screen it returned 1. So that wasn’t going to work 🙁
However further, down the article someone suggested using the windows API call IsWindowEnabled()
and I found that that worked all the time.
So I updated by code as follows to fix the issue:
Procedure TDGHAutoSaveWizard.TimerEvent(Sender: TObject); {$IFDEF DEBUG} Const strIDEInModalState = 'IDE is in a modal state (%d)!'; {$ENDIF DEBUG} Begin FTimer.Enabled := False; Try Inc(FCounter); If FCounter >= FSettings.Interval Then Begin If FSettings.Enabled Then If IsWindowEnabled(Application.MainForm.Handle) Then // New Test Begin FCounter := 0; // Moved from earlier to ensure autosave engages // immediately after the modal state finishes TDGHIDEAutoSaveToolsAPIFunctions.SaveAllModifiedFiles(FSettings); End {$IFDEF DEBUG} Else // Debugging code where I would the issue CodeSite.SendFmtMsg(strIDEInModalState, [Application.ModalLevel]) {$ENDIF DEBUG} ; End; Finally FTimer.Enabled := True; End; End;
Regards
Dave