I am building a game. I have a Menu page, with a "Start" button. I would like to know how I can make the button direct the user to a new page with the game. I thought of simply changing all buttons' and labels' visibility to false, but that would be very messy. I thought of closing the form and reopening a new one as said here:
http://social.msdn.microsoft.com/Forums/windows/en-US/936c8ca3-0809-4ddb-890c-426521fe60f1/c-open-a-new-form-and-close-a-form?forum=winforms
Like this:
public static void ThreadProc()
{
Application.Run(new Form());
}
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
t.Start();
this.Close();
}
but when I click the button, you can see the form closing and reopening again, and it doesn't even reopen at the same coordinates.
Is there any way to do such a thing? I want it to move from page to page as it would if this was a website. Is this possible? If so how? Thanks in advance :-)
Use UserControls for every view you need and then switch between them in your code by adding/removing them to/from your form.
Example: The start-page is a UserControl containing the button that starts the game. The game UI is another UserControl that contains all the logic and visuals for your game.
You could then use something like he following:
public class StartView : UserControl
{
...
private void btnStart_Click(object sender, EventArgs e)
{
// Raise a separate event upon the button being clicked
if (StartButtonPressed != null)
StartButtonPressed(this, EventArgs.Empty);
}
public event EventHandler<EventArgs> StartButtonPressed;
}
public class GameView : UserControl
{
...
}
public UserControl SwitchView(UserControl newView)
{
UserControl oldControl = null;
if (this.Controls.Count > 0)
{ oldControl = (UserControl)this.Controls[0];
this.Controls.RemoveAt(0);
}
this.Controls.Add(newView);
newView.Dock = DockStyle.Fill;
return oldControl;
}
You can now create the start view in Form_Load:
public void Form_Load(object sender, EventArgs e)
{
StartView v = new StartView();
v.StartButtonPressed += StartButtonPressed;
SwitchView(v);
}
The event handler that reacts to the start button being pressed would do this:
public void StartButtonPressed(object senderView, EventArgs e)
{
GameView v = new GameView();
UserControl old = SwitchView(v);
if (old != null)
old.Dispose();
}
Related
I have a Main Form with a MenuStrip on it, and I use that MenuStrip to open new owned Forms like so:
var target = new Target();
target.Owner = this;
target.Show();
This works exactly how I want it to: the Forms are always shown in front of the Main Form.
The issue that I run into is that, when one of these owned Forms has the focus, I can't access the MenuStrip via keyboard. I'd like CTRL+S to trigger the Save functionality, the same as it does when the Main Form has the focus.
Is this possible? Is there a better way to approach this?
Sorry for the delay, but if you're still having issues or looking for a different method, see below.
In your MainForm:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child = new ChildForm();
// KeyPreview can be set in the properties of the child form instead
child.KeyPreview = true;
child.KeyPressed += Child_KeyPressed;
child.ShowDialog();
}
private void Child_KeyPressed(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
// Save Pressed
}
}
}
and then in your Child Form:
public partial class ChildForm : Form
{
public event EventHandler<KeyEventArgs> KeyPressed;
public ChildForm()
{
InitializeComponent();
}
private void Child1_KeyUp(object sender, KeyEventArgs e)
{
KeyPressed?.Invoke(sender, e);
}
}
Thanks to Troy Mac1ure for the direction. Here's the solution that lets me use the ShortCutKeys from the main menu.
ownedForm.KeyPreview = true;
ownedForm.KeyDown += OwnedForm_KeyDown;
private void OwnedForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
foreach (ToolStripMenuItem menuItem in menu.Items)
{
foreach (ToolStripMenuItem item in menuItem.DropDownItems.OfType<ToolStripMenuItem>())
{
if (item.ShortcutKeys == e.KeyData)
{
item.PerformClick();
return;
}
}
}
}
}
This doesn't handle Alt menu activation, but Paint.NET doesn't handle that either, so I view that as a nice-to-have.
I'm facing the same issue raised in "Arrow keys and changing control's focus hang the application". Since I'm unable to comment on it due to I don't have enough points. Hence, I posted a new one.
Thanks in advance.
Run the program
Select any radiobutton
Click button2
Press tab to focus onto radiobutton
Press Left/Right Navigation keys
Form hang-up (not responding).
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
ucPage11.BringToFront();
ucPage11.Enabled = true;
richTextBox1.Enabled = false;
}
private void ucPage11_SelectionChanged()
{
ucPage11.Enabled = false;
richTextBox1.BringToFront();
richTextBox1.Enabled = true;
}
}
UserControl.cs
- The user control has 3 radio button control in it.
public delegate void SelectionEventHandler();
public partial class UCPage1 : UserControl
{
//private ToggleImageControlManager toggleImgCtrlMgr;
public UCPage1()
{
this.InitializeComponent();
}
public event SelectionEventHandler SelectionChanged;
private void RBO_Click(object sender, EventArgs e)
{
SelectionChanged?.Invoke();
}
}
I´m programming a simple thing in C# and WPF. I have a MainWindow with a button. If I trigger the button it opens a secon window:
private void btnF4_Click(object sender, RoutedEventArgs e)
{
SecondWindow second = new SecondWindow();
second.Show();
}
Naturally if I trigger the button three or four times, I have three or four windows open. I don´t want to use ShowDialog(), but I want to open my second window only once. I mean if I trigger the button and the window is already open, should nothing happen.
Thank you!
Make second an instance variable to the parent window class and only create a new window if it hasn't been created.
Of course you need to make sure to null the instance variable when the second window is closed.
public class ParentWindow ...
{
private SecondWindow m_secondWindow = null;
....
private void btnF4_Click(object sender, RoutedEventArgs e)
{
if (m_secondWindow == null)
{
m_secondWindow = new SecondWindow();
m_secondWindow.Closed += SecondWindowClosed;
m_secondWindow.Show();
}
}
public void SecondWindowClosed(object sender, System.EventArgs e)
{
m_secondWindow = null;
}
}
This might be shortened to the following:
public class ParentWindow ...
{
private SecondWindow m_secondWindow = null;
....
private void btnF4_Click(object sender, RoutedEventArgs e)
{
if (m_secondWindow == null)
{
m_secondWindow = new SecondWindow();
}
m_secondWindow.Show();
}
}
However, I'm never sure whether you can actually "reopen" a window that was closed before. If you need to initialize the window all over upon reopening, use the first code. If you can live with the window starting up showing the previous content, use the second.
Declare SecondWindow in Parent Window class instead of a method.
public class MainWindow : Window {
SecondWindow second = new SecondWindow();
private void btnF4_Click(object sender, RoutedEventArgs e) {
if (!second.IsActive) {
second.Show();
}
}
}
Declaring second in the method makes the second window local to the method, which means every time you click the button it will create a new instance of that class (window)
I have a WPF application that I have removed the border and default controls by doing the following:
WindowStyle="None" AllowsTransparency="True"
Now I added a MouseDown handler MouseDown="Window_MouseDown" and added the following code to allow me to move my Window around:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
try
{
if (e.ChangedButton == MouseButton.Left)
DragMove();
}
catch (Exception ex) { }
}
But now I have a UserControl that I want to resize to the full size of my Application so to achieve this I created a new Window that is the same size as my MainWindow and placed the UserControl onto it. I create this new Window and set its parent to be my main application like so:
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
I launch this window like so:
MyFullScreenWindow fullScreen = new MyFullScreenWindow();
fullScreenVideo.ShowDialog();
My problem is that I want to still move my whole application around whenever the user clicks and moves this new window. To achieve this I have added an Event to MyFullScreenWindow:
public partial class MyFullScreenWindow: Window
{
static public event EventHandler MouseDownEvent;
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (MouseDownEvent != null)
{
MouseDownEvent(sender, e);
}
}
}
And I handle this event in my MainWindow like so:
MyFullScreenWindow.MouseDownEvent += new EventHandler(MyFullScreenMouseDownHandler);
private void MyFullScreenMouseDownHandler(object sender, EventArgs e)
{
DragMove();
}
But when I click and drag I see that the event is fired off but my whole application does not move like it should. Why is this??
Simply add the following function code only
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
move your window where ever you want.
I don't know the context of your problem, but why would you create a new window, "place" it inside the parent one? You can use controls without creating a new window.
It's possible that you are doing this because you need AllowTransparency=false functionality, while showing it in AllowTransparency=true window. (I had this case when working with DirectShow). If you're doing this for custom window chrome, then don't use AllowTransparency - it decreases performance greatly. It's creating picture of every frame and disables GPU acceleration, after all! Instead, you can adapt to CustomChromeWindow project(found on Internets).
Note that you can enable the main window so that it would process messages from underlying window:
public class WindowSecond : Window
{
public WindowSecond()
{
Owner = Application.Current.MainWindow;
MouseDown += delegate
{
// maybe cache it.
IntPtr handle = new WindowInteropHelper(Owner).Handle;
EnableWindow(handle, true);
Application.Current.MainWindow.DragMove();
EnableWindow(handle, false);
};
}
[DllImport("user32")]
internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable);
}
I have a main parent winform in which I have implemented some features and that have a number of child windows. Now I want the functionality I have implemented to run also on the child windows.
For instance, in the parent window I am moving an image on the selection of a checkbox. Now, if this checkbox is checked then the image should also move on the all other child windows.
Note: The image moving on the parent window should disapper and should only show on the opend dialogue or child window.
Please suggest if it is possible.
Try using events.
Create an event for the parent form called ImageMoved.
The child forms should subscribe to this event, and when you move the image, you raise the event, then the child forms will know to do their thing.
Lots of different ways to do this. Simple example:
public partial class Form1 : Form {
public event EventHandler ImageMoved;
private void OnImageMoved() {
if (ImageMoved != null)
ImageMoved(this, new EventArgs());
}
private void button1_Click(object sender, EventArgs e) {
OnImageMoved();
}
private void button2_Click(object sender, EventArgs e) {
Form2 f2 = new Form2(this);
f2.Show();
}
}
Then your child forms could look something like this:
public partial class Form2 : Form {
public Form2(Form1 parentForm) {
InitializeComponent();
parentForm.ImageMoved += new EventHandler(parentForm_ImageMoved);
}
void parentForm_ImageMoved(object sender, EventArgs e) {
MessageBox.Show("Image moved");
}
}
You could also create your own EventArgs class if you want to pass more information, such as which image, etc.