04140113.txt 14-Apr-00 ClassMate picture function in SLE Hi "ClassMates" Wondering why the cMaskedEdit Class did'nt like picture functions like "@D" I found the following: Note: This class does not support any of the function commands of the picture clause. OK - does anybody know the reason why and how can I use these functions - I am sure there is a way. Maybe subclassing ths cSLE Class?? Has anybody found a way to realize this, or do you not you need these functions ?? regards Uwe -- Uwe Hein (Voca Ruhrpott / Essen - Germany) Uwe, I too would like to add the functions to cMaskedEdit. The @R function in particular would be nice when trying to display dashes in zip codes or tax ids. I got around using the @D by using date edit controls both in cMaskedEdits and in the cDataBrowser. Paul Paul, > I too would like to add the functions to cMaskedEdit. The @R function in particular would be nice when trying to display dashes in zip codes or tax ids. This should be working as of 201. > I got around using the @D by using date edit controls both in cMaskedEdits and in the cDataBrowser. For dates I use "99/99/99" for the picture clause and assign NULL_DATE to the value assign. I've been doing this since 200 and as far as I can tell it works as expected. -- Larry Atkins, Hi Larry, Paul and all other cmHelpers... Paul wrote: > I got around using the @D by using date edit controls both in cMaskedEdits and in the cDataBrowser. Thanks for your answer concerning the @D picture function. I am a little ashamed as I overlooked the DateTimePicker control (still too much married with Clipper I guess). But there is a little problem using the DateTimePicker.. Is it possible to blank a DateTimePicker field to hide the displayed value completely ?? I understand the "disable feature" using the checkmark in the control, but I know my users.... E.g. we provide a birthday field for our customers - sometimes they forget to enter the birthday in the entry form - If we can leave the field empty, you can ask the customer for the birthday later- if there always is a date present, nobody will care for checked or unchecked fields, as they assume the date is filled in correctly. I am looking for sth. like an access called "checked" if you have checked the box for disabeling the date. Then you could set the TextColot to white (or the appropriate background color) and the entry would be invisible. But I fear its not that easy... Larry wrote: >For dates I use "99/99/99" for the picture clause and assign NULL_DATE to the value assign. I've been doing this since 200 and as far as I can tell it works as expected. This is great, as now you can be sure a correct date will be entered. A wrong date will leave the field emty and jump to the next control. BUT.............. To be nice to my users I wanted to display a warning message to inform the user about the typo. then back to the field and try again I nearly succeded - there's still a little problem left............ I did the following: // Subclassing the cMaskedEdit Class cmMaskedEdit inherit cMaskedEdit ~"ONLYEARLY+" protect handle as ptr ~"ONLYEARLY-" Method Init(oParent, uExtra) Class cmMaskedEdit super:Init(oParent, uExtra) ~"ONLYEARLY+" self:handle := self:hWnd return self ~"ONLYEARLY-"// Trying to catch the control after leaving Method OnFocusChange(oEvent as cFocusChangeEvent) ; as longint pascal class cmMaskedEdit local oDlg as cErrorBox ~"ONLYEARLY+" if !oEvent:GotFocus .and. self:Modified .and.; self:DataType == DATE // empty dates are allowed - so I have to check // if there is // sth. in the control - a wrong entry produces // :Value = NULL_DATE after processing the control if IsDigit(psz(_cast,left(self:TextValue, 1))) .and.; self:Value = NULL_DATE // displaying the dialog oDlg := cErrorBox{self,"Data Error!",; "You must enter a correct Date !!"} oDlg:Show() // putting the keyboard focus on the control SetFocus(self:hWnd) /* This works great - I can edit the desired control BUT the cursor is gone and I do not know how to get it back Of course I can press tab + shift_tab (or up and down - clipperkeys has no influence on this behaviour) but I want the method to do this for me I tried the following: PostMessage(self:Handle, WM_KEYDOWN, VK_UP , 1L) PostMessage(self:Handle, WM_KEYDOWN, VK_DOWN , 1L) woks fine, but the cursor is not in the desired field - it looks as if only the last statement is executed (in this case VK_DOWN) and the desired control is omitted for some reason Some more attempts: ShowCursor(true) -> no effect self:selection := cSelection { 0, -1 } -> no effect SendMessage(self:handle,EM_SETSEL,0,-1) -> no effect PostMessage(self:hWnd,WM_NEXTDLGCTL,0,0L) //prev-Control -> no effect PostMessage(self:hWnd,WM_NEXTDLGCTL,0,1L) // next-Control -> no effect It can't be that difficult to display that S$%& Cursor */ return super:OnFocusChange(oEvent) ~"ONLYEARLY-" Any suggestions for this - maybe I choose the wrong event method - I also tried OnControlFocusChange in the MdiChild window holding controls, but I did not come that far...... Uwe -- Uwe Hein (Voca Ruhrpott / Essen - Germany) -- uwe.hein@ob.kamp.net Hi Uwe, Along about 201, CM started supporting @R and other picture clauses that are used with the character mask. The cMaskedEdit accept/reject code requires a character mask so it can compare each key press with acceptable values for the character position. For dates, simply use a picture like: "99/99/9999". HTHs, Larry Atkins, Uwe, In article <38b65348.6671122@news.kamp.net>, uwe.hein@ob.kamp.net (Uwe Hein) writes: >Is it possible to blank a DateTimePicker field to hide the displayed value completely ?? I was mistaken, the Picture functions do work with Classmate. I guess the online help needs to be updated. I was having problems with them due to my asigning to the cMaskedEdit control's textvalue rather than its value. For Picture functions to work properly with Classmate, the same type must be first assigned to the control as one wants the Picture function to display. The DateTimePicker in Classmate, as well as in VO does not take a null value. I subclassed cMaskedEdit to get this to work in Classmate. It was suprisingly easy. The following is the code to do this with the exception of a simple triangle icon I created in the Image editor named 'DropDown' that looks like the arrow in a drop down box. In the Image editor, it has seven black squares from 13,15 to 19,15; five black squares from 14,16 to 18,16; three black squares from 15,17 to 17,17; and one square at 16,18. The remainder of the code for the control is: CLASS MyDateMaskEd INHERIT cMaskedEdit ~"ONLYEARLY+" HIDDEN oButton AS cSpeedButton DECLARE METHOD __SetButton ~"ONLYEARLY-" METHOD __SetButton(dwRID AS DWORD) AS VOID PASCAL ; CLASS MyDateMaskEdLOCAL iHeight AS LONGINT LOCAL oSize AS cDimension LOCAL oOrigin AS cPoint ~"ONLYEARLY+" iHeight := SELF:Size:Height oSize := cDimension{iHeight-5, iHeight-5} oOrigin := cPoint{SELF:Size:Width-iHeight,0} SELF:oButton:= cSpeedButton{SELF, dwRID, oOrigin,; oSize, , ,WS_EX_WINDOWEDGE, } SELF:oButton:Icon := DropDown{} SELF:oButton:InvokeMethod := #__DateBtn SELF:oButton:Show(SW_SHOWNORMAL) RETURN ~"ONLYEARLY-" METHOD Init(oOwner, xId, oOrigin, oSize, cClassName,; nStyle, nExtStyle, hWnd) CLASS MyDateMaskEd SUPER:Init(oOwner, xId, oOrigin, oSize, cClassName,; nStyle, nExtStyle, hWnd) ~"ONLYEARLY+" SELF:WindowStyle:=_or(SELF:WindowStyle,WS_CLIPCHILDREN) SELF:__SetButton(100) SELF:ReadOnly := TRUE RETURN SELF ~"ONLYEARLY-" METHOD __DateBtn() CLASS MyDateMaskEd LOCAL oDlg AS DatePicker ~"ONLYEARLY+" oDlg := DatePicker{SELF} IF oDlg:InitParams(SELF:DateValue) SELF:Value := oDlg:SelectedDate ENDIF RETURN NIL ~"ONLYEARLY-" METHOD OnFocusChange(oEvent AS cFocusChangeEvent) AS LONGINT PASCAL CLASS MyDateMaskEd ~"ONLYEARLY+" SUPER:OnFocusChange(oEvent) IF oEvent:GotFocus SELF:Selection := cSelection{0,0} ENDIF RETURN 0~"ONLYEARLY-" Uwe, Regarding the subclassed cMaskedEdit to provide a DatePicker that accepts null values, you will have to also create a dialog that holds a cMonthCalendar control. In the code this is called in the __DateBtn Method. For this subclass, I used a DatePicker dialog, along with its methods identical to the one Larry used in his Array Browser example. Sorry for the omission. Paul Paul, great - that was exactly what I was looking for - THANK YOU I hope you do not mind that I made some adjustments: **** Beginning of CODE ********* Class cmDateMaskEdit Inherit cMaskedEdit ~"ONLYEARLY+" Hidden oButton AS cSpeedButton Declare Method __SetButton ~"ONLYEARLY-" ******************************************* Method __SetButton(dwRID AS DWORD) AS VOID PASCAL CLASS cmDateMaskEdit local iHeight AS LONGINT local oSize AS cDimension local oOrigin AS cPoint ~"ONLYEARLY+" iHeight := SELF:Size:Height oSize := cDimension{iHeight - 5, iHeight - 5} oOrigin := cPoint{SELF:Size:Width - iHeight, 0} self:oButton := cSpeedButton{SELF, dwRID, oOrigin,; oSize,,, WS_EX_WINDOWEDGE, } self:oButton:Icon := DropDown{} self:oButton:InvokeMethod := #__DateBtn self:oButton:Show(SW_SHOWNORMAL) return ~"ONLYEARLY-" *********************************************** Method Init(oOwner, xId, oOrigin, oSize, cClassName, ; nStyle, nExtStyle, hWnd) Class cmDateMaskEdit super:Init(oOwner, xId, oOrigin, oSize, cClassName,; nStyle, nExtStyle, hWnd) ~"ONLYEARLY+" // provide Date Check by assigning NULL_DATE <------ // if a wrong date is entered the control remains empty self:value := NULL_DATE <------ self:WindowStyle := _or(SELF:WindowStyle,WS_CLIPCHILDREN) self:__SetButton(100) self:ReadOnly := True return self ~"ONLYEARLY-" ************************************************** Method __DateBtn() CLASS cmDateMaskEdit local oDlg AS DatePicker ~"ONLYEARLY+" oDlg := DatePicker{SELF} if oDlg:InitParams(self:DateValue) self:Value := oDlg:SelectedDate endif // I added a 3rd Button to the calendar control // returning 2 with // the endWindow() method to be able to // delete the date // so I can leave the control ReadOnly basically // NULL_DATE Button pressed <------------ if oDlg:result = 2 <------------ self:Value := NULL_DATE <------------ endif <------------ return NIL ~"ONLYEARLY-" ******************************************** METHOD OnFocusChange(oEvent AS cFocusChangeEvent) ; AS longint pascal CLASS cmDateMaskEdit ~"ONLYEARLY+" super:OnFocusChange(oEvent) if oEvent:GotFocus self:Selection := cSelection { 0, 0 } endif return 0 ~"ONLYEARLY-" ********************************************** // added a new method Method OnKeyChar(oEvent as cKeyEvent) as ; longint pascal class cmDateMaskEdit local nKey as longint ~"ONLYEARLY+" nKey := oEvent:ASCIIChar if nKey = asc("d") .or. nKey = asc("D") // pressing d or D pops up the calendar control ~"ONLYEARLY-" self:__DateBtn() // no early binding ~"ONLYEARLY+" self:SetFocus() // get focus back PostMessage(self:hWnd, WM_KEYDOWN, VK_TAB , 1L) // go to next control elseif nKey >= asc("0") .and. nKey <= asc("3") ; .and. self:CursorPosition = 1 // entering a number between 1 and 3 at the // first pos // enables to edit directly // NOTE !! this refers to: // SetDateFormat("DD.MM.YYYY") this has to be // adjusted with other Date formats self:ReadOnly := False // enable editing self:SetFocus() else self:ReadOnly := True endif return super:OnKeyChar(oEvent) ~"ONLYEARLY-" **************************************** // Method I added to the DatePicker // of course you have to create a button // for this Method EmptyBtn() class DatePicker ~"ONLYEARLY+" self:EndDialog(2) return ~"ONLYEARLY-" ******** End of Code ************************* A final Question: I try to make the mouse as obsolete as possible in my apps - so is there a way to navigate the datePicker control with the keyboard ?? - I did not find any regards Uwe Uwe Hein (Voca Ruhrpott / Essen - Germany) -- Wed, 01 Mar 2000 17:46 +0100 Uwe, Those are great changes. Thank you. In response to your question, no, I do not know how to navigate the datePicker control with the keyboard. I like your approach though, allowing as much keyboard input as possible. It must be due to my getting older , but more and more often, my fingers twitch and click on the mouse button when I don't want them to. Take care Uwe. Paul Hi Paul, I think this issue of keyboard accessibility is a very important one. For the average user its not (although my wife and her staff still complain my Clipper apps are better than their windows cousins ). But for data entry operators, they scream the roof down every time their hands have to leave the keyboard for the mouse. Also, I have an enquiry counter system being used in mechanics workshops. With the grease and grime on the desk, a mouse tends to last an average of one week. When I saw the foreman heave the entire computer over the bench in one throw (just because the mouse stopped working - again), I decided to ensure that all my apps had keyboard access for every menu item and every control . Geoff Hi to all wondering why this cmDateMaskEdit does not work as expected... Sorry I made 2 mistakes.. In the OnKeyChar() Method change Elseif nKey >= asc("0") .and. nKey <= asc("3") .and. self:CursorPosition = 1 to Elseif nKey >= asc("0") .and. nKey <= asc("3") .and. self:CursorPosition = 0 and kill the else branch else self:ReadOnly := True endif Otherwise you will not be able to edit the control - I thought 1 was the first cursor pos - NO it is 0 !!# Second - after the first number - no matter what cursor pos, the control will not be editable any more because of else self:ReadOnly := True One of my favorite mistakes I make round 4 in the morning, wondering if there is something wrong with my OS ?? Uwe