|
Hello,
I want to create some custom groupboxes. What I did is created a new class called MyGroupBox that is derived from System.Windows.Forms.GroupBox .
Everything is going great but I have a problem. I want to overwrite the default OnEnabledChanged event and add a new feature.
What I did is this:
protected override void OnEnabledChanged(EventArgs e)
{
if (this.Enabled)
{
this.ColorScheme = EnmColorScheme.Purple;
}
else
{
this.ColorScheme = EnmColorScheme.Green;
}
}
Now what this will do is change the color of a disaled groupbox. The problem is that if I do this, the default functionality dissapers. When disabling a groupbox, all controls from the groupbox should be disabled. If I override the event, than his does not happen.
What can I do to make the event behave like in the past, but also hadd my functionality (to add colors).
I don't wan to implement this in every object that I created, that's why I am doing it in the main class "MyGroupBox".
Any help is greatly appreciated.
Thanks!
Vlad
|
|
|
|
|
I haven't looked but if the GroupBox default OnEnabledChanged is to loop through each child control and disable or enable them then that is your problem. Since you are overriding the default method you are not putting that code in there.
The code above is just changing the color. You need to add the code to disable/enable all the controls.
|
|
|
|
|
Hello,
Thanks for the suggestion but I already tried it in the past but it did not work. I used this:
for (int i = 0; i < this.Controls.Count; i++)
{
this.Controls[i].Enabled = this.Enabled;
}
The controls are getting activated, but they are not clickable. Can you give it a shot?
Vlad
|
|
|
|
|
I think you might have to force a refresh after changing it
try something like this:
protected override void OnEnabledChanged(EventArgs e)
{
if (this.Enabled)
{
EnableChildren();
base.Refresh();
}
else
{
DisableChildren();
base.Refresh();
}
}
private void DisableChildren()
{
foreach (Control c in this.Controls)
{
c.Enabled = false;
}
}
private void EnableChildren()
{
foreach (Control c in this.Controls)
{
c.Enabled = true;
}
}
|
|
|
|
|
I did try your example.. It does do what you want but it doesn't show up because it hasn't repainted the controls.
You will notice that once that runs and it disables all child controls that they appear to still be enabled (even though they are not). If you run your mouse over them they will redraw and will now show to be disabled.
After your for statement run a this.Refresh();
So when the groupbox gets called to disable/enable each time it will loop through each control and eitehr disable or enable them.
|
|
|
|
|
Hello,
First, your code could easily be written as:
foreach(Control c in this.Controls)
{
c.Enabled = this.Enabled;
}
base.Refresh();
*this is just a note
Now the problem is that it still does not work
I tried it with this.Refresh() also but still no luck...
|
|
|
|
|
I know that.
Here is what I created to mimic your problem:
public partial class CustomControl1 : System.Windows.Forms.GroupBox
{
public CustomControl1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
protected override void OnEnabledChanged(EventArgs e)
{
if (this.Enabled)
{
}
else
{
}
foreach (Control c in this.Controls)
c.Enabled = this.Enabled;
base.Refresh();
}
}
After I created that I created a Windows Form with two group box. One groupbox was my custom one, and the other was an normal group box. Each groupbox had two regular checkboxes in them. I also placed two buttons out to the right (one for Enable and Disable)
private void button1_Click(object sender, EventArgs e)
{
customControl11.Enabled = true;
groupBox1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
customControl11.Enabled = false;
groupBox1.Enabled = false;
}
Now on my form I click the Disable button and it disables both group boxes and all FOUR checkboxes. I click Enable and it enables them. This is what your problem was correct?
|
|
|
|
|
Hello,
I just wanted to add the reply and I see your message.
Anyways, I think I found the best way to do this. What I did is included this after my code (to change the color):
base.OnEnabledChanged(e);
So I call the "default" method from the main class. The idea came to me when you wrote base ... I don't use the base keyword to much.
What do you think? It works 100%, and it's the "fastest" way to implement it. Do you think it's "safe" ?
Thanks for the help!
Vlad
|
|
|
|
|
Would it be possible for you to post all the code so I can take a look at what you are doing? The ColorScheme is not part of the GroupBox so I figured that is something you created.
Calling base.OnEnabledChanged(e) will run the code in the base class which will disable / enable the child controls. That way you can get rid of your foreach statement in your method.
I'm still interested in the rest of the code as to why it wasn't working with a Refresh or Invalidate. Doing it that way should be fine and safe. Most likely is the fastest way also I would think
|
|
|
|
|
You've found the correct way of doing it! Nothing to worry about there...
|
|
|
|
|
The solution you reached in the end, calling the base's method is the correct way.
protected override void OnEnabledChanged(EventArgs e)
{
if (this.Enabled)
this.ColorScheme = EnmColorScheme.Purple;
else
this.ColorScheme = EnmColorScheme.Green;
base.OnEnabledChanged(e);
}
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Just a quick addition...
If your code is really that simple, you can drop the if/else and do a one liner:
ColorScheme = Enabled ? EnmColorScheme.Purple : EnmColorScheme.Green;
base.OnEnabledChanged(e);
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Ive got the webbrowser control navigating in a foreach loop which doesn't contain any IO yet i get the following exception
Exception:Thrown: "Could not find file 'C:\Users\Raymond\Desktop\TestProgram\bin\Debug\TestProgram.vshost.exe.config'." (System.IO.FileNotFoundException)
A System.IO.FileNotFoundException was thrown: "Could not find file 'C:\Users\Raymond\Desktop\TestProgram\bin\Debug\TestProgram.vshost.exe.config'."
foreach (string ValueName in Regkey.GetValueNames())
{
Browser.Navigate("http://www.google.com");
System.DateTime ThisMoment = System.DateTime.Now;
System.TimeSpan duration = new System.TimeSpan(0, 0, 0, 0, 10000);
System.DateTime AfterWards = ThisMoment.Add(duration);
while (Loaded != true || AfterWards >= ThisMoment)
{
Application.DoEvents();
Thread.Sleep(50);
}
}
with Browser.document completed set to the function below
private void BrowserCallback(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Loaded = true;
}
No IO is taking place and the path in the exception is correct it even happens whenh im not debuging
Is there any way to fix this or get the foreach loop to wait until Browser.documentcompleted is fired without using a delay ?
|
|
|
|
|
You may not be doing any IO, but the debugging process is. The file that is missing is the config file for the debug process. While you're debugging, the executable that runs is called "myprogram.vshost.exe" and the config file it uses is called "myprogram.vshost.exe.config."
Does your project contain a configuration file? I don't know the details, but it appears to be looking for some kind of configuration information for the application, and it's not finding it. If you use Google on the file name, it returns several links that describe the missing file, and ways to suppress its creation. But you may already have a setting in VS that is stopping it from being created, and your app really needs it. From my reading, by the way, it appears that these files are created even when you build a Release version, but there's no need to actually deploy them.
Not a complete answer, I know, but at least it narrows the search some. Good luck!
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
Strange but adding a app.config file solved the problem
modified on Sunday, June 27, 2010 12:47 PM
|
|
|
|
|
I thought it might take something like that, but I've had apps with no app.config file that worked fine. Some do, some don't, and I don't yet know why. Glad it solved the problem!
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
|
I'm working on a program that needs to run in the foreground (so it can hold up a script running until it's done) for the first part of the application, then switch to running in the background for the remainder of its life.
I have tried putting commands before the Application.Run() line, but that didn't work. I also tried changing it to a Command Line application in Visual Studio, but then it didn't go into the background at all.
Is there an easy way of doing this?
|
|
|
|
|
Not sure what you mean..........
Do you mean you want the GUI to move to behind all the other windows?
or
Do you want the thread priority to be reduced from normal to lower?
or
Do you mean something else?
|
|
|
|
|
Sorry, I'll be more descriptive.
When a windows forms application is run in the command prompt, you hit enter and you instantly see another standard command prompt line because the application has opened in the background (or at least it has been opened and told the command prompt that it's not needed any more).
What I want is for my application to not instantly ignore the command prompt but to do a few things and output a few lines to it before going off and being a windows forms application.
I think that's still worded badly, but hopefully you can figure out what I mean.
|
|
|
|
|
There are two parts - the application and the form that application displays.
Normally all the applicaiton does is display the form but you can do ther work before that.
Does this make it clearer?
|
|
|
|
|
Mmm... slightly. How do I do work before the form is displayed? I put my lines of code right at the beginning of the main() method and that doesn't work. Unless there's somewhere else I should be adding the code?
|
|
|
|
|
In an application i am working on there is program.cs with the following code:
namespace StreamTest
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
As you can see the Application.Run method is what triggers the UI so put your code before that. You can change the form definition to pass parameters if you want, I have done that before.
|
|
|
|
|
WubbleU wrote: I put my lines of code right at the beginning of the main() method and that doesn't work.
Yes, but what exactly are you trying to do and what is the result?
Your program should look something like
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new RotaForm());
}
You should be able to perform any other functionality before the three lines above to achieve the result you are after. However, it is somewhat difficult to understand exactly what you are trying to do, maybe if you post some of your code it will become clearer.
It's time for a new signature.
|
|
|
|
|
As far as I can tell, you want the project to be a Console project.
Perform your "before" stuff.
(Maybe wait for the user to press RETURN.)
Then call FreeConsole to remove the console window.
Then Run the Form.
[
System.Runtime.InteropServices.DllImportAttribute
(
"Kernel32"
,
SetLastError=true
,
EntryPoint="FreeConsole"
)
]
private static extern bool
API_FreeConsole() ;
/**
<summary>
Uses pinvoke to call the Windows FreeConsole method
</summary>
<returns>
The result of FreeConsole
</returns>
*/
public static bool
FreeConsole
(
)
{
return ( API_FreeConsole() ) ;
}
|
|
|
|