change c# form application width in left direction - c#

So I wanted to change my form size on a button click and also wanted it to look like a little animation so this code help me
while (desiredWidht < this.Width)
{
this.Width += 5;
Thread.Sleep(4);
}
but there is one problem. this code expands form in right direction. how can I do the same thing in left direction.. I tried expanding the form then moving it left and moving all controls to the right but the problem was that after form reached certain width controls disappeared for some reason and when the expansion method was done they appeared back again. I cannot figure out what is the problem. What is the proper way I do this.

Try -
this.Refresh();
after moving the controls.

const int MAX_STEP = 5;
while (Width < desiredWidth)
{
int step = Math.Min(MAX_STEP, desiredWidth - Width);
SetBounds(Left - step, Top, Width + step, Height);
Refresh();
Application.DoEvents();
Thread.Sleep(4);
}
Here I've done a couple of things, first was defining a maximum step and setting the step so you'll get the exact width you desire. The big change here from the over answer was the SetBounds which will set all the properties atomically, I didn't have anything else going on in my sample program so I was seeing the right side gitter back and form as I was setting the width then the left (previously when testing a solution). You probably have this in some other process so you'll need to raise the event Application.DoEvents() and like mentioned by #banana you can do a Refresh(), that should be automatically called but it shouldn't hurt calling it again.
Also, I spelled Width correctly in desiredWidth, it was driving me crazy!
The "this.Property" or "this.Method" is a redundant qualifier of "this" so I've removed it from my example.
**Note, look into ClientSize.Width as it is typically what people want, you may want to also look to SetDesktopBounds

Related

How to move around a UI element during run-time?

