Thursday, August 8, 2024

Preventing Accidental Clicks and Double-Clicks in Your Microsoft Access Forms

 Preventing Accidental Clicks and Double-Clicks in Your Microsoft Access Forms


You know it's happened to you at least once in your life where you accidentally double-clicked on something instead of just clicking on it. And you know, you double-click on a button that you should have just clicked on once and now it happens twice like printing a long report. 

So in today's video, we're going to talk about preventing accidental clicks and double-clicks in your Microsoft Access Forms. Today's question comes from Felix in Peoria, Arizona, one of my Platinum members. Felix asks, how can I prevent a user from accidentally double-clicking a button that should only be clicked once, such as a print report button? I want to ensure that the action stops after the first click. I've got a lot of users, myself included, who accidentally double-click on buttons and send down two copies of a 13-page report. Happens a lot.

Yeah, this has happened to me a couple of times, too. I used to have this end-of-month report that I'd run in my own database, and it involved action queries, like an Append query and some other stuff, importing. And once in a while, I would accidentally double-click on it, and it's like a two-minute process. And so I'd be like, ugh. All right, so how do we prevent that from happening?

First up, some prerequisites. This is a developer-level class, so you're going to need to know a little bit of VBA. So if you've never done any VBA programming before and you want to learn how, go watch this video first. It's about 20 minutes long and it will teach you everything you need to know to get started programming in VBA and Access.

Okay, so here I am in my TechHelp free template. This is a free database you can download a copy off my website if you'd like to. You'll find links down below. And in here I've got a little button that just says, Hello World, and it puts Hello World in the little status box. That's all that guy does.

But let's reprogram this button and we're going to pretend that this button launches some long event, like printing a big document or running a big append query or an import or something like that. Now, I'm just going to simulate that event by using a sleep timer. I'm going to make the system just sleep for one second and that will be enough for us to see that multiple clicks are happening. 

Now if you downloaded a recent copy of this in the global module here, you will find a copy of my sleep function. It's right here, sleep sec, and we declare it right there. That's where we get the sleep function from. I got a whole separate video that explains this thing and how it works. You'll find a link to this video down below.

All right, so let's reprogram this button so it does something and just so we can see how many times the button click actually registered, let's turn this box into a counter. So we can see every time that the event runs, we'll just increment the counter one. So let's just rename this here counter. The box itself, let's go to all. I'm going to rename the box to counter. Let's get rid of the control source and get rid of the format and I'll set the default value to 1. So when the form opens up, that will have the value 1 in it. 

Now the button itself, I'm just going to put on here print or whatever. We can leave it Hello World button, that's fine, that doesn't matter. Save that. Now let's go into the button, build event and instead of status Hello World, I'm going to say counter equals counter plus 1. We're just going to increment that counter variable. That's all that's going to do. Right? So come back out here, close it, open it back up again, click the button, it goes to two. Click it again, it goes to three. 

Now, you've all seen this before. If you haven't done it yourself, I'm sure you know someone who has. I used to teach Windows basis classes in the classroom and all the time I would tell people, no, just click on the icon and they would double click and you can't fault them. If you're new to computers and I used to teach a lot of newbies, it takes a while to get the concept of a double click and even if you're an advanced computer user like myself, I accidentally double click on something. I just did it this morning. 

So what we want to do is we want to intercept that second click and stop it from happening. The only way we can really do that is to make the button know if it's currently being used. We're going to set a variable and say, hey, hold on. I'm in use right now. I'm unavailable. So if a click happens, just ignore it. 

Now the first thing we're going to do is we're going to simulate a long process happening. So what I'm going to do is use a sleep in here. I'm going to say sleep 1,000. Those are milliseconds. So it's going to sleep one second between clicks. And that will give us the opportunity to see what's going on there. Save that, come back out here. 

Now if I click, you'll see there's a delay and then it goes to two. Click again, a delay, and it goes to three. Even if I double click, watch this, click, click, four, five, it's still getting that next click. One, two, three, I just clicked three times, six, seven, eight. So we have to intercept that somehow. 

All right, and the way to do that is back in the code, we're going to set a variable that is going to know that this particular button has just been clicked. It's processing something that's already started. Now, there's a couple different ways we could do this. We could use a form field. We could use a global variable. We could use any number of different ways to do this. I'm going to use a temp var because I love temp vars. And if you don't know what tempVars are, talk to Adam. 

Now, tempVars are basically just system memory variables that have a lot of benefits to them. I like to use them a lot. Go watch this video if you want to learn more about them. So right here, I'm going to say tempVars isProcessing equals true, okay? And then when the event is done running, I'm going to say it equals false, okay? 

Are you with me so far? Now, when we first come into this, I'm going to say, if tempVarsIsProcessing equals true, then exit sub. In other words, when you first come in here, if this is true, just leave. Don't do anything, okay?

Now we should initialize this temp vars somewhere. Normally temp vars for Boolean types will be initialized to false. Long integers default to zero. Strings default to an empty string, but I don't like relying on that, so I'm going to initialize this to false when the form loads. All right, so I'm going to find the form load event, and when the form loads, we're going to set it to false. 

