April 25, 2024, 03:38:05 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Edit control - mask input of characters

Started by Andy, August 27, 2017, 12:25:44 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

I was just wondering, is there a way to restrict what characters a user can input in an edit control.

By that I mean I only what the characters 0 to 9 and A to F - the edit control will be used for hex values only.

Thanks,
Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

jalih

August 27, 2017, 07:25:28 AM #1 Last Edit: August 27, 2017, 01:54:40 PM by jalih
Quote from: Andy on August 27, 2017, 12:25:44 AM
I was just wondering, is there a way to restrict what characters a user can input in an edit control.

By that I mean I only what the characters 0 to 9 and A to F - the edit control will be used for hex values only.

Thanks,
Andy.

Just subclass the edit control and use lookup table for masking the input:


$INCLUDE "windowssdk.inc"


WINDOW win

ENUM win_const
win_EDIT1 = 100
ENDENUM

OpenWindow win,0,0,416,339,@SIZE|@MINBOX|@MAXBOX|@CAPTION|@SYSMENU,0,"Form2",&win_handler
CONTROL win,@EDIT,"",79,74,186,25,@CTEDITAUTOH|@CTEDITLEFT,win_EDIT1

MaskEditControl(win, win_EDIT1, "0123456789ABCDEFabcdef\x8")

WAITUNTIL ISWINDOWCLOSED(win)
END


sub win_handler(), int
  select @MESSAGE
    case @IDCREATE
      centerwindow win
    case @IDCONTROL
      select @CONTROLID
        case win_EDIT1
      endselect
    case @IDCLOSEWINDOW
      closewindow win
  endselect
  return 0
endsub


sub maskedEditHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
  pointer mask
  select uMsg
    case WM_NCDESTROY
      RemovePropA(hWnd,"edit_handler")
      mask = GetPropA(hWnd,"mask_addr")
      delete mask
      RemovePropA(hWnd,"mask_addr")
    case @IDCHAR
      mask = GetPropA(hWnd,"mask_addr")
      if #<int>mask[wParam & 0xff] = FALSE
        return 0
      endif
  endselect
  return CallWindowProcA(GetPropA(hWnd,"edit_handler"),hWnd,uMsg,wParam,lParam)
endsub


sub MaskEditControl(WINDOW parent, INT id, string szMask)
  HWND hEdit = GETCONTROLHANDLE(parent,id)
  LONG lpFn = SetWindowLongA(hEdit,GWL_WNDPROC,&maskedEditHandler)
  SetPropA(hEdit,"edit_handler",lpFn)
  pointer mask = new(int, 256)
  int i

  for i = 0 to 255
    #<int>mask[i] = FALSE
  next i

  for i = 0 to len(szMask)
    #<int>mask[szMask[i]] = TRUE
  next i

  SetPropA(hEdit,"mask_addr", mask)

  return
endsub


sub UnMaskEditControl(WINDOW parent,INT id)
   HWND hEdit = GETCONTROLHANDLE(parent,id)
   LONG lpFn = SetWindowLongA(hEdit,GWL_WNDPROC, GetPropA(hEdit,"edit_handler"))
   RemovePropA(hEdit,"edit_handler")
   pointer mask = GetPropA(hEdit,"mask_addr")
   delete mask
   RemovePropA(hEdit,"mask_addr")
   return
endsub


Andy

Jalih to the rescue again - thanks!

Sub classing is something I'm not too hot on, I must try to find a little time to study the process.

I've amended it slightly to receive only uppercase characters, and restrict the input box to 8 characters.

$include "windowssdk.inc"

WINDOW win

CONST EDIT1=100
CONST ES_UPPERCASE = 0x8 'Uppercase letters only.

OpenWindow win,0,0,416,339,@SIZE|@MINBOX|@MAXBOX|@CAPTION|@SYSMENU,0,"Form2",&win_handler
CONTROL win,@EDIT,"",79,74,186,25,@CTEDITAUTOH|@CTEDITLEFT|ES_UPPERCASE,EDIT1
SETFOCUS win,EDIT1

MaskEditControl(win,EDIT1,"0123456789ABCDEFabcdef\x8")
CONTROLCMD win,EDIT1,@EDSETLIMITTEXT,8 'Set maximum number of characters.

WAITUNTIL ISWINDOWCLOSED(win)
END

sub win_handler(),int
    select @MESSAGE
      case @IDCREATE
           centerwindow win
      case @IDCONTROL
           select @CONTROLID
              case EDIT1
           endselect
      case @IDCLOSEWINDOW
           closewindow win
      case WM_DESTROY
           UnMaskEditControl(win,EDIT1)
    endselect
    return 0
endsub

sub maskedEditHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
    select uMsg
      case @IDCHAR
        pointer mask=GetPropA(hWND,"mask_addr")
        if #<int>mask[wParam & 0xff]=FALSE
           return 0
        endif
    endselect
    return CallWindowProcA(GetPropA(hWnd,"edit_handler"),hWnd,uMsg,wParam,lParam)
