1

I have a Winform project in VB.net 2013. On a form I have a lot's of controls. When a condition is true , I need to make all the controls inside a specific form's area , not clickable ( but without disabling them ) Of course , when the condition became false the area should return to normal state. Thank you !

alex
  • 694
  • 3
  • 15
  • 35
  • You cant ... just create an event and hook it up dependent on what you need... – Trevor Apr 06 '15 at 04:04
  • 1
    Could you be more clear ? Inside this form's area I have controls of different types.When the condition is true , I need that all these controls to just be unusable by the user , but I don't want to disable them because I don't want the "disabled paint style". – alex Apr 06 '15 at 04:14

2 Answers2

1

You could assign a NativeWindow to each control and intercept the HITTEST message.

E.g. This example only does it for the immediate Form's children. You could also recurse through all the children.

Form f = new Form();
f.Controls.Add(new Button { Text = "test test test "});
Form f2 = new Form();
CheckBox cb = new CheckBox { Text = "Toggle" };
f2.Controls.Add(cb);
List<NW> nws = null;
cb.CheckedChanged += delegate {
    if (nws == null) {
        nws = new List<NW>();
        foreach (Control c in f.Controls) {
            nws.Add(new NW(c.Handle));
        }
    }
    else {
        foreach (var nw in nws)
            nw.ReleaseHandle();
        nws = null;
    }
};
f.Show();
Application.Run(f2);


class NW : NativeWindow {
    public NW(IntPtr hwnd) {
        AssignHandle(hwnd);
    }
    const int WM_NCHITTEST = 0x84;
    protected override void WndProc(ref Message m) {
        if (m.Msg == WM_NCHITTEST)
            return;
        base.WndProc(ref m);
    }
}
Loathing
  • 5,109
  • 3
  • 24
  • 35
  • 2
    That's C# my friend, not VB.NET. – Visual Vincent Apr 06 '15 at 08:08
  • @ Loathing : Your code is working partially. It's strange but all the controls became not clickable except Textboxes and DatetimePicker that remain clickable and editable. why ? – alex Apr 07 '15 at 03:16
  • @alex In `NW` you can change the test to `if (Msg != WM_PAINT) return;` where `const int WM_PAINT = 0xF;` That will make it so the controls can't be typed in. Make sure you are getting all nested child controls too, e.g. http://stackoverflow.com/questions/8595425/how-to-get-all-children-of-a-parent-control – Loathing Apr 07 '15 at 04:18
  • Sorry , it's the same situation. TextBoxes and DatetimePicker remain clickable and editable. And now with your changes , sometime in some buttons the text is missing when the controls became not clickable. Also It's sure that I have include all controls , because I made a breakpoint and I have detected that the textboxes and datetimepicker are included. – alex Apr 07 '15 at 04:36
  • @alex Can you confirm you are using ` != ` and not ` == ` ? Painting not working makes me think you are using ` == `. You want to allow paint messages to go through and stop everything else. – Loathing Apr 07 '15 at 04:42
  • Yes I'm using the corresponding != for vb.net , so <> , and I said only on the button;s the text is missing , all other are paint correctly. – alex Apr 07 '15 at 04:43
  • @alex I've tested it using a `TextBox` and `DateTimePicker` in a nested `FlowLayoutPanel` and it works as expected. Post a simple example that doesn't work and I will take a look. – Loathing Apr 07 '15 at 04:47
  • I;m using exactly your code , but for a Groupbox ( or panel) with several controls inside. The only thing that change is that I doesn;t use Foreach control in f.controls , but For each control in Groupbox1.controls. – alex Apr 07 '15 at 04:50
  • @alex I tested both .NET 35 and 45, and both worked as expected. Not sure why it's not working for you. Another solution you might consider is `IMessageFilter`. – Loathing Apr 07 '15 at 05:07
  • I'm using NET 4.0 , and I have this issue only for Textboxes and DateTimePicker. All the other controls are working as expected. – alex Apr 07 '15 at 05:15
  • I don't know why , but applying this : foreach (Control c in TestBox1.Controls) { nws.Add(new NW(c.Handle)); } resolved the problem. Very Strange ! – – alex Apr 07 '15 at 21:46
  • @alex Thanks for confirming. You should also make sure you release the handles before your app closes, otherwise you'll probably get a cross thread exception (because the `WndProc` destroy events aren't being handled). The alternative is only intercepting the `HITKEY` and keyboard events. – Loathing Apr 07 '15 at 22:03
  • @Loathing - Sorry friend but I have noticed a problem. I'm using the version with WM_NCHITTEST (because I have problems with WM_Paint) . And now I have noticed that a user can press the TAB and can edit my textboxes and other controls. How to block this behavior too ? – alex Apr 08 '15 at 00:04
  • @alex To prevent key strokes you will need to selectively handle the `WM_KEY` message codes: http://wiki.winehq.org/List_Of_Windows_Messages E.g. `if (m.Msg == WM_KEYDOWN || m.Msg == WM_KEYUP || etc.) return;` or maybe just `WM_INPUT` will suffice. Not sure. You can play and research what works. – Loathing Apr 08 '15 at 01:36
  • @Loathing - Is there any special for TAB key ? I try with WM_Input , but doesn;t work – alex Apr 08 '15 at 01:48
  • @Loathing : The WM_CHAR block the modifications on the controls , but still the controls can have focus for example on Textboxes the text can be selected using TAB. So blocking Tab key for these controls or block these controls from Getting focus would be the solution I think. – alex Apr 08 '15 at 02:10
  • 1
    I think it's `WM_SETFOCUS`. – Loathing Apr 08 '15 at 03:49
0

Place all controls in a PANEL and then disable that panel.

panel.Enabled= false;

JPT564
  • 59
  • 2
  • If I disable the panel , all the controls inside will be disabled. will have a disabled paint style. I don't want this. – alex Apr 06 '15 at 04:11