|
Hi,
I'm trying to make the images in a super slide show to automatically enlarge. Super because I want to control the images with a timer accuracy of 1 millisecond.
So I've got a timer event set up. That changes the image (according to a config file) every x ms.
When the image is shown I want the image to grow larger (including beyond the size of the screen) to create the effect of flying into the image.
I can't get it to work.
Here's the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using Multimedia; //For the MM timer
using System.Windows.Forms;
namespace MyImage
{
public partial class Form1 : Form
{
public delegate void ScaleImageDelegate(); //public delegate void WriteDataDelegate(object sender, EventArgs eArgs);
Multimedia.Timer myTimer = new Multimedia.Timer(); //Define a new 1ms resolution timer
int TimeCounter, ImageCounter;
bool DoScale = false;
Bitmap[] myImage = new Bitmap[10];
string[] ImageName = new string[10];
int[] ImageStart = new int[10];
int[] ImageDuration = new int[10];
int TotalNumberofImages;
float Scaler = 1;
public Form1()
{
InitializeComponent();
myTimer.Mode = TimerMode.Periodic; //Make sure the timer keeps running after the set period
myTimer.Period = 10; //Set the period (when the Event is triggered) to x ms
myTimer.Resolution = 1; //Set the resolution of the timer to 1ms
this.myTimer.Tick += new System.EventHandler(this.myTimer_Tick); //Initialize the EventHandler
GetFiles(); //REad the images in an array for fast display
myTimer.Start(); //Start the timer and thus the Event Handler and do something
TimeCounter = 0; //Reset the timer counter
ImageCounter = 0;
}
void myTimer_Tick(object sender, System.EventArgs args)
{
TimeCounter += 1; //an other 10ms has elapsed
if (TimeCounter * 10 == ImageStart[ImageCounter])
{
pictureBox1.Image = myImage[ImageCounter];
ScaleImage();
}
if (TimeCounter * 10 == ImageStart[ImageCounter] + ImageDuration[ImageCounter])
{
pictureBox1.Image = myImage[4];
ImageCounter += 1;
DoScale = false;
if (ImageCounter > TotalNumberofImages)
{
Application.Exit();
}
}
if (DoScale)
{
ScaleImage();
}
}
void GetFiles()
{
TextReader tr = new StreamReader(@"c:\data\images.dat");
char[] seps = { ';' };
String line;
String[] values;
int i =0;
while ((line = tr.ReadLine()) != null)
{
values = line.Split(seps);
ImageName[i] = values[0];
ImageStart[i] = int.Parse(values[1]);
ImageDuration[i] = int.Parse(values[2]);
i++;
}
TotalNumberofImages = i - 1;
for (i = 0; i <= TotalNumberofImages; i++)
{
myImage[i] = new Bitmap(ImageName[i]);
}
// close the stream
tr.Close();
}
private void ScaleImage()
{
double myWidth, myHeight;
if (InvokeRequired)
{
BeginInvoke(new ScaleImageDelegate(ScaleImage));
return;
}
if (!DoScale)
{
Scaler = 1;
DoScale = true;
}
Scaler += 0.01f;
myWidth = Convert.ToDouble(pictureBox1.Width) * Convert.ToInt32(Scaler);
pictureBox1.Width = Convert.ToInt32(myWidth);
myHeight = Convert.ToDouble(pictureBox1.Height) * Convert.ToInt32(Scaler);
pictureBox1.Height = Convert.ToInt32(myHeight);
}
}
}
THX!
Marco
|
|
|
|
|
I for one cannot be bothered to read all that.
Does your have an error message to go with it?
Or perhaps you could say what it is that doesnt work how you want
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
There is no error. It just does not work.
This is the run down:
1) Show an image full screen every 1 second using a timed event
2) When the image is on screen, enlarge gradually it during that 1 second to 200% (so overflowing the screen). So at 1.5s the image should be at 150%, etc.
What it does do is quit after the first image.
As far as I can see it has something to do with the threading as it finishes the program (stop in the program.cs at the call to Form1) when it checks if (BeginInvoke)...
modified on Friday, February 6, 2009 9:02 AM
|
|
|
|
|
oh, i understood what you want, it just seems you want others to do all the work. you may have posted code but you have no clue as to what is failing.
Im not familiar with the Multimedia.Timer - why not you System.Windows.Forms.Timer?
Also a think you may need to take into account the delay in loading an image every second
maybe you should try loading an image, then starting the timer (set at 10ms or something) then with every tick then you update the size of a bitmap.
Why dont you try using a panel and handle the paint event yourself to do the bitmap drawing, rather than using a picturebox
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
Errr, isn't helping THE idea behind message boards?
The Forms.Timer is not accurate enough. It runs for several ms then hickups about 16ms. The MM timer is the only one I've found that will do the trick.
I avoid the load delay by pre-loading the images in an array.
I have tried timer, image, resize. Didn't work, at least not the way I did it.
Thanks for the Paint event suggestion, I will take another look at it.
|
|
|
|
|
Yes and i like to help, but i dont have the time to evalute all of your code when you dont give specific issues.
m.otte wrote: I avoid the load delay by pre-loading the images in an array.
I beleive you may also get a delay while assigning a picturebox with an image, only small i know, but as your doing a very time-tight operation you want to avoid as much assignment in loops as posible
P.S. thanks for the info on the timer
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
m.otte wrote: What it does do is quit after the first image.
As far as I can see it has something to do with the threading as it finishes the program (stop in the program.cs at the call to Form1) when it checks if (BeginInvoke)...
check the imageCounter is not greater than numOfImages (or what ever check it was that causes application.Exit();
if your thread is failing you wont get debug errors, you need to put debug messages in yourself to test.
Try running it on same thread and see if any error messages
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
It doesn't reach the app.exit! I checked.
Trying to run it in the same thread causes the Cross Thread error to pop up as soon as the execution reaches the size update of the picturebox.
|
|
|
|
|
how can you get a crossthread error if you only using one thread?
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
As far as I understand, the Timer has a thread and the Form has.
I might be wrong, but then I don't know where the other thread comes from.
|
|
|
|
|
As i said i only new the Forms.Timer which the tick event does not cause another thread.
If your timer is having another thread, then you may be getting a cross-thread error you dont know about while using the other thread in your application (as said, errors will not show in thread other than main) does that make sense?
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
|
with a paintEvent method, the timer should set a global scale value, and then call the panel.Invalidate() method
the paint event should, draw the required image using the global scale value and other positioning calculations
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
Mmm, I see. Interesting. Will try it and am curious what it will do to the timing?
Thanks
|
|
|
|
|
Right. If you want specific actions with images, don't rely on PictureBoxes; use some drawing surface and paint the stuff yourself. Panels are ideal for such purposes.
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Friday, February 6, 2009 12:57 PM
modified on Friday, June 10, 2011 11:30 AM
|
|
|
|
|
Thanks for the backup
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|
|
Hi,
almost all asynchronous devices including serial ports, timers, etc. use extra threads. All timers except one (Forms.Timer) tick on a separate thread, and are not suited for directly touching any Control. One either needs Control.InvokeRequired + Control.Invoke, or use Forms.Timer
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Friday, June 10, 2011 11:31 AM
|
|
|
|
|
Hey everybody... I got a question for advanced C# programmers. I've been playing around with type constraints for template classes, and I got stuck.
I used [ and ] instead of < and > for template classes because I wanted to have HTML code for you to see better what code I got.
In the C# 3.0 specification (and I will quote directly from Microsoft's document), it's said that this will work:
class B[T] where T: IEnumerable {...}
class D[T]: B[T] where T: IEnumerable {...}
class E[T]: B[List[T]] {...}
Because (so they say):
"Since type parameters are not inherited, constraints are never inherited either. In the example below, D needs to specify the constraint on its type parameter T so that T satisfies the constraint imposed by the base class B[T]. In contrast, class E need not specify a constraint, because List[T] implements IEnumerable for any T."
Now... I put this pre into VS 2008 and the compiler won't work. My pre:
class B[T] where T : IEnumerable[T] { }
class D[T] : B[T] where T : IEnumerable[T] { }
class E[T] : B[List[T]] { }
Error:
"Error 1 The type 'System.Collections.Generic.List[T]' cannot be used as type parameter 'T' in the generic type or method 'FunFollAdmin.frmMain.B[T]'. There is no implicit reference conversion from 'System.Collections.Generic.List[T]' to 'System.Collections.Generic.IEnumerable[System.Collections.Generic.List[T]]'. D:\Order\A1.FunFoll Administrator [FFA]\2009-01-25\FunFollAdmin\frmMain.cs 46 10 FunFollAdmin"
Even more......... not even this works:
B[test] test = new B[test]();
Error:
"Error 1 The type 'FunFollAdmin.frmMain.test' cannot be used as type parameter 'T' in the generic type or method 'FunFollAdmin.frmMain.B[T]'. There is no implicit reference conversion from 'FunFollAdmin.frmMain.test' to 'System.Collections.Generic.IEnumerable[FunFollAdmin.frmMain.test]'. D:\Order\A1.FunFoll Administrator [FFA]\2009-01-25\FunFollAdmin\frmMain.cs 216 9 FunFollAdmin
Error 2 The type 'FunFollAdmin.frmMain.test' cannot be used as type parameter 'T' in the generic type or method 'FunFollAdmin.frmMain.B[T]'. There is no implicit reference conversion from 'FunFollAdmin.frmMain.test' to 'System.Collections.Generic.IEnumerable[FunFollAdmin.frmMain.test]'. D:\Order\A1.FunFoll Administrator [FFA]\2009-01-25\FunFollAdmin\frmMain.cs 216 28 FunFollAdmin"
Even though I have implemented the class test correctly:
class test : IEnumerable[int]
{
public test () { }
#region IEnumerable[int] Members
public IEnumerator[int] GetEnumerator ()
{
throw new NotImplementedException();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
throw new NotImplementedException();
}
#endregion
}
|
|
|
|
|
The compiler is right. You wrote where T : IEnumerable[T] : this means that T must be an enumeration of itself!
Note that the MSDN sample uses the non-generic version of IEnumerable (where T : IEnumerable ), meaning that T can be any enumeration.
modified on Friday, February 6, 2009 10:10 AM
|
|
|
|
|
Note that the MSDN sample uses the non-generic version of IEnumerable (where T : IEnumerable[T]), meaning that T can be any enumeration.
You mean where T : IEnumerable
Ok but how do you declare it so? Because if I declare it so, it says
Error 1 Using the generic type 'System.Collections.Generic.IEnumerable<t>' requires '1' type arguments D:\Order\A1.FunFoll Administrator [FFA]\2009-01-25\FunFollAdmin\frmMain.cs 48 33 FunFollAdmin</t>
I used the code directly from MSDN
interface IMyInterface<br />
{<br />
}<br />
<br />
class Dictionary[TKey, TVal]<br />
where TKey : IComparable, IEnumerable<br />
where TVal : IMyInterface<br />
{<br />
public void Add (TKey key, TVal val)<br />
{<br />
}<br />
}
Same error as above!!! I don't get it! Oh boy......... ::- (
Error 1 Using the generic type 'System.Collections.Generic.IEnumerable<t>' requires '1' type arguments D:\Order\A1.FunFoll Administrator [FFA]\2009-01-25\FunFollAdmin\frmMain.cs 48 33 FunFollAdmin</t>
|
|
|
|
|
You mean <code>where T : IEnumerable</code> Yes, I mistyped. Corrected now.
You must add using System.Collections in order to use the non-generic version of IEnumerable (or you use its full name: where T : System.Collections.IEnumerable ).
|
|
|
|
|
Ah, damn. I had using System.Collections.Generic; but not using System.Collections;
Thank you Mirko! ::- )
That fixed it.
|
|
|
|
|
You welcome
|
|
|
|
|
hi friends
i want to implement a logic .. string input will be given...it should merge only single characters..pls help
eg.. behind r m d street
o/p expected is behind rmd street
any body help me out with apt logic......
the quieter u become more u hear
|
|
|
|
|
how bout a function along the lines of the following
string MergeFunction(string value)
{
result = value;
for(int i = 0; i < value.length; i++)
{
if(value[i-1] == ' ' && value[i+1] == ' ')
{
result = result.remove(i+1, 1);
}
}
return result;
}
dont forget you also need to include some check for handling if i == 0; or i == value.length -1;
because it will throw a index out of bounds error as it is.
EDIT: oops you will need some sort of count for the number of spaces currently remove so you can subtract it from the value when using result.remove
result.remove(i+1-count, 1);
My opinion is... If someone has already posted an answer, dont post the SAME answer
|
|
|
|