endsub

sub MaskEditControl(WINDOW parent,INT id,string szMask)
    HWND hEdit=GETCONTROLHANDLE(parent,id)
    LONG lpFn=SetWindowLongA(hEdit,GWL_WNDPROC,&maskedEditHandler)
    SetPropA(hEdit,"edit_handler",lpFn)
    pointer mask=new(int,256)
    int i
    for i=0 to 255
  #<int>mask[i]=FALSE
    next i
    for i=0 to len(szMask)
  #<int>mask[szMask[i]]=TRUE
    next i
    SetPropA(hEdit,"mask_addr",mask)
    return
ENDSUB

SUB UnMaskEditControl(WINDOW parent,INT id)
    HWND hEdit=GETCONTROLHANDLE(parent,id)
    LONG lpFn=SetWindowLongA(hEdit,GWL_WNDPROC,GetPropA(hEdit,"edit_handler"))
    RemovePropA(hEdit,"edit_handler")
    pointer mask=GetPropA(hEdit,"mask_addr")
    delete mask
    return
ENDSUB


Thanks again!!
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

Just working my way through the mask input code and I have a few questions on it:

What is the purpose of \x8 in the line

MaskEditControl(win,EDIT1,"0123456789ABCDEFabcdef\x8")

In the line:

pointer mask=GetPropA(hWND,"mask_addr") I presume "mask_addr" could be any old name?

And finally, what is the purpose of & 0XFF

        if #<int>mask[wParam & 0xff]=FALSE
           return 0
        endif

Thanks.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Brian

Andy,

The \x8 is the Back Delete key. Wondered about the 0xFF myself,
only that it is OR'd with the wparam result

Brian

ckoehn

The "& 0xFF" is "AND"ed with the wParam. It returns the last 8 bits (or byte) of the wParam.

Later Clint

Andy

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Brian

Whoops! Got my ANDs and ORs mixed up. The mask_addr can be anything as long as it is unique
Brian

jalih

August 29, 2017, 10:15:49 AM #8 Last Edit: August 29, 2017, 10:59:07 AM by jalih
Quote from: Andy on August 29, 2017, 12:07:45 AM

In the line:

pointer mask=GetPropA(hWND,"mask_addr") I presume "mask_addr" could be any old name?

And finally, what is the purpose of & 0XFF

        if #<int>mask[wParam & 0xff]=FALSE
           return 0
        endif

"& 0xFF" just makes sure we keep within boundaries of our lookup table.

You should probably get rid of from using properties and just reserve space for lookuptable+WNDPROC and store the address in window long:


$INCLUDE "windowssdk.inc"


WINDOW win

ENUM win_const
win_EDIT1 = 100
ENDENUM

OpenWindow win,0,0,416,339,@SIZE|@MINBOX|@MAXBOX|@CAPTION|@SYSMENU,0,"Form2",&win_handler
CONTROL win,@EDIT,"",79,74,186,25,@CTEDITAUTOH|@CTEDITLEFT,win_EDIT1

MaskEditControl(win, win_EDIT1, "0123456789ABCDEFabcdef\x8")

WAITUNTIL ISWINDOWCLOSED(win)
END


sub win_handler(), int
  select @MESSAGE
    case @IDCREATE
      centerwindow win
    case @IDCONTROL
      select @CONTROLID
        case win_EDIT1
      endselect
    case @IDCLOSEWINDOW
      closewindow win
  endselect
  return 0
endsub


sub MaskedEditHandler(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam),LRESULT
  pointer mask = GetWindowLong(hwnd, GWL_USERDATA)
  SELECT uMsg
    case WM_NCDESTROY
      delete mask
    CASE @IDCHAR
      if #<int>mask[wParam & 0xff] = FALSE
        return 0
      endif
    ENDSELECT
  RETURN CallWindowProcA(#<int>mask[256],hWnd,uMsg,wParam,lParam)
ENDSUB


SUB MaskEditControl(WINDOW parent, INT id, string szMask)
   HWND hEdit = GETCONTROLHANDLE(parent,id)
   LONG lpFn = GetWindowLong(hEdit, GWL_WNDPROC)
   pointer mask
   int i

   if lpFn <> &MaskedEditHandler
     mask = new(int, 257)
   else
     mask = GetWindowLong(hEdit, GWL_USERDATA)
   endif

   for i = 0 to 255
     #<int>mask[i] = FALSE
   next i

   for i = 0 to len(szMask)
     #<int>mask[szMask[i]] = TRUE
   next i

   if lpFn <> &MaskedEditHandler
     #<int>mask[256] = SetWindowLongA(hEdit,GWL_WNDPROC,&MaskedEditHandler)
     SetWindowLong(hEdit, GWL_USERDATA, mask)
   endif

ENDSUB