C# COM Interop and Application.DoEvents() - com

I found the following code and am trying to implement it in a COM module:
public Bitmap GetThumbnail()
{
ThreadStart _threadstart = new ThreadStart(GenerateThumbnail);
Thread _thread = new Thread(_threadstart);
_thread.SetApartmentState(ApartmentState.STA);
_thread.Start();
_thread.Join();
return _image;
}
private void GenerateThumbnail()
{
WebBrowser _browser = new WebBrowser();
_browser.ScrollBarsEnabled = false;
_browser.ScriptErrorsSuppressed = true;
_browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(_browser_DocumentCompleted);
_browser.Navigate(_url);
while (_browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
_browser.Dispose();
}
void _browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser _browser = (WebBrowser)sender;
_browser.ClientSize = new Size(this._pagewidth, this._pageheight);
_browser.ScrollBarsEnabled = false;
_image = new Bitmap(_browser.Bounds.Width, _browser.Bounds.Height);
_browser.BringToFront();
_browser.DrawToBitmap(_image, _browser.Bounds);
if (_imageheight != 0 && _imagewidth != 0)
_image = (Bitmap)_image.GetThumbnailImage(_imagewidth, _imageheight, null, IntPtr.Zero);
}
However, I've discovered that the Application.DoEvents() and COM do not work together. The code works great in a C# application, but it hangs when called via COM. As you can tell, I'm trying to get a website thumbnail, and I can't seem to figure out a substitute for the DoEvents().
Any suggestions?
Thanks,
Kevin

Related

PushStreamContent in asp.net core - video start playing only when whole file is buffered

i have problem with PushStreamContent in asp.net core.
It display video on the website but my problem is that it will buffer whole file and then play it when my goal is to buffer small part of it and play on the website. Code i have:
My endpoint for playing video in browser
public IActionResult Play(string file)
{
var fileName = "C:\\repo\\trailer1.mp4";
var video = new VideoStream(fileName);
var response = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue("video/mp4"))
{
};
var objectResult = new ObjectResult(response);
objectResult.ContentTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("video/mp4"));
return objectResult;
}
Ive got VideoStreamClass to help with displaying video
public class VideoStream
{
private readonly string _filename;
public VideoStream(string filename)
{
_filename = #"C:\\repo\\trailer1.mp4";
}
public async Task WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
try
{
var buffer = new byte[65536];
using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read))
{
var length = (int)video.Length;
var bytesRead = 1;
while (length > 0 && bytesRead > 0)
{
bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
await outputStream.WriteAsync(buffer, 0, bytesRead);
await outputStream.FlushAsync();
length -= bytesRead;
}
}
}
catch (Exception)
{ return; }
finally
{
outputStream.Dispose();
}
}
}
And here is my VideoOutputFormatter added to bootstraper
public class VideoOutputFormatter : IOutputFormatter
{
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (context.Object is PushStreamContent)
return true;
return false;
}
public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
using (var stream = ((PushStreamContent)context.Object))
{
var response = context.HttpContext.Response;
if (context.ContentType != null)
{
response.ContentType = context.ContentType.ToString();
}
await stream.CopyToAsync(response.Body);
}
}
}
I've tried to add atributes to controller "UseBufferedOutputStream" and "UseBufferedInputStream" setted to false but this still dosent work for me
ObjectResult is intended for holding an in-memory object as a response. If you want to return an existing file, then PhysicalFileResult is probably your best bet.
If you're interested in PushStreamContent, I believe the one you're using is for HttpClient, not ASP.NET. If you want a PushStreamContent equivalent, I have a FileCallbackResult that would work once it's updated for the latest .NET Core.

How to set image.Source via async stream in an UWP application?

I want to set image.Source via async stream in an UWP application. Otherwise the image will flicker when switch to other image source.
My code is as below. And the log shows it works. Certainly I put 2 image files in the corresponding path before I test the demo code.
But in fact I did not see any picture shown, why?
Log:
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444
Code:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
Debug.WriteLine("111111111111 image file path = " + imageFilePath);
Stream fileStream = await sFile.OpenStreamForReadAsync();
Debug.WriteLine("22222222222");
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
Debug.WriteLine("33333333333333");
await fileStream.CopyToAsync(ras.AsStreamForRead());
Debug.WriteLine("4444444444444");
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
image1.Source = bi;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/1.jpg"));
}
else
{
setImageSource(fullFolder + #"\2.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/2.jpg"));
}
count++;
}
Here is an example of how I convert a base64 image string to a BitmapImage..
var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;
Try some of the things I'm doing there. Like I notice your code is not setting the seek of the InMemoryReadAccessStream
For your question, I have something to clarify with you.
Your pictures are always in the application data folder. If you want to show it at runtime by programming, the easy way is using the ms-appdata URI scheme to refer to files that come from the app's local, roaming, and temporary data folders. Then, you could use this URL to initialize the BitmapImage object. With this way, you don't need to manually manipulate the file stream.
private void setImageSource(int i)
{
BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
image1.Source = bi;
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (count % 2 == 1)
{
setImageSource(1);
}
else
{
setImageSource(2);
}
count++;
}
If you say you have to manipulate the file stream to initialize the BitmaImage, then please add some break points to debug your code. If you add break points to check the InMemoryRandomAccessStream after call CopyToAsync method, you will see that its size is 0. It meant that the file stream has not been wrote to it. To solve this issue, you need to set a buffer size for it. Note: you used ras.AsStreamForRead() method, it's incorrect. You're writing stream to it, so you need to call ras.AsStreamForWrite().
The code looks like the following:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
using (Stream fileStream = await sFile.OpenStreamForReadAsync())
{
using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
{
await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
ras.Seek(0);
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
img.Source = bi;
}
}
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
}
else
{
setImageSource(fullFolder + #"\2.jpg");
}
count++;
}
In addition, like #visc said, you need to call ras.Seek(0) method to reset the stream to beginning, else the image will not show there.

