xMask - A Masked Edit Gadget

Developed or developing a new product in PureBasic? Tell the world about it.
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

xMask - A Masked Edit Gadget

Post by Xombie »

I needed a masked edit control for my main project and didn't really like what was out there so I made my own :D

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 :D

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("_"))
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...

Code: Select all

xmCreate(#maskMain, WindowID(), 5, 5, 120, 18, "0000", "", Asc("_"))
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...

Code: Select all

xmSetMask(#maskMain, "-LL00LL", "HIIIIIII", Asc("_"))
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 :D

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 :D )
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! :D

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... :D 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 8)

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! :D 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! :D 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! :D

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.
Tommeh
Enthusiast
Enthusiast
Posts: 149
Joined: Sun Aug 29, 2004 2:25 pm
Location: United Kingdom

Post by Tommeh »

Woah, let me just say, it looks like you have put a lot of thought and time into this and it looks like some very nice work, well done :-)

Can't wait to try it later 8)
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Post by jack »

thanks Xombie, I agree with what Tommeh said. :)
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Re: xMask - A Masked Edit Gadget

Post by TerryHough »

Xombie wrote: The current formatting rules are (borrowed from MS :D )
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.

I really welcome any comments. Also, please pass along any ideas for enhancements or bug fixing. I keep thinking I forgot something.... :D
:D Hi Xombie

I like what you have done. However, you and Microsoft forgot that real numbers sometimes must be entered, eg. 123.45, and a fixed or variable decimal place is sometimes required, as are negative numbers.

The mask characters you have chosen do not allow the entry of a decimal , comma, or hyphen in otherwise numeric fields. It would be pretty easy to allow those characters, but providing for decimal alignment with the mask is a bit more difficult.

I do love that you have solved the cut and paste problem I had.

Keep up the good work!

Terry
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

Nice Job

but it's possible to convert to Purebasic Library ?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Excellent job there, very interesting.

One problem is that I cannot seem to compile the code with JaPBe! It comes up with 'Cannot load Main.pb' !

Compiling with the normal IDE is no problem.

Is this a problem with JaPBe or am I being monumentally thick? :roll:

Thanks.
I may look like a mule, but I'm not a complete ass.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

delete this lines:

Code: Select all

; jaPBe Version=2.5.4.22
; FoldLines=000000060008002E002F0037003C018F019001E401E503A603A703B103B203BC
; FoldLines=03BE0557055905620563057405880590059105A705A805C305C405E405E505F9
; FoldLines=05FA060806090615061606220623062F063206480649065B065C0699
; Build=0
; CompileThis=Main.pb
; FirstLine=0
; CursorPosition=1397
; ExecutableFormat=Windows
; DontSaveDeclare
; EOF
with UltraEdit or other editor
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Aye, thanks ts-soft, that did the trick.

What's all that about then? I've only just begun to use JaPBe so am not familiar as yet with all its ins and outs!

Thanks again.
I may look like a mule, but I'm not a complete ass.
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

srod, those lines are used by japbe to store little bits of info for the .pb file. Like which lines are folded or not, etc... Japbe won't show the lines in the editor but if you open the same file in a text editor you will see them.

So is the xMask gadget working out for people? I will probably have another update this evening for some bug fixes and a few more things.

To be honest, I only needed this for an extremely specific purpose. Just 1 type of mask. However, other people seemed to want a masked edit so I figured I might as well try making one. The problem is, I don't know the proper way a masked edit control should react to certain situations. I'd need other people to set me straight. So if you see it reacting differently than you expect, let me know.

Also, Mr. Hough, I may have an example for you in the next revision. A financial type mask. Might see if it's good and then I can try adapting to plain floats.
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Re: xMask - A Masked Edit Gadget

Post by Xombie »

TerryHough wrote: :D Hi Xombie

I like what you have done. However, you and Microsoft forgot that real numbers sometimes must be entered, eg. 123.45, and a fixed or variable decimal place is sometimes required, as are negative numbers.

The mask characters you have chosen do not allow the entry of a decimal , comma, or hyphen in otherwise numeric fields. It would be pretty easy to allow those characters, but providing for decimal alignment with the mask is a bit more difficult.

