|
Thanks, I'll have a go at it.
Everything makes sense in someone's mind
|
|
|
|
|
Ok, I've coded it.
What should be happening when I run this?
Everything makes sense in someone's mind
|
|
|
|
|
When I run it on my system it
1. retrieves the original volume
2. then changes it and retrieves it agin to show it is changed.
3. It then sets it back to the original and retrieves it again to it has been changed back.
If you remove step 3 it should remain changed to whatever you set it to in 2. Check out the code in Test.Run() , I have commented it all.
|
|
|
|
|
Ok, that's what I figred should be happening.
I'm listening to music right now via headphones. When I run this, the sound level doesn't change.
Everything makes sense in someone's mind
|
|
|
|
|
I haven't actually tested it with audio - just the values from GetVolume so I see that the driver has responded. There could be one of two things here...
1. The device ID needs to be the correct one for the device who's volume you want to adjust - I'm not sure without further research how to determine the correct ID for the main audio out device/master
2. Maybe the API only adjusts the volume for the audio stream you play directly - unlikely though.
Edit: you can use waveOutGetNumDevs to get the number of devices and waveOutGetDevCaps in conjuction with WAVEOUTCAPS to get the correct device. Check out this[^] page. If you can't resolve this, let me know and I'll have another look tomorrow, bedtime for me here in the UK - good luck!
|
|
|
|
|
Are you using Vista or Windows 7? If so, this[^] may explain why it's not working and a possible workaround?
Edit: Tested demo app and it works!
|
|
|
|
|
Yes, I'm Windows 7.
This app worked. Thank you
Everything makes sense in someone's mind
|
|
|
|
|
If the above doesn't help - a search for Audio Mixer C# yielded this[^] - looks good...
|
|
|
|
|
I saw that but it looked far more comples than I wanted to get into just for setting the master volume. But hey, I might have to go there at some point.
Everything makes sense in someone's mind
|
|
|
|
|
Ok so I seem to have my backgroundWorkers worked out. However I can't figure out how to report progress back to the original form. I'll try to pice together the code to have this make sense. FYI I don't have anything in the progressUpdated even yet.
namespace MailTest
{
public partial class Form1 : Form
{
List<BGW> BGWs = new List<BGW>();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 3; i++)
{
BGWs.Add(new BGW());
BGWs[i].ProgressChanged += BGW_ProgressChanged;
BGWs[i].RunWorkerCompleted += BGW_WorkerCompleted;
}
btnGetMessageInfo.Enabled = false;
}
void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
BGW bgw = (BGW)sender;
}
void BGW_WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BGW bgw = (BGW)sender;
}
class BGW : BackgroundWorker
{
public BGW()
{
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = true;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
base.OnDoWork(e);
WriteMail.WriteAndParseMail();
}
}
private void btnGetMessageInfo_Click(object sender, EventArgs e)
{
processNumberOfWorkers.howMayWorkers();
MessageBox.Show("There are " + GlobalVars.intHowManyWorkers + " workers needed!");
btnGetMessageInfo.Enabled = false;
backgroundWorker2.RunWorkerAsync();
BGWs[0].RunWorkerAsync();
}
class WriteMail
{
public static void WriteAndParseMail()
{
int intEmail;
bool bolSrvMsg;
string txtLogString = null;
TcpClient tcpClient = new TcpClient();
if (percentComplete <= highestPercentageReached)
{
if (percentComplete == 0)
{
percentComplete = 1;
}
highestPercentageReached = percentComplete + 1;
string strCounter = currentMail + " of " + intEmail;
}
I know I'm probably missing something obvious but still new to backgroundWorkers in C# and not seeing many examples for doing this from a class. When I do it from the main form with a different backgroundWorker it works fine, but when I changed it to this "type" it didn't like the function on the same class so I had to create a new one (which I wanted to do anyways).
Thanks in advance!!!!
|
|
|
|
|
MacRaider4 wrote: I'm probably missing something obvious
For some obscure reason there is a BackgroundWorker.WorkerReportsProgress property, and in good Microsoft tradition its default value is the least useful one.
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
I thought the only two choices for that are true and false? which I have in :
public BGW()
{
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = true;
}
is this where I get a lot of snickering behind my back
|
|
|
|
|
Sorry, I initially didn't read all your code, I just reported the most likely oversight.
I looked through your code now, and I would say:
1. your ReportProgress method should get called, however it is empty. What makes you say it doesn't work?
2. your Mail stuff is static, having multiple BGW's active in WriteAndParseMail() is not safe, it requires data synchronization.
3. I'm not sure you can have multiple TcpClient instances operating concurrently like that.
4. your percentage stuff is incomplete, so I can't be sure it is correct.
5. for overall progress, I often use a timer (Windows.Forms.Timer) which just gathers the number and updates the GUI at fixed intervals, say once a second. That turns out to be easier than having to check for actual percentage changes (which is however more economical).
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
When I use the hard coded version I have:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbWrite.Value = e.ProgressPercentage;
lblCurrentCount.Text = e.UserState.ToString();
}
Of which does work (when it's not calling from the class), sorry I should have included that.
What makes me say it doesn't work is when I uncomment that section of code out I get a error saying it's not in the current context.
I have had 2 TcpClients running at the same time, so that doesn't seem to be a issue.
Is this what you mean by percentage stuff being incomplete?
percentComplete = (int)((float)currentMail / (float)intEmail * 100);
if (percentComplete <= highestPercentageReached)
{
if (percentComplete == 0)
{
percentComplete = 1;
}
highestPercentageReached = percentComplete + 1;
string strCounter = currentMail + " of " + intEmail;
BGWs[0].ReportProgress(percentComplete, strCounter);
}
|
|
|
|
|
Easy... Your BGWs are defined in Form1, while you're trying to access them from within WriteMail.
I would suggest adding a "sender" parameter to WriteAndParseMail(), so you can pass the worker into it.
protected override void OnDoWork(DoWorkEventArgs e)
{
base.OnDoWork(e);
WriteMail.WriteAndParseMail(this);
}
And in the worker thread...
highestPercentageReached = percentComplete + 1;
string strCounter = currentMail + " of " + intEmail;
(sender as BackgroundWorker).ReportProgress(percentComplete, strCounter);
|
|
|
|
|
I tried that but no luck, though I'm sure it's me. This was so much easier in VB...
|
|
|
|
|
Oh, ya know what... I wonder if the BackgroundWorker only allows ReportProgress to be called during the DoWork... Technically, your routine is running AFTER DoWork completes... I really don't think it's intended to be run that way.
The standard way to use a BackgroundWorker is to hook the DoWork EVENT, and put your code there. No need to subclass it, unless you really want to centralize those two boolean property settings.
Just guessing here, of course... I've never seen the BW subclassed... Never had any need to do that.
|
|
|
|
|
Ok I've been doing some more reading, would this be better using a "thread" vs a BGW? Now granted I don't need to put this in a seperate class, however for what ever reason when I use BGWs[0].RunWorkerAsync(); vs backgroundWorker1.RunWorkerAsync(); I'm not able to have the "function" in the same class (the Form) thus why I moved it to a seperate class. Plus when I was getting into more advanced someone reccomended keeping as little as you can on your main form and using classes for as much as possible. Is this a good habbit, bad habbit or just personal preference? Where I work there are two of us, and he does all the C++ stuff and I do the VB (6+ years, though .net in only the last year) and just starting with C# (about 6 months ago).
I have been able to subclass a BGW in VB but obviously not in C#, yet again if I don't have to not a big deal.
Basically what I need to do is be able to run the same function up to 3 times concurrently. I believe if my memory serves me correctally each "occurance" of the function will have it's own local variables. I also believe that if I use a thread vs a bgw I can lock what I'm writing to and instead of throwing a error, the threads will wait until the current one is done updating. Lets say it's just lblOutput.Text = e.UserState.ToString(); (as if it were a bgw perhaps in a thread you can use the variable directally)?
Does this help to explain what I'm trying to accomplish and maybe give you all a better idea of what path I should be taking?
|
|
|
|
|
MacRaider4 wrote: (as if it were a bgw perhaps in a thread you can use the variable directally)?
Nope, that limitation is universal to all types of multithreading in WinForms (And WPF, for that matter). No touching the GUI controls except from the GUI thread.
MacRaider4 wrote: Plus when I was getting into more advanced someone reccomended keeping as little as you can on your main form and using classes for as much as possible. Is this a good habbit, bad habbit or just personal preference?
That's generally a good idea, except in really small tools when it would be complete overkill. The form is your connection to the GUI, and business logic goes elsewhere... In your particular situation, I think I would probably handle it something like this:
(Consider this C#ish pseudocode, as I don't have VS installed on my home machine at the moment)
public static void SendMessagesAsync(ProgressChangedHandler progressCallback, params SomeClass[] messages)
{
for (int idx = 0; idx < messages.Length; idx++)
{
BackgroundWorker wkr = new BackgroundWorker();
wkr.WorkerSupportsProgress = true;
wkr.ProgressChanged += progressCallback;
wkr.DoWorkEventArgs += wkr_DoWork;
wkr.RunWorkerAsync(messages[idx]);
}
}
private static void wkr_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wkr = sender as BackgroundWorker;
SomeClass args = e.Argument as SomeClass;
}
private void SomethingCalledFromYourForm()
{
MyStaticClass.SendMessagesAsync(wkr_ProgressChanged, new SomeClass[] {
new SomeClass() { Whatever = parameters, YouWant = toset },
new SomeClass() { Subject = someone, Body = "something else?", Recipient = "someone@somewhere.sometime" }
});
}
I don't know what you need to pass to the WriteMail function, but that's generally how you get information into a background worker... Make a class to hold it, and pass it as the argument to RunWorkerAsync().
|
|
|
|
|
Ian Shlasko wrote: I wonder if the BackgroundWorker only allows ReportProgress to be called during the DoWork
No, internally it uses a SendOrPostCallback delegate and an AsyncOperation . If the AsyncOperation is null (there is no active worker thread) then the delegate is called directly. If it's not null then the AsyncOperation 's Post method is called with the delegate and args as parameters which automatically invokes it on the syncronization context that RunWorkerAsync existed in.
public void ReportProgress(int percentProgress, object userState)
{
if (!this.WorkerReportsProgress)
{
throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntReportProgress"));
}
ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
if (this.asyncOperation != null)
{
this.asyncOperation.Post(this.progressReporter, arg);
}
else
{
this.progressReporter(arg);
}
}
|
|
|
|
|
Hey guys,
is it possible to load a .jpg on a form and make it transparently to sketch it in paint or somewhere else?
The picture should always stay in the foreground, but I want interact to the window under it.
any suggestions?
|
|
|
|
|
How about...
- Set jpg as form BackgroundImage
- Set form Opacity to 50% (or whatever)
- Set FormBorderStyle to None (but you will have to handle Move another way)
- Set form TopMost to true
Illogical thoughts make me ill
|
|
|
|
|
yeah, thank you !
But 1 Problem remain...
How could I draw under it without set the focus to the Form?
|
|
|
|
|
Ahhh.. I knew it seemed too easy
Maybe this[^] will help
Illogical thoughts make me ill
|
|
|
|
|
Yeah its vb.net but I have no problem with it !
Thank you very much
|
|
|
|