[C#] Form disablen maar zonder "greyed-out" controls

Pagina: 1
Acties:

  • reyan
  • Registratie: November 2003
  • Laatst online: 17-12-2021
Korte en simpele vraag waar ik met Google echter niet veel nuttigs kon vinden. Met .Enable = true kun je eenvoudig een form disablen. Het resultaat is dat geen enkele control erop - inclusief de form zelf - nog luistert naar input. Een tweede resultaat is dat de hele handel "greyed-out" wordt.

Nu dat laatste wil ik in een specifiek geval niet. Ik wil wel dat de hele form disabled wordt, maar het uiterlijk mag niet veranderd worden. Vergelijk het met wat er gebeurt bij een MessageBox.Show. Ook hier aanvaard de form van waaruit de MessageBox.Show wordt aangeroepen geen enkele invoer meer, maar de form zelf blijft wel uiterlijk onveranderd - dus geen greyed-out controls.

Kan ik dat gedrag nabootsen?

Ik wil het gebruiken om zelf een soort geavanceerde MessageBox in te bouwen in een applicatie. Nu is dat eenvoudig met .ShowDialog op een form uit te voeren, maar... dit "onderbreekt" de hele applicatie en dat is niet de bedoeling.

Korte situatieschets:

FormMain is de hoofdapplicatie. Daarop staat een button die Form1 opent. FormMain blijft ondertussen actief en kan nog steeds invoer aanvaarden. Op Form1 staat een button die FormMessageBox opent. De bedoeling is dat nu Form1 disabled wordt (zolang FormMessageBox open is), maar dat FormMain nog steeds invoer aanvaardt!

Ik heb dat werkende, maar zit met die vervelende grey-out van de disable.

Ik heb wel de indruk dat multithreading een andere (en waarschijnlijk betere) aanpak voor mijn probleem is. Kan iemand bevestigen of wat ik wil doen ook daadwerkelijk mogelijk is met threading vooraleer ik uren en uren tijd daarin steek. En hoe ga ik dan tewerk? Laat ik Form1 in een nieuwe thread starten?

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 12:06
reyan schreef op woensdag 30 november 2005 @ 14:19:
Korte situatieschets:

FormMain is de hoofdapplicatie. Daarop staat een button die Form1 opent. FormMain blijft ondertussen actief en kan nog steeds invoer aanvaarden. Op Form1 staat een button die FormMessageBox opent. De bedoeling is dat nu Form1 disabled wordt (zolang FormMessageBox open is), maar dat FormMain nog steeds invoer aanvaardt!
Edit:
*knip*
Je hebt gelijk, een Messagebox lockt de hele applicatie, en niet alleen het onderliggende form, zoals ik dacht...

[ Voor 29% gewijzigd door sig69 op 30-11-2005 14:36 ]

Roomba E5 te koop


  • reyan
  • Registratie: November 2003
  • Laatst online: 17-12-2021
Hier gaan we dan...In FormMain:
code:
1
2
3
4
5
private void button_Click(object sender, EventArgs e)
{
    Form1 form = new Form1();
    form.Show();
}
In Form1:
code:
1
2
3
4
5
6
7
8
9
10
private void button_Click(object sender, EventArgs e)
{
    FormMessageBox form = new FormMessageBox();
    form.Show();
    this.Enabled = false;
    // Met event handlers vang ik de close van de FormMessageBox weer op
    // zodat ik een .Enabled = true kan doen.
    // Als ik form.Show() vervang door form.ShowDialog() dan blokkeert niet
    // alleen Form1 maar ook FormMain en dat is niet de bedoeling.
}


UPDATE

Even simpel een nieuwe thread starten schijnt niet te werken. Als ik de code in button_Click in FormMain lanceer in een nieuwe thread, dan crasht het programma bij het klikken op die knop en de debugger geeft bij een aantal controls op Form1 "Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.". Mjah, blijkbaar lust de gebruikersinterface dus geen multithreading.

[ Voor 30% gewijzigd door reyan op 30-11-2005 14:47 ]


  • Mottebelke
  • Registratie: Juni 2001
  • Laatst online: 11:29
Je kunt ook het Focus event van Form1 een eventhandler geven zodra je de MessageBox opent.
In de eventhandler zet je dan dat de MessageBox de focus moet krijgen.

Dus zo iets:
code:
1
2
3
4
5
6
form1.GotFocus += new EventHandler(form1_Focus);

private void form1_Focus(...)
{
  msgBox.Focus();
}


En als je dan de MessageBox sluit verwijder je die eventhandler weer.

  • JapJap
  • Registratie: Maart 2001
  • Laatst online: 07-01 11:02
Sorry...

[ Voor 88% gewijzigd door JapJap op 30-11-2005 17:27 ]


  • SlowMeDown
  • Registratie: Mei 2003
  • Laatst online: 15-04 08:14
Een leuke truc is wellicht om een transparante control over jouw form te leggen. Alle controls die eronder liggen zijn dan mooi zichtbaar en ook nog enabled. Door de Validating event te gebruiken en Cancel op true te zetten, blijft de focus dan ook op jouw transparante control.

Ben je klaar met dat wat je wilt doen, haal je de Validating event weer eraf en remove je de control.

Engiste nadeel wat ik zo zie is het feit dat je de WS_EX_TRANSPARENT flag moet gebruiken en dat dit alleen werkt op Windows 2000 en hoger. Hieronder in ieder geval een klein controltje wat je zou kunnen gebruiken.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TransControl : Control
    {
        public TransControl()
        {
            SetStyle(ControlStyles.SupportsTransparentBackColor | 
                     ControlStyles.Opaque, true);
        }

        protected override CreateParams CreateParams
        {
            get
            {
                const int WS_EX_TRANSPARENT  =  0x00000020; 

                CreateParams pms = base.CreateParams;

                pms.ExStyle |= WS_EX_TRANSPARENT;

                return pms;
            }
        }

    }

Op het moment dat je alle input op de onderliggende controls wilt blokkeren doe je zo iets als
C#:
1
2
3
4
5
6
7
TransControl ctrl = new TransControl();
this.Controls.Add(ctrl);
ctrl.Dock = DockStyle.Fill;
ctrl.BringToFront();
ctrl.Focus();

ctrl.Validating += new CancelEventHandler(ctrl_Validating);

In de ctrl_Validating doe je dan Cancel op true zetten.

Na ja, is natuurlijk niet 100% af, maar wellicht een start. Succes ermee.

[ Voor 4% gewijzigd door SlowMeDown op 30-11-2005 17:29 ]

Pagina: 1