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 <g>

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 <g>, 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 <sigh>). 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 <g>.

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 ?? <BG>

Uwe