I require to move around a button UI element during runtime via code. How can I accomplish this?
The button UI element has these following properties:
Layout
- Width
- Height
- Left
- Top
- Margin (Left, Right, Top, Bottom)
I require to change is the Layout->Left and Layout->Right during runtime.
When I googled for it, I mostly found information on altering the Margin, and not the Left and Top values. Please guide me. I expect it's a standard question, unfortunately I have been unable to find the answer to it.
Canvas.Left and Canvas.Top are attached properties, they are set in a slightly different way than ordinary properties.
The "standard" way is to use the .SetValue method:
buttonPlayTrailer.SetValue(Canvas.LeftProperty, 500);
Another way is to use the Canvas.SetLeft and Canvas.SetTop methods (it will have the exact same result, it's just more convenient):
Canvas.SetLeft(buttonPlayTrailer, 500);
private void MoveButton(int leftOffset,int topoffset)
{
Canvas.SetLeft(buttonPlayTrailer,leftOffset);
Canvas.SetTop(buttonPlayTrailer,topoffset);
}
something like that?

How can I predict a XAML Label's height on a Canvas

I have an application where I need to dynamically build the content to a Canvas. Everything works just fine, but I am a little unsure of how I can set the y coordinates for the labels in the safest way. For example, I need to add three labels that are essentially lines of text. In Java Swing or C# GDI I would just query the the font for the line height and add that value to the y coordinate of the drawText command.
This is my code.
double y = 0.0;
_line1.Content = "Line1";
_line1.SetValue(Canvas.TopProperty, y);
_line1.SetValue(Canvas.LeftProperty, 0.0);
CanvasChart.Children.Add(_line1);
double textHeight = _line1.Height;
y += textHeight;
_line2.Content = "Line2";
_line2.SetValue(Canvas.TopProperty, 0.0);
_line2.SetValue(Canvas.LeftProperty, y);
CanvasChart.Children.Add(_line2);
This does not work because _line1.Height does not seem to be set to anything useful at this point. I suppose it has not rendered yet. The above code is in the loaded event for the window. ActualHeight does not help either.
Most code that I've seen seems to just set them to a hard coded value. That I suppose looks right on the developer's display, and you just hope looks good at other resolutions/DPI. In Swing and GDI I always had the best results finding out exactly how many pixels a string will be rendered at and using this to offset the next line.
You must call the Measure method, specifying an infinite available size. This will update the DesiredSize of the control:
_line1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
double textHeight = _line1.DesiredSize.Height;
Another easy way to achieve the desired effect is to put the labels in a StackPanel.
In Swing and GDI I always had the best results finding out exactly how many pixels a string will be rendered at and using this to offset the next line.
This is possible in WPF as well. The GlyphTypeface class provides the AdvanceWidths and AdvanceHeights properties for each character in a typeface. By using CharacterToGlyphMap, you can map a character to an index within the AdvanceHeights, and use that to determine the actual height of any character.
For a detailed example, see GlyphRun and So Forth.

Text-relative Adornments in VS2010: they are SOMETIMES displayed at incorrect positions

You are my only hope. I have searched everywhere and just can't find anything that could help me with this one.
I've done a simple code marking plugin for Visual Studio (2010). It just finds some parts of code to highlight (by Regex), creates Spans out of the matches found and then creates Rectangle adornments for them (in the background of the text), that scroll with the text. All of this is done in view.LayoutChanged event's implementation. It works fine... but... NOT EVERY TIME! Sometimes the markers get moved by various distances (mostly up or down) and then just keep these incorrect positions while the text is scrolled. I have no idea why and WHEN this happens. I was able to discover only these few things:
you can reproduce this bug (move some markers from their correct positions) by dragging the vertical scrollbar of the code editor window very fast and agresively up and down (but sometimes it also fixes the positions...)
you cannot fix a marker's position by editing the line on which it is placed (or even the marked text)
you can fix the marker's position by deleting and restoring the ending "}" of the code block in which the marked code is placed (which causes the whole block of code to be reformatted)
the view.ViewportTop is negative when the positions are calculated incorrectly (view is a WpfTextView class) and the Geometry "g" (see below) is getting the negative Bounds.Top too. (You can test it by attaching one VS to another and set a breakpoint)
Here is the piece of my code that calculates the positions and creates the markers (LayoutChanged event):
Geometry g = textViewLines.GetMarkerGeometry(span);
if (g != null)
{
GeometryDrawing drawing = new GeometryDrawing(_brush, _pen, g);
drawing.Freeze();
DrawingImage drawingImage = new DrawingImage(drawing);
drawingImage.Freeze();
Image image = new Image();
image.Source = drawingImage;
//Align the image with the top of the bounds of the text geometry
Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);
//_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, image, null);
Rect rect = new Rect(g.Bounds.Location, g.Bounds.Size);
Rectangle marker = new Rectangle();
marker.Margin = new Thickness(rect.X - 3, rect.Y - 2, 0, 0);
marker.Width = rect.Width + 6; marker.Height = rect.Height + 4;
marker.Fill = new SolidColorBrush(mark);
marker.RadiusX = marker.RadiusY = 5;
marker.Stroke = new SolidColorBrush(color);
_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, marker, null);
}
This is basically the MSDN example for creating adornments, I'm not doing any magic here.
Please help!
I had the same problem. If you use
_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative,...);
more then once you have to insert
Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);
every time before.
I've just spent the whole day on similar issue.
There're a lot of undocumented corner cases besides span moving issue. Even worse, seems-to-be-proven solution tend to break in never VS version (especially, starting with roslyn and VS2015). My favorite one was the following: the adornments were removed occasionally if you press enter multiple times inside a multiline comment. Hilarious!
So, the only working approach is the following: don't try to outsmart VS editor, it'll fool you anyway.
Instead, borrow the code from the roslyn's AdornmentManager<T>. It contains a lot of hacks I had to reinvent and even more I didn't ever suspect about, but it works. All you need to do is replace the code below
// add the visual to the adornment layer.
with yours one (the part is a good candidate to refactor into overridable method).
P.S. I know that I'm slightly late :) Hope this will save some time to another poor soul.

Showing and hiding parts of winforms (extending?) C# .NET