I do love that you have solved the cut and paste problem I had.

Keep up the good work!

Terry
Whelp, I made an experimental new mask to try this out. Since I work a little with numbers, I made a financial mask. This allows you to put in any number (negative or not) and decimal places. It will display the number in a kind of money format. So, depending on what options you choose, you can create this new type of mask like...

Code: Select all

xmCreate(#maskSimple, WindowID(), 5, 55, 120, 18, "#Financial", "1000.5498", Asc("_"))
Note the "#Financial" mask. It's case sensitive and must be entered in as is. When the form loads the "1000.5498" will be displayed as "$1,000.54". It also reacts differently than a normal mask. Give it a shot and see if it's close to what you were thinking originally. I think it's similar to what you want except this uses the idea in a finance format. Easy enough to change to a pure number, though.

The options for this new mask can be set with...

Code: Select all

Procedure xmSetFinancialMaskOptions(inGadgetID.l, ShowThousandsSeparator.b, ForceDecimals.b, NumberDecimals.b, RoundDecimals.b, ShowNegativeAsParan.b)
...this procedure. ShowThousandsSeparator controls whether we show "," in the display. ForceDecimals controls whether we force a decimal place to show in our display. NumberDecimals controls how many decimal points we allow. RoundDecimals controls whether we round or truncate when a user enters too many decimals. ShowNegativeAsParan controls whether we display a negative number using parantheses (ie, '-100.31' as '(100.31)' ).

Hopefully I didn't break anything adding this stuff in ^_^ Again, not the most optimized way to do it but what the hey, right? :D

Download at the same place in my first post.
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Re: xMask - A Masked Edit Gadget

Post by TerryHough »

Xombie wrote:the "#Financial" mask.
When the form loads the "1000.5498" will be displayed as "$1,000.54".

Give it a shot and see if it's close to what you were thinking originally. I think it's similar to what you want except this uses the idea in a finance format. Easy enough to change to a pure number, though.
Good progress! Not quite there for me yet though.

First, it would be "beter" practice (IMHO) to set the features of the mask for a gadget at creation time. As you have it, all #Financial masked gadgets utilized would be the same. That is not always the way you would need to use them.

For example: Many times, even in financial applications, it is necessary to enter, display, and calculate with numbers that are not just 2 decimal places. One example would be stock prices. Often it is ncessary to display a ratio or percentage out to several decimal places while otherwise showing the normal "financial" numbers in dollars and cents.

As a matter of style, it is not normal to show all dollars and cents entries on a report with a leading $. Traditionally the $ is only shown on the first entry in a column and on subtotal and total lines (accounting format). Sometimes that is shown with a sliding $ and somestimes a fixed place $ ($ 100.50 vs. $100.50), so some flexibility must be allowed.

Second, after searching for the way to turn on rounding and setting it, I don't think your rounding is working properly. In fact, with rounding to 2 decimal places turned on, your example fails. $1000.5498 rounded to 2 decimal places should be $1000.55, right?

Your concept is heading in the right direction though. Keep up the good work.

Terry
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

Hmmm... actually, all of that was just a test. I have no intentions of continuing development on the financial part of it. I just wanted to see if I could actually get it to work like that.

As I said, I originally did this for a very specific purpose in my main app and then just added in a little more stuff for other people. I'll fix bugs if people report them but I leave the rest of it for other interested parties to fool with. I don't need heavy masked edit stuff in my app so it's not something I will spend that much time on. There are quite a lot of other areas I need to be working on in my program.

One of those areas I'll make a post in Tips & Tricks in a minute or so...
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Nice gadget, Xombie.

I have tried to implement it in a current project, but everytime I enter a character, my computer beeps. Am I missing something or is this a feature? I would like to turn off the beep if possible.

Thanks
Image Image
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

It works but it beeps? What version of PB are you using? If PB4, this wasn't built for it. I'll try to upload the updated version later this evening. Heck, I should rework the whole thing. That's some old code >_> I'm older and ... wiser now <_< ... :D
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Thanks Xombie. I am using it on 3.94 Windows. My OS is Windows 2000 Pro.

Thanks.
Image Image
Post Reply