Detect Dialog Altered

Technical support and scripting issues

Moderators: JRL, Dorian (MJT support)

Post Reply
User avatar
JRL
Automation Wizard
Posts: 3532
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Detect Dialog Altered

Post by JRL » Mon May 12, 2008 8:06 pm

Hi,
Is there an easy way to detect that something has been changed by the user of a dialog?

I have a dialog with a bunch of stuff in it. If the user enters data and picks "Save" the data contained in the dialog is saved to a file. If the user enters data and picks "Cancel" the data is not saved and is lost forever. What I would like to do is detect that the user has made any kind of change to the dialog. If the user then picks "Cancel" before picking "Save", pop up a "Are you sure" warning with an option to save.

Is there an easy way to accomplish this other than examining all fields to see if any were changed?

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Tue May 13, 2008 2:55 pm

You'd have to examine all fields. But you could have DIALOG_CHANGE OnEvent handlers for each dialog object all call the same subroutine which just sets a flag.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Tue May 13, 2008 3:06 pm

Hi JRL,

The code intensive (hard) way would be to save the state/value of every field and control, perhaps in an array and on Cancel, compare current state to what's in the array and if different, warn the user. This has the advantage that you could also tell the user what field/s had been changed and even... what the last "saved to disk state" was for that field/control compared to what it is now... but I take it you want something quick and dirty (easy).

A less code intensive, roundabout (and hopefully easier) way would be to use ScreenCapture> to save an image of your dialog as a jpg file when it first opens. For this to work, that saved image must show *all* your text data and controls. When user hits the save button, it should use ScreenCapture again and update the saved image file which represents your "saved values". Now lets say the user changes data in the dialog then hits Cancel. The subroutine that handles Cancel should use ScreenCapture> to take another image of the dialog, compare it with the saved image and if they are not the same, it must be because the user has changed something so warn the user.

Just a thought... If you try this approach and get this working, let us know.

If anyone else knows an easy way to detect changes in a dialog, please share.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3532
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Tue May 13, 2008 10:06 pm

jpuziano wrote:but I take it you want something quick and dirty (easy).
I did mention "EASY" a couple of times. :)

Both good ideas. Thank you Marcus and jpuziano. I'll try to remember to post a sample result when/if I come up with one.

Me_again
Automation Wizard
Posts: 1101
Joined: Fri Jan 07, 2005 5:55 pm
Location: Somewhere else on the planet

Post by Me_again » Tue May 13, 2008 10:21 pm

Can you have cancel actually save, but in a different set of variables?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed May 14, 2008 7:15 pm

Hi JRL,

When the user hits save, does it create a new separate instance of the file or is it just overwriting the same file every time? If there's just one file that you overwrite then there's another way you could simplify things:
  • - Offer only an Exit button on the dialog.

    - Put a label by the Exit button that says "All values saved to disk on Exit".

    - When they press Exit, save all values to disk before the macro ends.
If that would work for your situation... you can't get much easier. :D

Then, with all the time saved from such an easy approach, you might consider adding a validation subroutine:
  • - Right after saving the values to disk, you could read the values back from disk to compare them to the values in the dialog.

    - If they match, you've validated a good save and could display a message to the user like "Values saved and validated, have a nice day".

    - If they don't, you could try the save again and/or tell the user there was a problem or whatever course of action is appropriate... get a Mac, etc.
Hope this was helpful... or at least entertaining.

Take care
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3532
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Wed May 14, 2008 10:25 pm

Lots of good thoughts guys, thanks for your input.

Following is a sample of what I created and is now working for me. It functions in the way that I would expect a Microsoft program to function.

- If no changes are made to the document (dialog) and the "Close" button is picked, the document (dialog) closes.

- If any changes of any kind are made to the document (dialog), and the "Close" button is picked, a prompt will ask if you want to save before quitting.

- If changes are made to the document (dialog) and the "Save" button is selected and no more changes are made before the "Close" button is picked, the document (dialog) closes.

This uses the OnEvent> dialog_change event handler so the script requires Macro Scheduler version 10 (or newer). I will work on making this a generic included function unless someone else posts it before I get it done...

Any questions? be sure to read the comments.

Code: Select all

//Set up the dialog change event handling.

//the first parameter in the GoSub> is the name
//of the dialog to be controlled.

//The number at the end of this GoSub> represents
//the maximum number of any type of object that
//needs to be controlled.  In other words, if you have
//10 edit fields and 12 checkboxes,  set the number to 12.
//You could also remark out any lines that are handling
//objects you are not using.
GoSub>SetUpChangeEventHandler,dialog1,5

SRT>SetUpChangeEventHandler
//Initialize the flag variable by setting it to 0 (zero).
Let>DialogChangedFlag=0

Let>changeK=0

//Create a bunch of Dialog Change event handlers.  At least one
//for every object to be controlled.  Extras, for non existent objects
//does not seem to hurt anything.
Repeat>changeK
  Add>changeK,1
  OnEvent>DIALOG_CHANGE,%SetUpChangeEventHandler_var_1%,msedit%changeK%,SetDialogChangedFlag
  OnEvent>DIALOG_CHANGE,%SetUpChangeEventHandler_var_1%,msmemo%changeK%,SetDialogChangedFlag
  OnEvent>DIALOG_CHANGE,%SetUpChangeEventHandler_var_1%,mscheckbox%changeK%,SetDialogChangedFlag
  OnEvent>DIALOG_CHANGE,%SetUpChangeEventHandler_var_1%,mscombobox%changeK%,SetDialogChangedFlag
  OnEvent>DIALOG_CHANGE,%SetUpChangeEventHandler_var_1%,mslistbox%changeK%,SetDialogChangedFlag