Trying to stop SpeechSynthesizer in uwp on click of a button

I'm trying to stop SpeechSynthesizer in uwp on click of a button and also trying to start SpeechSynthesizer on clicking same icon again.Any Help would be appreciated for resolution of this issue.
XAML
<Image x:Name="Sound" Source="ABCD/sound_active.png"
RelativePanel.AlignBottomWithPanel="True"
RelativePanel.RightOf="Pause" Tapped="SoundTap"
Margin="17,0,0,0"
Width="40" Height="40"/>
C# code
private void SoundTap(object sender, TappedRoutedEventArgs e)
{
if ((Sound.Source as BitmapImage).UriSource == new Uri("ms-appx:///ABCD/Sound_active.png", UriKind.Absolute))
{
Sound.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Sound_mute.png"));
textToSpeech.Stop();
}
else
{
Sound.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Sound_active.png"));
textToSpeech.Play();
}
}
public async void Prevevent(object sender, TappedRoutedEventArgs e)
{
currentIndex--;
if (currentIndex < 0)
{
currentIndex = 0;
return;
}
Alph_cap.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Cap_alpha/Cap_" + currentIndex + ".png"));
Alph_small.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Cap_alpha/Sml_" + currentIndex + ".png"));
CapAlphaName.Text = CapsAlpha[currentIndex];
SmallAlphaName.Text = SmallAlpha[currentIndex];
var speechText = this.CapAlphaName.Text;
if (speechText != "")
{
var synth = new SpeechSynthesizer();
var speechStream =await synth.SynthesizeTextToStreamAsync(speechText);
this.textToSpeech.AutoPlay = true;
this.textToSpeech.SetSource(speechStream, speechStream.ContentType);
this.textToSpeech.Play();
}
}
Understanding the question:
Basically you're looking for a toggle switch to turn on and turn off the speech synthesis tts(Text to Speech) in simpler terms.
The Solution:
This couldn't have been simpler enough, never the less, this is how you do it.
Create a Bool property, eg: private IsTTSEnabled = false we'll use this as a flag.
On your Image tap or click, check the current value of IsTTSEnabled and flip it (false if true or true if false) eg: IsTTSEnable = !IsTTSEnable;
Now put a if loop for handling if the TTS is turned on or if it's turned off. Also, since TTS is done using a media element, you don't need to reInitialize your TTS, simple pause and play your media element or start and Stop it as per needs.
So your c# code becomes:
private bool IsTTSEnabled = false;
private void SoundTap(object sender, TappedRoutedEventArgs e)
{
IsTTSEnabled = !IsTTSEnabled;
if(IsTTSEnabled)
{
Sound.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Sound_mute.png"));
textToSpeech.Stop();
}
else
{
Sound.Source = new BitmapImage(new Uri("ms-appx:///ABCD/Sound_active.png"));
textToSpeech.Play();
}
}
Note: This functionality can be easily implemented using Data Binding to provide scalability and ease of management but then the simpler way to do so is like the one I've illustrated

C# Web Cam with Remoting

