Threading with Windows Forms - c#

I've written a Windows Forms application in C#. When I run a separate thread containing a method that toggles the invisibility of a panel on my form, it works the first time but not the second. Why and how can I fix it?

Thanks, solved My Problem by follow Code :
Panel tmp = null;
switch (d.Person)
{
case 1: tmp = backPic1;
break;
case 2: tmp = backPic2;
break;
case 3: tmp = backPic3;
break;
}
if (InvokeRequired)
{
tmp.Invoke(new MethodInvoker(delegate() { tmp.Visible = true; }));
}
else
{
tmp.Visible = true;
}

My guess be he UI code invoking from a background thread is. ;)

Your question is a bit vague, but it sounds like you want to control the UI from a different thread, in which case you will need to synchronise the request. It's difficult to tell you how to do that without knowing what programming language you are using.

Related

Unity - playerprefs deletes info

I'm making a game. it has a login panel and rememmer me button. i keep the info on regedit. when I click rememmer me button it works and when I start game after click button it gets my info like id and pass but when I start again it deletes my id and pass on regedit. So it get just one time. I couldn't find the problem or fix way. Can you help me? Thank you.
Here is my codes:
void Start()
{
if(PlayerPrefs.GetInt("BeniHatirla")==1)
{
Debug.Log("start "+PlayerPrefs.GetInt("BeniHatirla"));
BeniHatirlaGetir();
}
}
Here is the method ı called in start:
public void BeniHatirlaGetir()
{
isim = PlayerPrefs.GetString("BeniHatirlaIsim");
sifre = PlayerPrefs.GetString("BeniHatirlaSifre");
Debug.Log("kullanici "+isim+sifre);
BeniHatirlaUniSlider.value = 1;
Debug.Log("Ogrenm Durumu"+PlayerPrefs.GetInt("OgrenimDurumuBelirleme"));
switch (PlayerPrefs.GetInt("OgrenimDurumuBelirleme"))
{
case 1:
OrtaOkulKadiTextBox.text = isim.ToString();
OrtaokulKsifreTextBox.text = sifre.ToString();
LoginPanelleri[0].SetActive(true);
break;
case 2:
LiseKadiTextBox.text = isim.ToString();
LiseKsifreTextBox.text = sifre.ToString();
LoginPanelleri[1].SetActive(true);
break;
case 3:
UniversiteKadiTextBox.text = isim.ToString();
UniversiteKsifreTextBox.text = sifre.ToString();
LoginPanelleri[2].SetActive(true);
break;
}
}
And here is the rememmer me button:
public void BeniHatırlaButon()
{
PlayerPrefs.SetInt("BeniHatirla", 1);
switch (PlayerPrefs.GetInt("OgrenimDurumuBelirleme"))
{
case 1:
PlayerPrefs.SetString("BeniHatirlaIsim", OrtaOkulKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", OrtaokulKsifreTextBox.text.ToString());
break;
case 2:
PlayerPrefs.SetString("BeniHatirlaIsim", LiseKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", LiseKsifreTextBox.text.ToString());
break;
case 3:
PlayerPrefs.SetString("BeniHatirlaIsim", UniversiteKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", UniversiteKsifreTextBox.text.ToString());
break;
}
}
If you're running some debugger, it may be missing out on when it actually saves the values to disk. From the documentation for PlayerPrefs:
By default Unity writes preferences to disk during OnApplicationQuit(). In cases when the game crashes or otherwise prematuraly exits, you might want to write the PlayerPrefs at sensible 'checkpoints' in your game. This function will write to disk potentially causing a small hiccup, therefore it is not recommended to call during actual gameplay.
So if you are exiting the application prematurely through debugging it may be that you just need to call PlayerPrefs.Save() right after you try to write the values.

How do I change a variable outside of a class in C#?

I am making a very simple multiple choice console game. I have created a finite state machine using enums and if else states all within a while loop (while game = true).
The issue is, inside of the class level.level1 (contains level info) it needs to change myState to the new state which is in the main program, but it can't impact it. Any ideas on how to make this happen? I'm stumped.
var game = true;
while (game = true)
{
State myState = State.intro;
//first level
if (myState == State.intro)
{
level.Intro();
}
else
{
if (myState == State.contact1)
{
Console.WriteLine("Wroked");
}
in the level class:
Console.WriteLine(name + " What are you doing, I need your help!");
Thread.Sleep(1000);
Console.WriteLine("\nA. Who is this? \nB. How are you doing this?\nC. How do you know my name?");
var res = Console.ReadLine();
char response = res[0];
switch (response)
{
case 'a':
State myState = State.contact1;
break;
case 'b':
Console.WriteLine("\nright");
break;
case 'c':
Console.WriteLine("\nleft");
break;
}
There's obviously more code than this, but that's the important part. you can see full code here:
https://gist.github.com/MajorMojo/700936c02f1430de44b4559f0579917d
https://gist.github.com/MajorMojo/5bba21cb977a4b768029e765a0d74886
you either need to pass a game object into the level class or make some static variables.
I would do the first one and have a GameEngine class that is created by main and maintains the overall state of the game. It can have a SetState method (or State property). Pass the GameEngine object into the level when you create it.
I would suggest starting with a basic intro to programming tutorial. The C# one isn't too bad: https://msdn.microsoft.com/en-us/library/aa664628(v=vs.71).aspx
You're missing a lot of basic concepts. It would be a lot easier for you to pick them up by working through a complete tutorial than by asking individual questions here.

How to invoke a control within a IF statement

I have searched quite a bit looking for how to invoke a control within a if statement for awhile now and haven't been able to find anything on this. I'm sure I'm missing something but if someone could show me how to do this that would be great. Here is a short piece of my code to give you an idea of where my problem is.
if(cardPanelOpponent.GetChildAtPoint(new Point(i, x)) == null)
{
OpponentCard.Location = new Point(i, x);
cardPanelOpponent.Invoke(new Action(() => cardPanelOpponent.Controls.Add(OpponentCard))
break; }
This line is taking place in a Async environment so I am getting a cross thread exception. How can I run this if statement while on a different thread then the UI.
If your code is running in worker thread then you're not allowed to call GetChildAtPoint or set Location in it. You need to pass the control to UI thread.
if(cardPanelOpponent.InvokeRequired)
{
cardPanelOpponent.Invoke(new Action(() =>
{
if(cardPanelOpponent.GetChildAtPoint(new Point(i, x)) == null)
{
OpponentCard.Location = new Point(i, x);
cardPanelOpponent.Controls.Add(OpponentCard);
}
});
}
Note: Semantics has changed in above code. We can't add break statement here. So you may need to correct it as your needs.

Taskbar window minimenu Win7

I would like to use this menu through C# or F# in Win7. I even couldn't find how to call it.
In Introducing The Taskbar APIs on the MSDN magazine, it describes about how to use the Thumbnail Toolbars.
The managed equivalent does not currently appear in the Windows API
Code Pack, but it is planned to appear in a future release. In the
meantime, you can use the Windows 7 taskbar Interop Sample Library. It
contains the ThumbButtonManager class with the corresponding
CreateThumbButton and AddThumbButtons methods for controlling the
thumbnail toolbar, and also the ThumbButton class for modifying the
thumbnail button state at runtime. To receive notifications, you
register for the ThumbButton.Clicked event and override your window
procedure to dispatch the messages to the ThumbButtonManager class,
which does the dispatching magic for you. (For more details, see the
blog article Windows 7 Taskbar: Thumbnail Toolbars.)
ITaskbarList3* ptl;//Created earlier //In your window procedure:
switch (msg) {
case g_wmTBC://TaskbarButtonCreated
THUMBBUTTON buttons[2]; buttons[0].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS; buttons[0].iId = 0;
buttons[0].hIcon = GetIconForButton(0); wcscpy(buttons[0].szTip, L"Tooltip 1"); buttons[0].dwFlags = THBF_ENABLED;
buttons[1].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS;
buttons[1].iId = 1; buttons[1].hIcon = GetIconForButton(1);
wcscpy(buttons[0].szTip, L"Tooltip 2"); buttons[1].dwFlags = THBF_ENABLED; VERIFY(ptl->ThumbBarAddButtons(hWnd, 2,buttons));
break;
case WM_COMMAND:
if (HIWORD(wParam) == THBN_CLICKED) {
if (LOWORD(wParam) == 0)
MessageBox(L"Button 0 clicked", ...);
if (LOWORD(wParam) == 1) MessageBox(L"Button 1 clicked", ...);
}
break;
.
.
And in the second link it shows a C# sample using a wrapper library:
As always, the managed wrappers come to the rescue. The
ThumbButtonManager class (in the Windows7.DesktopIntegration project)
_thumbButtonManager = this.CreateThumbButtonManager();
ThumbButton button2 = _thumbButtonManager.CreateThumbButton(102, SystemIcons.Exclamation, "Beware of me!");
button2.Clicked += delegate
{
statusLabel.Text = "Second button clicked";
button2.Enabled = false;
};
ThumbButton button = _thumbButtonManager.CreateThumbButton(101, SystemIcons.Information, "Click me");
button.Clicked += delegate
{
statusLabel.Text = "First button clicked";
button2.Enabled = true;
};
_thumbButtonManager.AddThumbButtons(button, button2);
Note that you have tooltips and icons at your disposal to personalize the thumbnail toolbar to your application’s needs. All you need to do now is override your windows’ window procedure and call the DispatchMessage method of the ThumbButtonManager, so that it can correctly route the event to your registered event handlers (and of course, don’t forget to call the default window procedure when you’re done!):
if (_thumbButtonManager != null)
_thumbButtonManager.DispatchMessage(ref m);
base.WndProc(ref m);

Updating GUI components in class B from class A in c#

EDIT: I see I'm getting a lot of downvotes on this post. I've tried to explain what I try to do, where my errors and in which direction want to go. I'm asking for insight in what I'm doing wrong. If you downvote; pleas tell me why, so I can improve the question. Thanks.
I'm creating an application where I have one main form, and several different User Controls which the user works on. This helps me splitting the code, managing the different parts of the program. And it would be easy to expand the application later on.
I'm trying to create a class where I manage the active controls I want to call one function in that class with as argument the form that should become active.
An image can illustrate how I try to setup this application. Note that the control manager class is not a seperate class in the code i show below, but a partial class of the mainform. Any tips on how to get it like in the image are very welcome :)
The class to manage all active forms looks like this: Please note that all user controls are just a user control with some buttons/textboxes etc on it. No code is added at all yet.
public partial class STP2Main
{
// I make each UserControl accessable for the whole class
SetupDeviceControl.SetupDevice SetupDev = new SetupDeviceControl.SetupDevice();
GenConfigFileControl.GenConfigFileControl GenConfFile = new GenConfigFileControl.GenConfigFileControl();
Monitoring.MonitoringControl Monitor = new Monitoring.MonitoringControl();
GenEncKeyControl.GenEncKeyControl GenEncKey = new GenEncKeyControl.GenEncKeyControl();
MenuControl.MenuControl MenuControl = new MenuControl.MenuControl();
public void SelectActiveWindow()
{
// Any active control should be hidden thats what this function does:
HideCurrentActiveControl();
// Check whether the window is already created
if (!WindowExists())
{ // if not created; create the windows:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl: // control 1:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated = true;
SetupDev.Parent = this;
SetupDev.Location = new Point(3, 30);
SetupDev.Show();
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl: //control 2:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
STP_Design.ProgramParameters.C.MonitoringControlIsCreated = true;
Monitor.Parent = this;
Monitor.Location = new Point(3, 125);
Monitor.Show();
Monitor.BringToFront();
break;
case STP_Data.Data.MenuControl: // control 3
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
STP_Design.ProgramParameters.C.MenuControlIsCreated = true;
MenuControl.Location = new Point(3, 30);
MenuControl.Parent = this;
MenuControl.Show();
MenuControl.BringToFront();
break;
}
}
else
{ // window is already created so needs to be called to front again:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
Monitor.Visible = true;
Monitor.BringToFront();
break;
case STP_Data.Data.AdvancedMenu:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.AdvancedMenu;
tabControl1.Visible = true;
tabControl1.BringToFront();
break;
case STP_Data.Data.MenuControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
MenuControl.Visible = true;
MenuControl.BringToFront();
break;
}
}
btnMenu.BringToFront();
}
// some functions which are called above are not shown; not relevant for this question
}
What I experience is the following: I get no errors at all. But the controls simply not change at all. If I call a window, it is created only once, because I did make it as partial class of my Mainform. (I've tried a complete seperate class, which did result in errors with threading, As I am not an experienced c# programmer, I tried to avoid that using a partial class.)
I'll add another function; which does not do anything at all:
private void HideCurrentActiveControl()
{
switch (STP_Design.ProgramParameters.C.CurrentActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
SetupDev.Visible = false;
break;
case STP_Data.Data.MonitoringControl:
tabControl1.Visible = false;
Monitor.Visible = false;
break;
case STP_Data.Data.GenConfFileControl:
GenConfFile.Visible = false;
break;
case STP_Data.Data.GenEncKeyControl:
GenEncKey.Visible = false;
break;
case STP_Data.Data.MenuControl:
MenuControl.Visible = false;
break;
case STP_Data.Data.AdvancedMenu:
tabControl1.Visible = false;
break;
default:
tabControl1.Visible = false;
break;
}
}
I've tried debugging this part of code and it executes the statements, but I see no changes at all.
I think I've shown what I am trying to do; and how I try to do that. My question is: How do I acces those forms so I can manage them from a seperate class (or in this case partial class of the main form).
Then I have this last function, which does some wierd things. Before I call the SelectActiveWindow() function I update the variable STP_Design.ProgramParameters.C.NextActiveControl to for example: ...AdvancedMenu. (this was before that ...MenuControl) But it does always show that it is still MenuControl. Nowhere in my code is something where I change that value besides right before I start the function. (I've also tried to make the nextcontrol as an argument of the function SelectActiveWindow() but this did the same)
private bool WindowExists()
{
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
if (STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated)
return true;
else
return false;
case STP_Data.Data.MonitoringControl:
if (STP_Design.ProgramParameters.C.MonitoringControlIsCreated)
return true;
else
return false;
case STP_Data.Data.GenConfFileControl:
if (STP_Design.ProgramParameters.C.GenConfFileIsCreated)
return true;
else
return false;
case STP_Data.Data.GenEncKeyControl:
if (STP_Design.ProgramParameters.C.GenEncKeyControlIsCreated)
return true;
else
return false;
case STP_Data.Data.AdvancedMenu:
return true;
case STP_Data.Data.MenuControl:
if (STP_Design.ProgramParameters.C.MenuControlIsCreated)
return true;
else
return false;
default:
return false;
}
}
Summery of what I am looking for:
I am having a main form where display different user controlls in. I am trying to create a seperate class which is accessable from each control/form in my project. This class should manage the controls which are shown. In the code above I illustrated how I tried to do this, but this does not result in the expected result.
Ok, Now I understand the context needed. We actually do something very similar in my program. Here is a basic outline of how we do it...
Layout
On the main form we have a Panel container that we call pnlMain. It is this control that we add and remove active user controls from. We also have a UserControl object at a global level on the form representing curActiveControl.
Code
When the user selects a window via one of the menu's, we run a function that looks like this
switch (UserSelection)
{
case "Page 1":
if(curActiveControl.GetType() != typeOf(Page1Control))
{
pnlMain.Controls.Remove(curActiveControl);
curActiveControl = new Page1Control();
//do setup and configuration things
pnlMain.Controls.Add(curActiveControl);
}
//do some post processing things
break;
//other pages/specific page controls
}
Refresh();
The downside to this specific method is that the pages themselves are not persistent, so if there are entries or variables you want to have active across a session rather than only while on a page, you have to store them in some other global object and reload them from the user control's Load or Constructor methods.
You could do this same thing but instead of creating a new control instance each time for curActiveControl you could simply replace it with the standby instance of the new control. Be careful with referencing and overwriting though, its not something I personally have tried before.
The key in the method we use is the Panel that holds the user controls. Rather than adjusting the visibility and Z-Order of a large number of user controls, we simply change the displayed control in the main panel and the other control don't even exist at any given point in time.
The other wrinkle is that this functionality is directly on our Main Form. I Don't know how well this will work as another partial class. Its definitely worth a try though.

Categories

Resources