xMask - A Masked Edit Gadget
Posted: Wed Apr 27, 2005 1:35 am
I needed a masked edit control for my main project and didn't really like what was out there so I made my own 
Here are some caveats:
1. It's Windows only. Sorry Linux fellas
It uses win api calls to work.
2. It's a beta. I haven't really checked it completely for bugs yet. Probably a lot of obvious mistakes as well
3. It's pretty basic. IE, it doesn't have any commands to colorize it or such.
4. Ummm... ugly code and unoptimized code. I apologize for my newbie-ness
Having said all that, it works great for me and it's really simple to use. No need to set any callbacks or remember any variables. The xMask gadget is created like...
This would create an xMask gadget that handles social security numbers. The creation procedure handles everything like maximum length and whatnot so you could easily create another xMask gadget like...
And you'll get a simple xMask that only allows 4 numbers in the field. So now you don't have to wonder how to prevent people from putting alpha characters in or anything weird like that. And if you change your mind and want to change the mask you could call...
Not that this will actually display "-______" in the xMask gadget because "HIIIIII" fails our mask. When that happens, the procedure will show the mask with the placeholder instead of the text. Also note the really super excellent cool ability to reference the xMask functions with the constant (or variable if you choose) used to create the xMask control. Just like a normal PB gagdet 
At the bottom of the message I'll attach two files - one is the main xMask include and the other is a small test program to show it off.
What makes this different than other masked edit solutions? Well, it works really nice to me. No quirky behavior like some of them. You can reference the gadget like a ... well... a gadget. There's a xmGetGadgetText(), an xmSetGadgetText(), etc... not very many commands but I can always add more later. Or hell, you could. Source code is included and I did my best to comment it well.
Another caveat here - some of the comments might be out of place. I did some cutting, copying and pasting towards the end and didn't fix up comments.
Anyway, if you need more you can always modify it to what you want. It's ripe for adding additional formatting codes or other behavior.
The main procedures are...
1. xmCreate() used to create the xMask gadget
2. xmDestroy() to destroy (remove) a single xMask gadget.
3. xmDestroyAll() to destroy all created xMask gadgets in your project.
4. xmSetGadgetText() to set text to the xMask gadget. Only use text, do not use a mask in this one. So if your mask is "(000)" only pass "911" and you'll get "(911)" in the display.
5. xmForceGadgetText() - Use this to force a certain text into the xMask gadget. Use at your own risk. If your mask is "(000)" and you use this function to fill with "AAA" you will get "AAA" in the text box. No paranthesis or anything. Your mask will still be there so the next time you try to type something in it, it'll start looking a little odd as it corrects itself.
6. xmGetGadgetText() to return the text, mask and all. Whatever is shown.
7. xmSelectAllOnFocus() is a per-xMask setting you can change that affects what happens when your xMask gadget receives focus from tabbing. If True, it will select everything in the xMask gadget.
8. xmActive() will simple set focus to your xMask gadget.
9. xmResizeGadget() will resize your xMask gadget. It behaves like ResizeGadget(). IE, you can pass -1 for some fields to leave them unchanged.
10. xmGadgetHandle() will return the handle to the gadget. You can use that for your own devious purposes. I imagine mainly for win api calls.
One important note - you cannot call internal PB functions with the value used to declare the xMask gadget
Another neat little thing is (and this would also be neat as a reference to other programming) - I intercept the copy/cut/delete commands and handle them differently. So if you select text in your xMask gadget... say... "(215) 691-8985" <and you select "691-8", right click in the xMask gadget and select "Cut", it will not go all weird and show "(215) 985". It will actually catch it and show "(215) ___-_985" even though "691-8" will be on the clipboard. I also double-check what's being pasted to make sure it doesn't break rules. I'm a little proud of those suckers.
The current formatting rules are (borrowed from MS
)
0 - Digit (0 - 9)
9 - Digit or Space
L - Letter (A to Z, a to z)
? - Letter or Space
A - Letter or Digit
a - Letter or Digit or Space
& - Any Character (displayable)
C - Any Character or Space
> - This will cause the next character to be capitalized
< - This will cause the next character to be decapitalized
\ - This will cause the next character to be displayed as a display character.
So if you have ">A" and you type "d" it will show "D" in your xMask gadget. If you have "<A" and you type "G", it will show "g". If you have "\090" and type "AAA A ((789722323" what will you have? Anyone? ('_' ) Anyone? ( '_') Hah! No! You will get: "0 7". Why? Because the "\0" forces it to display a "0". It's a display character and you can't overtype it. The '9' in your mask matches the " " (space) after the third "A" so it will allow the space. Finally it'll match the first '7' to the '0' mask character.
I really welcome any comments. Also, please pass along any ideas for enhancements or bug fixing. I keep thinking I forgot something.... Ah well!
Oh! I remember what else. Perhaps you're wondering... how the heck can you make it soooo nice and let us still reference the xMask commands with the variable (or constant) used to create the gadget? Well...
I keep track of all xMask gadgets created and destroyed with a PB linked list. That allows me to do some nice stuff. Check it out 
Download the test program here: Test Program
And the xMask library thingie here: xMask Library Thingie
The test program references xMask.pb so you'll need both in the same directory to run the test program.
Good luck and let me know how it goes.
UPDATE! Hah! Already an update!
The file names are the same so download them again just in case. I added a simple event procedure - a Change event. The test program shows how it works. Pretty simple to set up. What it does is allow you to make a custom procedure and then when you make a change to an xMask gadget, the code will call that procedure with the new text and your procedure will handle the rest. Pretty nifty. It'd be very very easy to add an event procedure for other things. For instance, one could be added if a user types an incorrect value for your mask. Hell, it'd be so easy, I think I'll do it real quick to prove it...
UPDATE 2!
Updated with a basic 'Bad Key' Event. Right now it's really basic. If you type a bad key it will send a notification to any procedure you've set as a bad key event procedure. It will also do the same if you try to paste a bad string into the xMask gadget. Basically this is raised if the keys fail the mask for the xMask gadget. I could probably set up different constants like #XM_BADKEYTYPED and #XM_BADKEYPASTE to differentiate between the different types of bad key event notifications but this one just uses '0' for typed or '1' for paste. For now. Again, the test program shows an example of how it works. Yay! 
UPDATE 3 Updated again. ^_^ Fixed a bug when copying text from the xMask gadget. Added two more events. An event for when the return key is pressed and an event for when the gadget loses focus. Examples are in the test program. Download from the same place.

