|
Hi.
I just found the wonderfull SuspendLayout Method on the WinForm class.
I was wondering if there is a similar feature to susoend the layout for the whole Application in multible forms, without doing it on every single form?
Something like Application.SuspendLayout();;)
Any ideas or suggestions?
|
|
|
|
|
No, and why would there be? The whole idea of object-oriented programming is that objects are responsible for themselves (encapsulation, data hiding, etc.). Each form initializes it's surface so you just need to suspend and resume the layout in each. An Application in Windows Forms really just represents the message pump that keeps the main window (Form ) alive and dispatches window messages to their respective windows.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I have a Form containing a Panel that contains buttons.
The size of the panel will sometimes change, and I whant the bounds of the buttons to change acordenly to the panel.
Is there a method for this, or must I recalculate the bounds of all the buttons each time?
(Maybe something like setting the panel as the buttons parent)
Thanks
Thomas
|
|
|
|
|
The controls can automatically be resized, but they can't move in relation to an adjacent control's size automatically. For information on what is possible, see the Control.Anchor and Control.Dock property documentation in the .NET Framework SDK. These are exposed in the Visual Studio .NET designer as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
This is the second time someone asks a question like this. Simply point them to the code I posted (see post below this one).
This is a typical question from programmers that used a third party VB control, and that I believe is not available for .NET.
FYI: I know that the code posted does not work nicely with text boxes (for which I have a private solution), but it should give them a starting point to work from.
|
|
|
|
|
Second? Yeah right - try 200th. Instead of harping on me though, why don't you harp on the original posters for not searching previous forum threads BEFORE posting their (most-likely) previously-asked questions?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
Not harping on you, nor the original poster. Repetition is the unfortunte by-product of support, which you seem to do more than your share on this board.
|
|
|
|
|
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace Workbench
{
/// <summary>
/// A panel that resizes controls automatically.
/// </summary>
public class AutoSizePanel : Panel
{
/// <summary>
/// Holds the control info.
/// </summary>
private Hashtable htInfo = new Hashtable();
/// <summary>
/// Flag to prevent recursive call.
/// </summary>
private bool bAllowResize = true;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Constructor.
/// </summary>
public AutoSizePanel()
{
InitializeComponent();
}
/// <summary>
/// Adds a control to the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlAdded(ControlEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Create the original info
SizingInfo riData = new SizingInfo(e.Control);
// Add to table
htInfo.Add(e.Control, riData);
// BAck to normal
bAllowResize = true;
//
base.OnControlAdded (e);
}
/// <summary>
/// Removes a control from the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlRemoved(ControlEventArgs e)
{
// Delete the info
htInfo.Remove(e.Control);
//
base.OnControlRemoved (e);
}
/// <summary>
/// Does the magic.
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
// Only once
if (bAllowResize)
{
// Set
bAllowResize = false;
// And apply to each control
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Resize
riCtl.Resize(ctl);
}
}
// Reset
bAllowResize = true;
}
//
base.OnResize (e);
}
protected override void OnPaint(PaintEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Collect info
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Update
riCtl.Update(ctl);
}
}
// Back to normal
bAllowResize = true;
//
base.OnPaint (e);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// AutoSizePanel
//
this.Name = "AutoSizePanel";
this.Size = new System.Drawing.Size(232, 184);
}
#endregion
/// <summary>
/// This holds the original control information.
/// </summary>
private class SizingInfo
{
/// <summary>
/// Info to be kept.
/// </summary>
public int iTop;
public int iLeft;
public int iHeight;
public int iWidth;
public int iParentHeight;
public int iParentWidth;
/// <summary>
/// Constructor
/// </summary>
/// <param name="ctl"></param>
public SizingInfo(Control ctl)
{
// Save
this.Initialize(ctl);
}
/// <summary>
/// Updates the internal info
/// </summary>
/// <param name="ctl"></param>
public void Update(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And where it would go.
int iWTop = (int) (iTop * dRatioHeight);
int iWHeight = (int) (iHeight * dRatioHeight);
int iWLeft = (int) (iLeft * dRatioWidth);
int iWWidth = (int) (iWidth * dRatioWidth);
// Changes?
if ((iWTop != ctl.Top) || (iWLeft != ctl.Left) || (iWHeight != ctl.Height) || (iWWidth != ctl.Width))
{
// Reset
this.Initialize(ctl);
}
}
/// <summary>
/// Does the magic
/// </summary>
/// <param name="ctl"></param>
public void Resize(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And shake it
ctl.Top = (int) (iTop * dRatioHeight);
ctl.Height = (int) (iHeight * dRatioHeight);
ctl.Left = (int) (iLeft * dRatioWidth);
ctl.Width = (int) (iWidth * dRatioWidth);
}
/// <summary>
/// Saves the base info
/// </summary>
/// <param name="ctl"></param>
private void Initialize(Control ctl)
{
// Save
iTop = ctl.Top;
iLeft = ctl.Left;
iHeight = ctl.Height;
iWidth = ctl.Width;
iParentHeight = ctl.Parent.Height;
iParentWidth = ctl.Parent.Width;
}
}
}
}
|
|
|
|
|
I used the "Abort()" method of class Thread in a program to cancel a thread. It seemed to function correctly, but after the main program exited, the process can still be found in processes tab of "Windows Task Manager". Whenever this line is not executed, the problem does not occur.
Is it inappropriate to cancel a thread in this manner?
|
|
|
|
|
1) Do you catch the ThreadAbortException in a loop like that?
try{<br />
for(...){<br />
try{<br />
<br />
}catch{ ... }<br />
}<br />
}catch(ThreadAbortException){ ... }
Then the thread can run for hours without doing anything.
2) You can stop the thread a clean way. Declare a boolean variable, and check it's value in the thread method:
bool threadStopped = false;<br />
...<br />
private void myThreadMethod(){<br />
doSomething();<br />
if(stopped){ return; }<br />
doSomethingElse();<br />
if(stopped){ return; }<br />
doAnything();<br />
if(stopped){ return; }<br />
...<br />
}
With that stop-variable you don't need Thread.Abort() and the try/catch stuff, because the thread stops when you set threadStopped = true .
|
|
|
|
|
I did not catch the ThreadAbortException in a loop and the execution of the tread is actually stoped.
There's still one problem with your codes: what if I want the tread to stop immediately when it is "doing something"?
|
|
|
|
|
Which is better code?
public object GetValue(Hashtable hashtable, object key)
{
if(hashTable == null)throw new ArgumentNullExeption("hashTable");
return hashtable[key];
}
or
public object GetValue(Hashtable hashtable, object key)
{
return hashtable[key];
}
Clearly the second example will throw anyway if the passed hashtable is null.
The first is more explicit if less concise. Is there any difference otherwise?
Any feedback would be appreciated.
Robert Zurer
|
|
|
|
|
For my opinion, the first is getter, you will get a cleaner error message. You should test key also.
If you have fear of the perf hit of such test you can use Debug.Assert from System.Diagnostics
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|
Thank you for your response, (and also for your fine articles).
As to using Debug.Assert, I want the exception to be thrown.
(As to testing key, I may want to return null and let the caller handle that, but this is just a test example anyway.)
Am I right in assuming that the performance hit you are referring to is not the statement
if([ErrorCondition])
but the actual exception which will be thrown?
In that case, the exception would be thrown only once in either case, resulting in equal perfomance hits. Or have I missed something?
Thanks again.
Robert Zurer
|
|
|
|
|
bzurer wrote:
In that case, the exception would be thrown only once in either case, resulting in equal perfomance hits. Or have I missed something?
Totally right, anyway, to my opinion, it is always worth the price to check parameters: write such tests and documented it.
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|
Thanks for you response, (and also for your fine articles).
I want to throw the exception so Debug.Assert wouldn't work here.
I assume that the perfomance hit you are talking about is the actual exception and not the if statement. If I haven't misunderstood, wouldn't one exception be thrown in either case resulting in equal performance hits?
Robert Zurer
|
|
|
|
|
IMO, throw the ArgumentNullException . If you don't, the CLR will throw a NullReferenceException , and those are always annoying because any reference Type throughout the executing code could be null and you'll have to debug to find out which. Throwing the ArgumentNullException exception should make it obvious. Either way, the calling code should catch the exception and display a user-friendly error (though in this example, there's no excuse for an exception being thrown in a release app).
In the base class library assemblies, any params that shouldn't be null are checked in this manner.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Is it possible to have a propety as an array? If so, how do I access it??
I usually create my properties in this manner
class Object{
private string sProperty;
public string Property{
get{return sProperty;}
set{sProperty = value;}
}
Can I do the following, and how do I properly access the array
class Object{
private string[] sProperty;
public string[] Property{
get{return sProperty;}
set{sProperty = value;}
}
|
|
|
|
|
I don't know about string[], but if you use ArrayList like:
private ArrayList alBtnCommands = new ArrayList();
public ArrayList ButtonCommands
{
get
{
return alBtnCommands;
}
set
{
alBtnCommands = value;
}
}
then you can call it by:
currentButton.ButtonCommands.Add(AnItem);
currentButton.ButtonCommands.RemoveAt(i); // i(integer) is an index
SomeThing = currentButton.ButtonCommands[i];
currentButton.ButtonCommands[i] = SomeThing;
It's not what you asked for, but it might be similar for string[]
Hope it helps
Thomas
|
|
|
|
|
Using an IList implementation like the ArrayList isn't always the answer. An array is fixed. Items can't be added or removed. This is often necessary in cases like returning the fonts installed on the system, or returning the printers installed on the system. In these cases, though, the property is read only (only implements the get accessor). If it was a list, developers can easily modify it (without even instantiating a new one) which might corrupt the behavior of the object.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Do it just like you wrote :
<br />
public string[] Property{ <br />
get{return sProperty;}<br />
set{sProperty = value;}<br />
}<br />
and access it like so
<br />
Object o = new Object();<br />
o.Property = new String[] {"foo", "bar"};<br />
Console.WriteLine("{0} {1}", o.Property[0], o.Property[1]);<br />
another trick is to use default properties[^]
write you property like this
<br />
public string this[int index] {<br />
get { return sProperty[index]; }<br />
set { sProperty[index] = value; }<br />
}<br />
and access like this
<br />
Object o = new Object();<br />
o.Property = new String[2];<br />
o[0] = "foo";<br />
o[1] = "bar";<br />
Console.WriteLine("{0} {1}", o[0], o[1]);
HTH
The smaller the mind the greater the conceit.
Aesop
|
|
|
|
|
The cop (FxCop) says do not return array as properties...
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|
Funny, the Cop didnt seem to have a problem with the little snippet I compiled
But if they're the rules fair enough.
Cheers for the info.
The smaller the mind the greater the conceit.
Aesop
|
|
|
|
|
Thanx - this is exactly what I needed.
I only need it because I'm converting some VB code and it does it this way.
What is the FxCop mentioned?
|
|
|
|
|