For some reason the default button on standard warning when called for delete defaults to Yes. My users complain that they sometimes accidently delete records because of this
I figured the code in ABError.clw : ErrorClass.TakeUser PROCEDURE is responsible for this. When I changed the default button as follows
ErrorClass.TakeUser PROCEDURE
CODE
IF SELF.Msg(SELF.SubsString(),SELF.GetErrorBufferTitle(),ICON:Question, |
Button:Yes+Button:No,BUTTON:No,SELF.MsgStyle) = Button:Yes
RETURN Level:Benign
ELSE
RETURN Level:Cancel
END
However I was wandering if there is any solution that does not require changes in Libsrc folder as when my app will be compiled on another copy of Clarion or I will simply upgrade to newer build my changes will be overwritten and it will default back to Yes button. I can also copy modified ABError.clw to my app directory, but there may be a problem if there are any changes in that file in new build and my app will still use old version. My concern is that I will simply forget about this change after a while.
How do you make sure records are not accidently deleted? Is there a way of overriding this method inside my app ?
I dislike a Message() with Yes/No buttons that require reading the body to understand the question. I.e. does YES Delete? I like the button labels to make it obvious.
If you want to improve things maybe separate Delete Message code with Buttons of Delete / Keep:
ErrorClass.TakeError PROCEDURE(SHORT Id)
CODE
SELF.StoreErrorEntry(Id)
CASE Id !Carl: Special handling for certain Error IDs
OF Msg:ConfirmDelete
RETURN SELF.Take:Msg:ConfirmDelete()
END
CASE SELF.GetErrorBufferFatality()
OF Level:Benign
....
ErrorClass.Take:Msg:ConfirmDelete PROCEDURE() !New Method for Delete
CODE
! IF SELF.Msg(SELF.SubsString(),SELF.GetErrorBufferTitle(),ICON:Question, |
IF SELF.Msg('Are you sure you want to delete the highlighted record?', |
'Confirm Delete',ICON:Question, |
'Delete Record|Keep Record',2,SELF.MsgStyle) = 1 THEN
RETURN Level:Benign
ELSE
RETURN Level:Cancel
END
!FYI
! USHORT(Msg:ConfirmDelete)
! BYTE(Level:User)
! PSTRING('Confirm Delete')
! PSTRING('Are you sure you want to delete the highlighted record?')
That would be perfect, I agree Yes/No buttons may be confusing, so I would rather have meaningful buttons as you suggest.
The problem is that I never derived a class in Clarion . I can see there is a derive checkbox but never done it myself, especially with built in classes. Do you have any examples how to do it?
I found some Clarion Live video by Bruce but cannot open it.
Or what I learned from an example of Steve Parker, via the UpdateForm:
ThisWindow.PrimeUpdate PROCEDURE
ReturnValue BYTE,AUTO
! Start of "WindowManager Method Data Section"
! [Priority 5000]
! End of "WindowManager Method Data Section"
CODE
! Start of "WindowManager Method Executable Code Section"
! [Priority 4500]
If ThisWindow.Request = DeleteRecord
Message(' you are going to delete the following Dossier: '& |
'| ' & |
'| ' & CLIP(DOSS:DossierName) & |
'| [ Click Ok ] and make a choice','Remove dossier',ICON:Exclamation)
End
And at:
! Parent Call
ReturnValue = PARENT.PrimeUpdate()
! [Priority 5001]
If ThisWindow.Request = DeleteRecord and ThisWindow.Response = RequestCompleted
Message('Dossier'&' '&clip(DOSS:DossierNaam)&' '&'is deleted','delete')
End
MEMBER
INCLUDE('MyErrorClass.INC'),ONCE
MAP
END
MyErrorClass.TakeUser PROCEDURE
CODE
If Self.GetErrorBufferId() = Msg:ConfirmDelete
IF MESSAGE(Self.SubsString(),SELF.GetErrorBufferTitle(),ICON:Question, |
Button:Yes+Button:No,BUTTON:No,0) = Button:Yes
RETURN Level:Benign
ELSE
RETURN Level:Cancel
END
Else
Return Parent.TakeUser()
End
Then in Global Properties->Actions->Classes, Refresh Application Builder Class Information, then press the General Button, on the Error Manager Dropdown, locate MyErrorClass and select it.
Then recompile, and your derived class will now be the one used in your application
NOTE You will need to change this in all applications of a multi dll solution.
FWIW, that OMIT() stuff kind of pre-dates the ONCE syntax and isn’t really necessary (if you use ONCE, that is :-), which usually is the case nowadays )
Thanks, Mark. Nice example.
Additionally, if you start going down this road of deriving your own classes from the base ABC classes, you can write a global template that will change your Apps to use your classes.
Combing Mark’s override of .TakeUser() with my desire for named buttons I would suggest below that any ID can have custom buttons for Yes/No so choices are better understood.
MyErrorClass.TakeUser PROCEDURE() !,DERIVED
Button1 PSTRING(32) !Text for YES
Button2 PSTRING(32) !Text for NO
DefaultBtn BYTE(1) !Default to YES like the original
CODE
CASE Self.GetErrorBufferId()
OF Msg:ConfirmDelete !Confirm Delete - Are you sure you want to delete the highlighted record?
OROF Msg:RetryDelete !Record Delete Error - An error was experienced deleting this record. Do you want to try to delete it again?
Button1='Delete Record'
Button2='Keep Record'
DefaultBtn=2
OF Msg:SaveRecord !Save Record - Do you want to save the changes to this record?
Button1='Save Record'
Button2='Discard'
DefaultBtn=1
OF Msg:RetrySave !Record Update Error - An error was experienced changing this record. Do you want to try to save again?
Button1='Retry Save'
Button2='Discard'
DefaultBtn=1
OF Msg:AddAnother !Record Added - This record has been added to the file. Do you want to add another record?
Button1='Add Again'
Button2='Close Form'
DefaultBtn=2
ELSE
Return Parent.TakeUser() !Call Base Class Yes/No Message
END
IF ~Button1 THEN Button1='&Yes'. !Did above code fail to set values
IF ~Button2 THEN Button2='&No'.
IF MESSAGE(Self.SubsString(),SELF.GetErrorBufferTitle(),ICON:Question, |
Button1 &'|'& Button2, DefaultBtn, SELF.MsgStyle) = 1 THEN
RETURN Level:Benign
ELSE
RETURN Level:Cancel
END
Note that your original change for all Defaults to be NO would have a negative affect on some like “Save Record” would default to NO where YES is the better default.
It complains about SELF.MsgStyle
Invalid use of PRIVATE data - C:\Clarion11.1\libsrc\win\MYERRORCLASS.CLW:46,46
Removing OMIT lines does not make difference,
but when I removed this message parameter works like charm
It does help. Thanks a lot. I have been previously adding methods to eg. WindowManager in the IDE and called ThisWindow.MyNewMethod, but never actually done it this way overriding a method. Nice and useful.