Here are some caveats:
1. It's Windows only. Sorry Linux fellas

2. It's a beta. I haven't really checked it completely for bugs yet. Probably a lot of obvious mistakes as well

3. It's pretty basic. IE, it doesn't have any commands to colorize it or such.
4. Ummm... ugly code and unoptimized code. I apologize for my newbie-ness

Having said all that, it works great for me and it's really simple to use. No need to set any callbacks or remember any variables. The xMask gadget is created like...
Code: Select all
xmCreate(#maskMain, WindowID(), 5, 5, 120, 18, "000-00-0000", "371983719", Asc("_"))
Code: Select all
xmCreate(#maskMain, WindowID(), 5, 5, 120, 18, "0000", "", Asc("_"))
Code: Select all
xmSetMask(#maskMain, "-LL00LL", "HIIIIIII", Asc("_"))

At the bottom of the message I'll attach two files - one is the main xMask include and the other is a small test program to show it off.
What makes this different than other masked edit solutions? Well, it works really nice to me. No quirky behavior like some of them. You can reference the gadget like a ... well... a gadget. There's a xmGetGadgetText(), an xmSetGadgetText(), etc... not very many commands but I can always add more later. Or hell, you could. Source code is included and I did my best to comment it well.
Another caveat here - some of the comments might be out of place. I did some cutting, copying and pasting towards the end and didn't fix up comments.
Anyway, if you need more you can always modify it to what you want. It's ripe for adding additional formatting codes or other behavior.
The main procedures are...
1. xmCreate() used to create the xMask gadget
2. xmDestroy() to destroy (remove) a single xMask gadget.
3. xmDestroyAll() to destroy all created xMask gadgets in your project.
4. xmSetGadgetText() to set text to the xMask gadget. Only use text, do not use a mask in this one. So if your mask is "(000)" only pass "911" and you'll get "(911)" in the display.
5. xmForceGadgetText() - Use this to force a certain text into the xMask gadget. Use at your own risk. If your mask is "(000)" and you use this function to fill with "AAA" you will get "AAA" in the text box. No paranthesis or anything. Your mask will still be there so the next time you try to type something in it, it'll start looking a little odd as it corrects itself.
6. xmGetGadgetText() to return the text, mask and all. Whatever is shown.
7. xmSelectAllOnFocus() is a per-xMask setting you can change that affects what happens when your xMask gadget receives focus from tabbing. If True, it will select everything in the xMask gadget.
8. xmActive() will simple set focus to your xMask gadget.
9. xmResizeGadget() will resize your xMask gadget. It behaves like ResizeGadget(). IE, you can pass -1 for some fields to leave them unchanged.
10. xmGadgetHandle() will return the handle to the gadget. You can use that for your own devious purposes. I imagine mainly for win api calls.
One important note - you cannot call internal PB functions with the value used to declare the xMask gadget
Another neat little thing is (and this would also be neat as a reference to other programming) - I intercept the copy/cut/delete commands and handle them differently. So if you select text in your xMask gadget... say... "(215) 691-8985" <and you select "691-8", right click in the xMask gadget and select "Cut", it will not go all weird and show "(215) 985". It will actually catch it and show "(215) ___-_985" even though "691-8" will be on the clipboard. I also double-check what's being pasted to make sure it doesn't break rules. I'm a little proud of those suckers.
The current formatting rules are (borrowed from MS

0 - Digit (0 - 9)
9 - Digit or Space
L - Letter (A to Z, a to z)
? - Letter or Space
A - Letter or Digit
a - Letter or Digit or Space
& - Any Character (displayable)
C - Any Character or Space
> - This will cause the next character to be capitalized
< - This will cause the next character to be decapitalized
\ - This will cause the next character to be displayed as a display character.
So if you have ">A" and you type "d" it will show "D" in your xMask gadget. If you have "<A" and you type "G", it will show "g". If you have "\090" and type "AAA A ((789722323" what will you have? Anyone? ('_' ) Anyone? ( '_') Hah! No! You will get: "0 7". Why? Because the "\0" forces it to display a "0". It's a display character and you can't overtype it. The '9' in your mask matches the " " (space) after the third "A" so it will allow the space. Finally it'll match the first '7' to the '0' mask character.
I really welcome any comments. Also, please pass along any ideas for enhancements or bug fixing. I keep thinking I forgot something.... Ah well!

Oh! I remember what else. Perhaps you're wondering... how the heck can you make it soooo nice and let us still reference the xMask commands with the variable (or constant) used to create the gadget? Well...


Download the test program here: Test Program
And the xMask library thingie here: xMask Library Thingie
The test program references xMask.pb so you'll need both in the same directory to run the test program.
Good luck and let me know how it goes.
UPDATE! Hah! Already an update!

UPDATE 2!


UPDATE 3 Updated again. ^_^ Fixed a bug when copying text from the xMask gadget. Added two more events. An event for when the return key is pressed and an event for when the gadget loses focus. Examples are in the test program. Download from the same place.