My project is about Remoting and i want to add a webcam component to it. Here it goes: I have 3 project in my solution... Client, Server, Remote.dll. In Remote.dll is a common class which has methods works in server machine. When i call these methods from Client it executes in server side. So now my question is i put the code of Webcam in remote.dll and it has an event called "video_NewFrame" which it works everytime when webcam catch an image. But i cant reach to the images from my Client side because when code drops to this event it executes infinitely
and my timer in Client side doesnt work as well. I tried to assing image to my global variable but whenever code goes to client and comes to Remote.dll again my variable is null...
How can i reach simultaneously captured images from my client? here is my code:
(i use AForge framework for webcam)
private bool DeviceExist = true;
private FilterInfoCollection videoDevices;
private VideoCaptureDevice videoSource = null;
public bool WebCamStart(int DeviceIndex)
{
if (DeviceExist)
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//string myDevice = videoDevices[0].Name;
videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
CloseVideoSource();
videoSource.DesiredFrameSize = new Size(640, 480);
//videoSource.DesiredFrameRate = 10;
videoSource.Start();
return true;
}
else return false;
}
public Bitmap lastImg;
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap img = (Bitmap)eventArgs.Frame.Clone();
//in executes infinitely when execution comes here and i cant reach from Cliend side...
}
public string getFPS()
{
return videoSource.FramesReceived.ToString();
}
public void CloseVideoSource()
{
if (!(videoSource == null))
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource.Stop();
videoSource = null;
}
}
public string getCamList()
{
string result = "No Device Found";
try
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//comboBox1.Items.Clear();
if (videoDevices.Count == 0)
throw new ApplicationException();
DeviceExist = true;
foreach (FilterInfo device in videoDevices)
{
//comboBox1.Items.Add(device.Name);
result = device.Name;
return result;
}
//comboBox1.SelectedIndex = 0; //make dafault to first cam
}
catch (ApplicationException)
{
DeviceExist = false;
//comboBox1.Items.Add("No capture device on your system");
return "No capture device on your system";
}
return result;
}
// and my client side...
private void timerWebCam_Tick(object sender, EventArgs e)
{
//lblFPS.Text ="Device Running... " + remObj.getFPS() + " FPS";
pictureBox1.Image = remObj.lastImg;
}

Implementation of simple Java IDE using Runtime Process and JTextArea

I am developing a simple Java IDE like Netbeans/Eclipse. My GUI includes two JTextArea component, one used as a TextEditor where the end user can type in his programs and the other used as an output window.
I am running the users programs by invoking the windows command prompt through Java Runtime and Process classes. I am also catching the IO streams of the process using the methods getInputStream(), getErrorStream(), getOutputStream().
If the program contains only the statements to print something onto the screen, I am able to display the output on the output window(JTextArea). But if it includes statements to read input from the user, then it must be possible for the user to type the expected input value via the output window and it must be sent to the process just as in Netbeans/Eclipse.
I also checked the following link
java: work with stdin/stdout of process in same time
Using this code, I am able to display only the statements waiting for input and not simple output statements. Also, only a single line is displayed on the output window at a time.
It would be great if anybody can help me to resolve this issue.
Thanks
Haleema
I've found the solution with little modification to the earlier post java: work with stdin/stdout of process in same time
class RunFile implements Runnable{
public Thread program = null;
public Process process = null;
private JTextArea console;
private String fn;
public RunFile(JTextArea cons,String filename){
console = cons;
fn=filename;
program = new Thread(this);
program.start();
}
#Override
public void run() {
try {
String commandj[] = new String[4];
commandj[0] = "cmd";
commandj[1]="/C";
commandj[2]="java";
commandj[3] = fn;
String envp[] = new String[1];
envp[0]="path=C:/Program Files (x86)/Java/jdk1.6.0/bin";
File dir = new File("Path to File");
Runtime rt = Runtime.getRuntime();
process = rt.exec(commandj,envp,dir);
ReadStdout read = new ReadStdout(process,console);
WriteStdin write = new WriteStdin(process, console);
int x=process.waitFor();
console.append("\nExit value: " + process.exitValue() + "\n");
}
catch (InterruptedException e) {}
catch (IOException e1) {}
}
}
class WriteStdin implements Runnable{
private Process process = null;
private JTextArea console = null;
public Thread write = null;
private String input = null;
private BufferedWriter writer = null;
public WriteStdin(Process p, JTextArea t){
process = p;
console = t;
writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
write = new Thread(this);
write.start();
console.addKeyListener(new java.awt.event.KeyAdapter() {
#Override
public void keyTyped(java.awt.event.KeyEvent e){
//save the last lines for console to variable input
if(e.getKeyChar() == '\n'){
try {
int line = console.getLineCount() -2;
int start = console.getLineStartOffset(line);
int end = console.getLineEndOffset(line);
input = console.getText(start, end - start);
write.resume();
} catch (BadLocationException e1) {}
}
}
});
console.addCaretListener(new javax.swing.event.CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
console.setCaretPosition(console.getDocument().getLength());
throw new UnsupportedOperationException("Not supported yet.");
}
});
console.addFocusListener(new java.awt.event.FocusAdapter() {
#Override
public void focusGained(java.awt.event.FocusEvent e)
{
console.setCaretPosition(console.getDocument().getLength());
}
});
}
#Override
public void run(){
write.suspend();
while(true){
try {
//send variable input in stdin of process
writer.write(input);
writer.flush();
} catch (IOException e) {}
write.suspend();
}
}
}
class ReadStdout implements Runnable{
public Thread read = null;
private BufferedReader reader = null;
private Process process = null;
private JTextArea console = null;
public ReadStdout(Process p,JTextArea t){
process = p;
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
console = t;
read = new Thread(this);
read.start();
}
public void run() {
String line;
try {
while((line = reader.readLine())!=null)
console.append(line+"\n");
}catch (IOException e) {}
}
}