Until>changeK=%SetUpChangeEventHandler_var_2%
END>SetUpChangeEventHandler

//The subroutine called by every event handler.
SRT>SetDialogChangedFlag
  //Add is just one method to make the variable not equal to zero.
  Add>DialogChangedFlag,1

  //A message that can be displayed for purposes of visual effect
  //only pertinent to this sample.
  IF>dialog1.mscheckbox1=True
    message>Dialog activity detected for the %DialogChangedFlag% time.
  EndIf
END>SetDialogChangedFlag

//the rest of this script is fairly straightforward.

Dialog>Dialog1
   Caption=Testing For Dialog Activity
   Width=440
   Height=250
   Top=CENTER
   Left=CENTER
   Label=Touch an object to turn on Save message at Cancel,16,8
   Edit=msEdit1,24,32,121,
   Memo=msMemo1,24,56,185,89,
   Button=Save,8,192,75,25,3
   Button=Close,352,192,75,25,2
   ListBox=msListBox1,224,56,121,97,Item1%CRLF%Item2
   ComboBox=msComboBox1,224,32,145,Item1%CRLF%Item2
   CheckBox=msCheckBox1,Check to see Event handler,24,152,197,False
EndDialog>Dialog1

Show>dialog1

Label>loop
  GetDialogAction>dialog1,res1
  If>res1=2,Check
  If>res1=3,Process
  Wait>0.01
Goto>loop

Label>EOF

SRT>Check
  If>DialogChangedFlag>0
    LibFunc>user32,MessageBoxA,res,0,Save changes before closing?,Close,35
    IF>res=2,SkipEOF
    IF>res=6,Process
    IF>res=7,EOF
  EndIf
  Goto>EOF
  Label>SkipEOF
  ResetDialogAction>dialog1
END>Check

SRT>Process
  LibFunc>user32,MessageBoxA,res,0,This represents a save,Saved,64
  Let>DialogChangedFlag=0
  ResetDialogAction>dialog1
END>Process
Last edited by JRL on Fri May 16, 2008 10:31 pm, edited 1 time in total.

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed May 14, 2008 11:51 pm

Hi JRL,

Very nice... Here's some more thoughts.

Lets say the user selects Item2 in the dropdown then immediately changes their mind and selects Item1 again. What is now in the dialog is exactly the same as what's in the file on disk... however on hitting Cancel, it will prompt the user to save changes anyway... and the user might think... save what? These are the same values I started with... I never did a save...???

Its a side effect of just flagging any change. It doesn't take into consideration a subsequent change may have reversed the first change.

Do the users need to be able to make a bunch of changes to the controls on the dialog and then Save them when they want to... minutes or hours later?

Or... are you more concerned with a user making a change and forgetting to save that change?

How important are the values that a user might have changed... but not yet have saved? What if they did a bunch of work by selecting new values and before they could manually save, the power goes off, Windows crashes, etc.?

A way to prevent data loss is to impliment an auto-save feature. You can already detect any change to a dialog control as soon as it happens. What if you immediately did a save on every change? Yes I know, ugly, lots of individual saves to disk... but you'd never worry about loosing a value... right? (Now that's quick and dirty). :shock:

To make it less ugly, you could impliment an inactivity timer. The idea being, if a user was just typing text into a field, each char they type would trigger the event (and a save) and you don't want to be saving on each and every character. However, if you could impliment a loop such that t waits for a period of inactivity, say 2 seconds goes by with no dialog changes, then it could check the change flag and if it indicates changes have happened, it could automatically do a save and reset the change flag.

At that point, the Save and Cancel buttons become almost unneccesary but you could leave them there for user comfort level... and no worries about data loss.

Some nice eye candy to go along with auto-save would be a visual indicator of unsaved changes... say a red *UNSAVED CHANGES* label appears on the dialog while there are unsaved changes... user is typing... 2 seconds of inactivity goes by... auto-save kicks in... changes are saved and the *UNSAVED CHANGES* indicator goes away.

Just some thoughts and ramblings...

Thanks again for posting your code JRL... much apprediated as always.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3532
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Fri May 16, 2008 10:38 pm

jpuziano wrote:Hi JRL,
Very nice...
Thank you.
jpuziano wrote:Lets say the user selects Item2 in the dropdown then immediately changes their mind and selects Item1 again. What is now in the dialog is exactly the same as what's in the file on disk... however on hitting Cancel, it will prompt the user to save changes anyway... and the user might think... save what? These are the same values I started with... I never did a save...???
JRL wrote:It functions in the way that I would expect a Microsoft program to function.
I altered the script above because the close message that asked if you want to save did not have a "Cancel" option as most Microsoft programs do. The message now includes a cancel option.

Post Reply
cron
Sign up to our newsletter for free automation tips, tricks & discounts