-
[RESOLVED] Disable an entire Form
I need to disable every control on my Form so that the user can not click or press any key that will change values of listboxes and other controls on the form. I need to be able to lock the whole Form like this because as part of the project I have to print the form 3 times with 3 different colors and the only way I've been able to get it to work is with a timer. So for about 3 seconds the form is changing colors and printing itself, so in between that time the user could accidantely click something and change a value on the form when all three prints should be of the same form, only difference is in the color.
I can't use disable as that will make all the controls look faded and messed up, I need a clean way to prevent anything from being changed.
If worst comes to worst I will probably just loop through every control at runtime and attach a handle to a click and keypress sub that mark the clicks and keypresses as already handled. I'm hoping for an easier way though.
-
Re: Disable an entire Form
Well you don't need to go to the length of trapping every control's keypress event - you can just set the form's KeyPreview property to true and then in the KeyPress handler set e.Handled to true.
Trapping the mouseclicks may be more of a problem - back in the old days of VB6 there was a Locked property which effectively made the control disabled but didn't change the appearance of the control. The Locked property in .Net just freezes the position of controls now and the ReadOnly property seems the nearest equivalent but only applies to a limited number of controls (I'm not sure whether Locked was the same - possibly it was).
An alternative may be to place a transparent picture box over the top of the form while you wish to freeze it.
-
Re: Disable an entire Form
Keystone,
Thanks for the input, the PictureBox sounds good for blocking any Mouse Clicks however I'm not sure that using KeyPreview = True and using the Form's KeyPress event to cancel them will work completely. It will block most keypresses however I've noticed in the past that even with KeyPreview on, when there are buttons on the form, the arrow keys will still focus on the buttons and the Forms KeyPress event will not fire when using them. I do in fact have buttons on my form, I will still give it a try but I'm guessing that I will still have the focus outline around buttons in the printed picture, so any ideas about stopping that?
-
Re: Disable an entire Form
Something I wasn't aware of until seeing JMcilhinney's response to another question (about preventing the focus appearing) is you can set the form's ActiveControl property = nothing.
If you insert that line just before you do a capture it should prevent any control from showing the focus rectangle.
-
Re: Disable an entire Form
I'm trying the picuterbox thing but I can't get it to work. How can I get it to be transparent? I tried making a completely transparant .GIF but that didn't work, it showed up as white and blocked the form. Then I tried the forms transparency color, however I knew that it would result in (and it did) everything being transparent. Any idea on how to get that to work?
-
Re: Disable an entire Form
Each control also has a .CanRaiseEvents property (overrideable) also, you could temporarily make that return false. If you find nothing else.
-
Re: Disable an entire Form
vb.net Code:
Me.Enabled = False
'do your work
Me.Enabled = True
EDIT:
AAAhh... I see. you have already opted out that option.
-
Re: Disable an entire Form
What happens if you hide the form for the duration?
Edit: Or, as an alternative, show a second form sized to the size of the first form, and positioned on top of it.
-
Re: Disable an entire Form
OK.. Try this.
It's more of a hack than straight code, but should be good for your situation.
Put everything on your form in one container so that you can show/hide it.
Here for example I assume it is a Panel named Panel1.
vb.net Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.BackgroundImageLayout = ImageLayout.Center
Me.BackgroundImage = CaptureScreen()
Application.DoEvents()
Panel1.Visible = False
'do your work here
Panel1.Visible = True
Me.BackgroundImage = Nothing
End Sub
Private Function CaptureScreen() As Image
Dim myGraphics As Graphics = Me.CreateGraphics()
Dim s As Size = Me.ClientSize
Dim memoryImage As Bitmap = New Bitmap(s.Width, s.Height, myGraphics)
Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
Dim pt As Point = PointToScreen(New Point(Me.ClientRectangle.X, Me.ClientRectangle.Y))
memoryGraphics.CopyFromScreen(pt.X, pt.Y, 0, 0, s)
Return memoryImage
End Function
-
Re: Disable an entire Form
Quote:
Originally Posted by
Vectris
Any idea on how to get that to work?
Sorry I sent you off on a wild goose chase there - it doesn't look like its possible in .Net. It is something I'm pretty sure I've done in the past in VB6 but .Net handles transparency differently.
I managed to get it to create the transparent picture box, however it always puts the other controls on top of the picture box even if you explicitly use myPictureBox.BringToFront.
-
Re: Disable an entire Form
How about doing something simple like
Code:
Windows.Forms.Cursor.Hide()
'do your form printing stuff here.
Windows.Forms.Cursor.Show()
-
Re: Disable an entire Form
Smart thinking Hack - that in conjunction with the Form KeyPreview trapping ought to do the trick.
-
Re: Disable an entire Form
I think a better alternative is:
Code:
My.Computer.Keyboard.ChargeWithHighVoltage = True
My.Computer.Mouse.IsRealLiveMouse = True
-
Re: Disable an entire Form
@Shaggy
I tried that but unless I use Form.ShowDialog() then the transparent form will always appear underneath the first one and it's useless. And if I do use ShowDialog then the rest of my code on the first form will not execute, and I have multiple things I have to do/print while the form is locked.
@Hack
Will that really keep the cursor from working though? Or will it just make it invisible but the mouse can still click things? And yes I can and will test this out myself but I would like to double check
@Forum (2nd Post)
I'm assuming sarcasm =P, but are you disagreeing with the previous ideas or just making a joke?
@keystone
I'm going to try Hack's mouse thing but I'm still having problems with the keyboard. I tried using KeyPreview true and marking any keypresses as handled on the Form KeyDown. The problem is that Tab still works to cycle through controls and some of them are CheckedListBoxes, so if the user presses Tab and focuses on one of them, instantly the first index will be highlighted blue and it will mess up the screenshot of the form that I am trying to print. I could cycle through all controls and make the TabStop False but then it would be using a lot of code again, and I'm hoping for a simpler solution. I'll try some more tests though and double check some things.
-
Re: Disable an entire Form
I wasn't suggesting anything transparent, I was thinking of something more like a large scale messagebox. It could be shown non-modal, but that will only work if the original form was shown non-modal as well.
-
Re: Disable an entire Form
Oh wait I see what you meant, you mean a message box that prevents you from reaching the other form.
It will still have the same problem as the Form though, it would prevent the next code from running. It would also probably mess up the screenshot.
-
Re: Disable an entire Form
By any chance, did you miss my post #9 ?
-
Re: Disable an entire Form
I've tried (and failed) to find a simple and elegant way of stopping the user from tabbing between controls, but I've found another slight hack that works :
Basically pick a control on your form (if your user activates the screen grab function via a button then thats a good choice) and bounce focus back to that control if the user attempts to move onto another control, making use of the control's LostFocus event.
The code below demonstrates this - when the user clicks on Button1 it will suddenly become a focus-magnet and any attempt to move focus away will fail (it doesn't even flicker on screen). If you combine this with hiding the mouse pointer then I think you're getting there.
Code:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
AddHandler Button1.LostFocus, AddressOf BounceFocus
End Sub
Private Sub BounceFocus()
Button1.Focus()
End Sub
Of course you will need to Remove the handler when you have finished your screen grabs in order to re-enable the form.
-
Re: Disable an entire Form
Hmm.. I've looked at bit further into Hack's suggestion of hiding the cursor, but your suspicion is correct - you can still click but you just don't know where the cursor is.
You could prevent this though by setting the cursor's clip rectangle to something suitably small and out of the way for the duration of your activity, although this isn't necessarily something that will thrill the user as it will effectively paralyse their system for the duration.
If you wanted to go down this route you would have something like this :
Code:
Private Sub FreezeWindow
Windows.Forms.Cursor.Clip = New Rectangle(0, 0, 5, 5)
Windows.Forms.Cursor.Hide()
AddHandler Button1.LostFocus, AddressOf BounceFocus
End Sub
Private Sub BounceFocus()
Button1.Focus()
End Sub
And then when you are down, re-show the cursor, set its clip region to nothing and remove the handler for the Button1.LostFocus event.
Code:
Private Sub UnFreeze()
Dim myEventHandler As New EventHandler(AddressOf BounceFocus) 'declare a variable with addressof your sub
RemoveHandler Button1.LostFocus, myEventHandler
Windows.Forms.Cursor.Clip = Nothing
Windows.Forms.Cursor.Show()
End Sub
Out of interest, going back to basics, why does it take 3 seconds to change some colours and print the form? Perhaps there may be a better way of doing your main task rather than having to go down this route?
-
Re: Disable an entire Form
What about popping up a modal form(using ShowDialog) outside of the screen boundries? Then when you are done, you simply hide that dialog and control returns to your main form.
-
Re: Disable an entire Form
That would have the same problem as my suggestion. The modal form would block any activity on the first form until it has gone away.
On the other hand, if the modal form was sized to the size of the underlying form, and received the underlying form as an argument, then it might work to have the printing take place from the modal form rather than the underlying form. If the modal form had a reference to the underlying form, then it could call methods of that underlying form. I don't know whether that would work with printing, but it should work for anything else.
-
Re: Disable an entire Form
Shaggy, I actually tested it out and a timer on the first form still fires even when the modal dialog is up.
So I did
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer2.Enabled = True
f.Location = New Point(-800, -800)
f.StartPosition = FormStartPosition.Manual
f.ShowDialog()
End Sub
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
f.Hide()
Timer2.Enabled = False
End Sub
-
Re: Disable an entire Form
Well I'm already using a Timer as part of it, setting up another timer to run the code after the modal form may work but I think I have an idea.
Keystone, your lost focus idea will work but instead of waiting for the user to click a button to make it a focus magnet, I can use .Focus() to focus on whatever control I want to get it stuck on, then turn it's Active property (or whatever it was) to false so the focus outline doesn't appear.
Then use the KeyPreview to block any other keypresses.
And lastly, the mouse, Hide will at least make the cursor invisible and would it work to set the mouse's position to 0,0 on some kind of MouseMove event? Then it's invisible and you can't move it over anything clickable (so long as the upper left corner is empty).
I'm not sure what even I can use for MouseMove though, haven't looked but I only remember there being mouse over and hover, I think over only fires once on the first MouseOver and I'm not sure what Hover does.
Still haven't tested any of this as I always check the forums late at night when I'm too tired too, but I think we're close to a solution.
@Pradeep
I saw it, didn't try it, but don't think it will work because if I put everything on one panel and then hide the panel, then my entire form is gone. And what I'm trying to do is keep everything on the form visible so I can take multiple timed screenshots of it, but without the user changing textbox values/listbox values in-between shots.
-
Re: Disable an entire Form
Quote:
instead of waiting for the user to click a button
Yeah of course - I was just using button.click in my example as I needed somewhere to raise it from.
Quote:
And lastly, the mouse, Hide will at least make the cursor invisible and would it work to set the mouse's position to 0,0 on some kind of MouseMove event? Then it's invisible and you can't move it over anything clickable (so long as the upper left corner is empty).
Moving the mouse position to 0,0 on mousemove is a possibility - mousemove does indeed exist (there are 10 different events for capturing mouse activity!)
Doing this does have the same drawback as the clip idea - in that I don't think it will be possible for the user to move their mousepointer to any other application while you are doing your work (unless they move up or left I guess).
-
Re: Disable an entire Form
Quote:
Originally Posted by
keystone_paul
I don't think it will be possible for the user to move their mousepointer to any other application while you are doing your work (unless they move up or left I guess).
No this is a good thing. If another window (application) opened up over the program, then when I used the screen capture code the application would be in the way and it would block it. The printing/screen capturing only takes about 5 seconds. So I guess I really could say I just need to lock the computer for 5 seconds, but I figured locking the form would be easier.
-
Re: Disable an entire Form
Quote:
Originally Posted by MSDN
The BlockInput function blocks keyboard and mouse input events from reaching applications.
The good thing is that ctrl+alt+del will override this block so no need for reset if things get ugly. A nice little second form should pop to inform the user he has to wait several seconds.
Code:
Private Declare Auto Function BlockInput Lib "user32" (ByVal fBlockIt As Boolean) As Boolean
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button2.Click
BlockInput(True)
Timer1.Interval = 5000
Timer1.Start()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Timer1.Tick
Timer1.Stop()
BlockInput(False)
Beep()
End Sub
-
Re: Disable an entire Form
instead of using a giant picturebox to cover it, have you tried a giant label?
You could also simply loop through all controls on the form with code and set them all to disabled. (not hidden). This should gray them out.
Also since you know how to take screen shots, you could simply take one of your form and display the screen shot of the form in the form's picture box.
Showing a modal form won't stop code execution in the form if you use a background worker or a threaded timer.
-
Re: Disable an entire Form
Quote:
Originally Posted by
Lord Orwell
instead of using a giant picturebox to cover it, have you tried a giant label?
How would that work, labels aren't transparent.
Quote:
You could also simply loop through all controls on the form with code and set them all to disabled. (not hidden). This should gray them out.
I pointed out in the first post that I need the controls to not look grayed out/disabled.
Quote:
Also since you know how to take screen shots, you could simply take one of your form and display the screen shot of the form in the form's picture box.
That would work if I wasn't changing the form and then taking screenshots of it each change. I'm not printing the same screen, I change the forms color and some small other things in between each capture.
Quote:
Showing a modal form won't stop code execution in the form if you use a background worker or a threaded timer.
I actually tried using a timer to do the printing/capturing before I realized I had to lock the form. I ran into to many problems with the Printing Pop Up Message getting in the way of the next screenshot, even after it closed.
I may try this again if all else fails.
-
Re: Disable an entire Form
sorry, used to vb6 labels, and i missed the note in the OP. I would ask you to reconsider though since a visual cue to the user is always good.
-
Re: Disable an entire Form
Quote:
Originally Posted by
Vectris
...
@Pradeep
I saw it, didn't try it, but don't think it will work because if I put everything on one panel and then hide the panel, then my entire form is gone. And what I'm trying to do is keep everything on the form visible so I can take multiple timed screenshots of it, but without the user changing textbox values/listbox values in-between shots.
I hope you give it a try. The exact code or a simple modified version of it could work for you.
What that does is this:
Takes a screenshot of the form, and hides your panel (that has all the controls in it) and shows that screenshot, until your task is done. The user would never know whether he is seeing a dummy image or the actual controls and would never be able to click it. If you want to exclude some controls, i.e. make some of them clickable, you can simply exclude them from the frame that you hide/show.
-
Re: Disable an entire Form
Quote:
I hope you give it a try. The exact code or a simple modified version of it could work for you
The problem is that Vectris needs to have the controls visible as he is taking a screenshot, then programmatically changing some properties, taking another screenshot, changing some more properties and then taking another screenshot.
The actual controls need to be visible in order for him to get the screenshots, but your suggestion would hide the controls and just show a picture of them. He wouldn't be able to change the properties and get his 2nd screenshot.
His problem is keeping the controls on screen, looking "enabled" but not allowing the user to tamper with them until he has all his screenshots.
-
Re: Disable an entire Form
That should be easy, isn't it?
Taking a screenshot takes a split second. Moreover, you won't need my method to take a screenshot as you might already be having a better version.
What you would do is based on same concept. Show the Panel for split second, take screenshot, set the screenshot as new form background, and then hide the Panel. Then change whatever values you want to change, show the panel, take a screenshot, set the screenshot as new form background. Then hide the Panel again. We continue in this fashion until our work is done.
-
Re: Disable an entire Form
Quote:
Taking a screenshot takes a split second
Agreed - I raised the point earlier in post #19 - not sure why it can't all be done in the blink of an eye without the user having chance to make changes, but I assume that there is more to it than that.
I can't help thinking that if we know a bit more about what was needed there might be a better way than disabling the form.
-
Re: Disable an entire Form
Pradeep, I didn't know exactly what your code does but now I believe it may work.
First, here is exactly what I'm doing. This is the final project for our VB class and you'd think it would be something challenging and that required programming smarts and skills, but no. Instead of making a calculator, game, or some other cool program, all we are told to do is make a Form that looks like a Referral and lets the user (teacher) select what the student was written up for and then press a print button which will print out 3 copies, the only difference in the copies (this is what I change each time) is changing the background color from white to pink to canary (yellow).
I really hate this assignment because you don't have to know a thing about VB to just drag textboxes and labels onto the form to make it look like a referral. Then, no coding is necessary for making checkboxes look checked. And the only coding we have to do is the printing, which we haven't learned and isn't even in our book.
Anyways, I made my form look exactly like the example referral we were given and I have an API that snaps a screenshot of nearly the entire screen (not just the form) but anything around the form is turned white. So since the form doesn't cover the entire screen, there is a large white outline around the picture with the form in it and it's so big that when it prints, the part of the image with the actual form is cut off. To fix this I got a Function for resizing an image to be smaller so the form portion of the image would stay on the page.
Then I had a problem each time I got the screen and then printed because after a print, a pop-up box comes up for about 3 seconds and then it lags the form a bit for another 2 or 3. So I have it on a timer to change the color, snap the screen, and then print. Then it waits 5 seconds for the pop-up to come and go, then it does it again for each of the other colors.
I can probably use pradeeps idea then (I think I'll re-code it myself since it sounds simple enough) and just have it all on a panel that will be the same size as the form. Then, I'll change the bg color of the panel, snap the shot, and instantly set it as the image for a picture box that will be made visible after the shot. Then a timer will wait 5 seconds for the pop up to come and go, and then change the bg color of the panel, make the picture box visible false, and lastly make the panel visible again.
I can't remember if we ruled this out, but couldn't I skip the panel and just place the picture box with the image in front of everything else? That why I only show/hide the picture box and the Form can remain behind it.
-
Re: Disable an entire Form
Quote:
Originally Posted by
Vectris
...
I can't remember if we ruled this out, but couldn't I skip the panel and just place the picture box with the image in front of everything else? That why I only show/hide the picture box and the Form can remain behind it.
The only problem I see with keeping the panel visible while putting the picturebox in the foreground is that the user can still use the keyboard to change things on the panel. (press tab two or three times and then press the up/down arrow to change combobox values etc.). So whatever approach you follow, I would suggest you hide the panel that holds the actual controls.
-
Re: Disable an entire Form
OK so if I understand correctly the reason you have the whole setup with timers and locking the form is because of some printing related dialog box which pops up during/after printing?
There is a simple solution to the problem :
Don't print the images immediately, capture all three images in a burst and then print all three after they are all captured.
That is going to give you a much cleaner program without nasty hacks.
-
Re: Disable an entire Form
have you looked into only printing the form itself? This functionality exists directly in visual studio 2008 and it's a download for 2005.
-
Re: Disable an entire Form
@Keystone,
Once again I overcomplicated things... I can't believe I did that. The only problem I can think of is if changing the bg color and then taking the screenshot creates any kind of lag on the form that would cause each successing screenshot to mess up. In that case then I would have to go back to a timer to separate screenshots. I haven't tested it without the print code though, and the printing is pretty much the only thing that makes it lag.
Quote:
Originally Posted by
Lord Orwell
have you looked into only printing the form itself? This functionality exists directly in visual studio 2008 and it's a download for 2005.
No I haven't, I think I can get this fixed without that though, still thanks.
-
Re: Disable an entire Form
Quote:
The only problem I can think of is if changing the bg color and then taking the screenshot creates any kind of lag on the form that would cause each successing screenshot to mess up
I think that theoretically so long as you throw a Me.Refesh in after changing the colour you should be OK but the only way to be sure is to give it a go and see what happens.
-
Re: Disable an entire Form
Any joy with this? Interested to know how you got on in the end.