In other words, it's not processing when the form first loads and we've made sure that the value is set to false. Now why can't we just use a regular variable in here? Well, it has to be at least a form level variable. We could declare a variable out here. That would work or you could use something called a static variable. There's all kinds of different options. I like tempvars. And yes, I've got videos for global variables and static variables and all that different stuff. You'll find them on my website if you want to learn more. 

All right, so let's save our work. Let's give it a debug compile. Always good to do once in a while. Debug compile, make sure there's no syntax errors. Come back out here, hit the button again. Okay, I got a nine. Let's double click it. Click click. Ten, eleven. Okay, alright, hang on. Click click. Twelve, okay, so what's happening? It's still registering twice. What happened here? It's not checking to see if it's equal to true and exiting sub. 

Well, the problem is that while the code is running, it can't stop to check anything else until the code is done executing. So what happens is it runs this, it runs this, it goes through this, it does this, sets it to false. And as soon as it exits back out again, your second click processes. And it starts the process all over again. So we need some way in here to interrupt that. We need some way to say, okay, when you're done sleeping, alright, but before you set this to false, I need you to go out and check to see if any other events want to run. Go out and check to see if, you know, some other form wants to do something or if the user happened to click.

These are all things that we can check for with doEvents. doEvents says, I'm going to hold on for a second, you do whatever else you got to do and then I'll finish doing what I was doing. What will happen is doEvents frees up the system for your second click to start processing. Once that second click processes, it's going to come in here and say, are you busy? Oh, yeah, you're busy because we haven't set up the false yet. See? So it comes back in here, says you're busy, exits out and doesn't process that click. Makes sense? You following me? doEvents is like going, all right, what do you want to do? Okay, and then it goes and does it. 

All right, so save that. Now, if I come out here and I go click, click, I only get one. Now, let's set this back to one so we can see it's easier. All right, so that's one. I'm going to go click, click. I just double-clicked. It goes to two and it stops. Why? Because as soon as it got to this spot here, it freed up the cycle so that the processor could go and run any other events that wanted to run. Alright, it grabbed that second click out of the buffer, re-ran this module, a second copy of the module basically ran, right, that's what doEvents kind of does, and the first thing it processed was this and it says, are you processing? Yeah, the other module, the other copy of the module was processing. So it exited out of the second click, then it comes back to the first click, now it can free up and say, I'm done processing. See how that works? It's tricky. It's all about learning how these processes run.

Another thing you could also do if you want the user to visually see that they can't click a second time is what you could do is like right here after the counter, you could say, make the button disabled. So say, hello world button dot enabled equals false. That will make it grayed out. Okay, and then I would throw another doEvents here so it updates the screen. Okay, so your counter will increment, the button will get disabled, the user will see that, the process will run, doEvents will run again and free everything up and clear that variable and then it will exit out. 

And if you want to re-enable the button after that, you can or you can just leave it disabled. If you want to make it so that you got like a big report and you don't want the user printing it a second time, you could force them to have to exit the form and then come back in so the button's enabled again. That's up to you or make a second button to unlock it, whatever. I think this works just fine.

So save this and back out here. I'm going to close and reopen it just to make sure everything is cleared. All right, ready? I'm going to double-click now. Double-click. See? It disabled the button, which you could visibly see, and it didn't run my second click. Let's do it again. I'm going to click three times. Click, click, click. See? It disabled the button, and it only processed one of those.

All right, I turned mouse click effects on in my software. Let's see. Click. All right, I'm going to double-click now. Click and a double-click now they only click once; I'm going to click three times and I only did one, see? I'm going to turn that off. I personally find those mouse click effects annoying. I don't know, what do you think about those? When I watch other tutorials and people have these, you know, mouse halos on and the click events and I find that distracting myself. I don't know. Do you like that? What do you think? Post in the comments down below and let me know what you think. All right. I turned it all back off. That's how I like to do it. Alright.

So there you go. That's how you disable the button, clear that event, and you only get one click out of that button no matter how many times the person clicks on it. Unless they happen to click before, you know, if they click while the process is just finishing, they might get that second click. You could add an additional sleep timer in here. So even after, let's say, this is your print event. You could add another second or two second pause down here before you set that temp var to false. And that will give them a buffer, maybe put like a five second pause in there, I don't care. That way, you know, in case they do click longer or multiple times, it will still eat up that time. Up to you. 

All right, I give you the Legos. You can play with them, build however you want. Do you like this stuff? Do you like learning with me? I got lots and lots of lessons on my website, folks. Tons and tons of them. Hundreds of hours of videos. And they're all arranged in a nice, orderly fashion. You know, level one, level two, level three, in the order that you should learn them. Okay, so check them out. You'll find a link down below. And yeah, it's cool stuff. And we have a lot of fun so that's gonna do it folks that is your TechHelp video for today I hope you learned something live long and prosper my friends I'll see you next time.

A special thank you and shout-out to our diamond sponsor Juan Soto with access experts software solutions. They're manufacturing experts specializing in Microsoft Access and SQL Server. Juan is a 13-time Microsoft Access MVP. Check him out at accessexperts.com.

For a complete video tutorial on this topic, please visit https://599cd.com/AccidentalClicks

No comments:

Post a Comment