I have a question about forms and controls. I want to add the ability to sort of make a part of my form only show when something is clicked. For example I have form1 and on the form i have a button and when that button is clicked the form grows or extends (slides out?) to show other controls that werent there before the button was clicked. I have no idea what this is called so I don't know what to look for but Ive seen it used in many other applications. Any information on this would be greatly appreciated.
You'd probably have to roll your own animation, increasing the size dimensions of your form (or panel, or whatever) on a timer, thereby exposing the previously hidden controls.
Timer T = new Timer();
T.Interval = 10;
T.Tick += (s, e) =>
{
myForm.Size = new System.Drawing.Size(myForm.Width + 10, myForm.Height);
if (myForm.Size.Width >= FormWidthThreashold)
T.Stop();
};
T.Start();
At the risk of stating the obvious, I don't suppose there's any way to switch the WPF? This stuff is built in, and quite easy for WPF. If not though, something like this should get you started.
I've done this before. Start by organising your form into logical sections. Don't leave all your controls on the form, place them inside panels. At Design-time you'll need to have the panels "fully expanded", but then at runtime you manipulate the panels' left, top, width, height, and maybe even the alignment and anchors properties, through code. You could use a timer as suggested by #Adam Rackis.. or you could change the increment value to alter the speed of the animation. The animation itself is just a loop that starts with x = x1 and ends with x = x2, where x = x + increment_value inside the loop. As the value of "x" changes, the component will be automatically redrawn. To get a smoother effect you might need to repaint the control (or the entire panel) on each iteration. If it runs too fast, you can either insert a delay or try to make the loop rely on a timer. I've had problems with timers for this kind of stuff, but admittedly I wasn't using C#.NET at the time (I did it in Delphi). It takes a lot of fiddling with the fine details to get this working nicely, so be patient, it's not Flash! Good luck.

Resizing a grid control programatically over a period of time

G'day,
I am attempting to simulate the old XBox 360 GUI with the sliding tabs (Remember, you'd press left or right and the content would slide in depending on the tab?) Anyways, at the moment, I have this working well, however I cannot get the "animation" working.
When the user presses left arrow or right arrow, my OpenWindow(int iIndex) method will be called, where iIndex is the index to the next or previous "window" to be slid in. (Not a window... each "Window" is a struct with a parent grid control containing a button and a smaller grid control that contains the windows contents.)
Now, my problem lies with resizing the parent grid control. When it is slid in, it is resized by calling mygrid.Width += 1; That works, but I don't see it happen over a determined period of time, it just lags a bit and then resizes to the required width. Whereas if I call this.Width += 1 in the same method, (this being the main program window) the window resizes how I want the grid control to resize. I've tried UpdateLayout() but to no avail. This tells me my timing is okay.
If anyone could be of assistance, it would be greatly appreciated.
Here is my OpenWindow method...
public void OpenWindow(int iIndex)
{
int iInterval = 1;
for (int i = (int)myDict[iIndex].Shell.Width; i < (int)stack_outter.Width; i += iInterval)
{
myDict[iIndex].Shell.Width += 1;
myDict[iIndex].Shell.UpdateLayout();
System.Threading.Thread.Sleep(1);
}
myDict[iIndex].Shell.Width = stack_outter.Width - (BUTTON_WIDTH * (myDict.Count - 1));
}
myDict is a Dictionary, Shell is the grid that I am attempting to animate when resizing. Sorry about the code, it's messy, my code is always hacked when I am trying to get stuff working :)
Thanks,
Ash
Neried Web Solutions
Your OpenWindow method is happening on the Dispatcher thread. That's also the thread responsible for rendering, so as long as your OpenWindow method doesn't return, nothing gets rendered.
The proper way to fix this would be to animate the Width property. I don't have any experience in starting animations from code (I've only used them in the past for things like a fade-in button highlight on mouse over, which is more easily done from WPF), but I took a quick read-through this page, Animation Overview on MSDN, and I think you'll want something like this:
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = myDict[iIndex].Shell.Width;
myDoubleAnimation.To = stack_outter.Width;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
myDoubleAnimation.AutoReverse = false;
myDoubleAnimation.RepeatBehavior = new RepeatBehavior(1.0);
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTarget(myDoubleAnimation, myDict[iIndex].Shell);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(FrameworkElement.WidthProperty));
myStoryboard.Begin(myDict[iIndex].Shell);

Categories

Resources