I have the user select a file using an OpenFileDialog. After the file is selected, and the dialog is closed, the main window is the last application when alt-tabbing. I want to have the main window regain focus and be on the foreground without having to alt+tab to it after closing the dialog window. Is this possible and if so how?
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Class1 c1;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
c1 = c1.Instance;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
c1.Load(Content);
c1.GetFile();
}
}
public sealed class Class1
{
private static Class1 _instance = null;
private static readonly object _padlock = new object();
private Class1()
{
}
public static Class1 Instance
{
get
{
lock (_padlock)
{
if (_instance == null)
{
_instance = new Class1();
}
return _instance;
}
}
}
public void GetFile()
{
string path;
OpenFileDialog ofdSelectLayout = new OpenFileDialog();
if(ofdSelectLayout.ShowDialog() == DialogResult.OK)
{
path = ofdSelectLayout.FileName;
}
//some code
}
public void Load(ContentManager content)
{
//Loading some textures
}
}
I thought there would be an simple method for it. (like Game.IsActive, which only checks if the game is out of focus)
After a while, I've found this one around, you can place it in the method where the FileDialog is closing:
using System.Windows.Forms;
Form myForm = (Form)Form.FromHandle(this.Window.Handle);
myForm.Activate();
This however does use System.Windows.Forms, and that means that your game have to be Windows-exclusive for it. But if you're working in Windows Forms, you can see it as a workaround for now.
Related
I'm having a problem: When I create a window in OpenGL, using C#, my window starts to lag, and I cannot use the window (I cannot close, minimize, resize, etc.). And when I hover my mouse inside the window, my cursor becomes that blue wheel, meaning it's lagging. How can I fix it?
It's worth saying that I'm using OpenGL and OpenTK to display and use the window however I want.
This is my code for generating the window:
First, this is the “GameLoop” class, everything related to the game itself is derived from this class, it contains some abstract classes that I can override, so it's really useful.
public abstract class GameLoop
{
public GameWindow window;
public Vector2Int windowSize = new Vector2Int(1280, 768);
public void Run()
{
OnInitialize();
WindowManager.CreateWindow(windowSize.x, windowSize.y, "Engine", out window);
OnLoad();
while (WindowManager.IsRunning)
{
OnUpdate();
OnRender();
}
OnCloseWindow();
}
protected abstract void OnInitialize();
protected abstract void OnLoad();
protected abstract void OnUpdate();
protected abstract void OnRender();
protected abstract void OnCloseWindow();
}
class RunGameLoop
{
static void Main()
{
GameLoop loop = new EngineWindow();
loop.Run();
}
}
Secondly, I have this method in another class that is responsible for creating the window itself:
public static void CreateWindow(int width, int height, string title, out GameWindow window)
{
window = new GameWindow(GameWindowSettings.Default, NativeWindowSettings.Default);
Vector2Int res = new Vector2Int(width, height);
//windowSize = res;
IsRunning = true;
window.CenterWindow(Vector2Int.ToVec2i(res));
window.Title = title;
}
And finally, I have the main class, where I can use OpenGL and make my project:
public class EngineWindow : GameLoop
{
protected override void OnInitialize()
{
Debug.WriteLine("On Initialize");
}
protected override void OnLoad()
{
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Lighting);
GL.ClearColor(Color.ToColor4(BackColor));
GL.Viewport(0, 0, windowSize.x, windowSize.y);
CreateMesh(cubeMesh);
}
protected override void OnUpdate()
{
}
protected override void OnRender()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
angle += Time.deltaTime;
SetupViewport(sceneCamera);
RenderMesh(cubeMesh);
ControllCamera(sceneCamera);
GL.CullFace(CullFaceMode.Back);
GL.Finish();
window.SwapBuffers();
}
protected override void OnCloseWindow()
{
Debug.WriteLine("Ended");
// Clean up
GL.DeleteProgram(program);
GL.DeleteBuffers(1, ref vbo);
GL.DeleteVertexArrays(1, ref vao);
}
}
But, the issue is that when the window is created, it starts up fine, but becomes extremely laggy and I can't use the window.
What might be the issue, and how can I fix it?
While creating WPF applications and working with Window class I created my own pattern of handling Window instances. In case I need only one instance of Window my approach is:
private CustomWindow CustomWindow;
private void MenuItemCustomWindowOpenClicked(object sender, RoutedEventArgs e)
{
if (CustomWindow == null)
{
CustomWindow = new CustomWindow();
CustomWindow.Closed += delegate
{
CustomWindow = null;
};
CustomWindow.Show();
}
}
CustomWindow is a class that inherits Window class.
I wanted to know if there is a better way? What should I use if I wanted to keep instance and not create new one? Can I reuse already closed window?
If your requirements state that you need to re-use your Windows for some reason, my suggestion is to do not do it. Your could will be much more clean and readable.
In case you need to do so, my 2 cents are to implements a sort of IWindowsManager to inject be injected to any class who needs to use Windows.
Is could be a good starting point.
IWindowsManager
interface IWindowsManager : IDisposable
{
Window GetWindow<T>() where T : Window;
void ShowWindow<T>() where T : Window;
void CloseWindow<T>() where T : Window;
}
WindowsManager
class WindowsManager : IWindowsManager
{
private Dictionary<Type, Window> windows;
private bool disposed;
public WindowsManager()
{
this.windows = new Dictionary<Type, Window>();
this.disposed = false;
}
public Window GetWindow<T>() where T : Window
{
if (this.windows.ContainsKey(typeof(T)))
return this.windows[typeof(T)];
var w = Activator.CreateInstance(typeof(T)) as Window;
if (w == null)
throw new InvalidCastException($"The passed Type {typeof(T)} does not extend Window class.");
w.Closing += W_Closing;
this.windows.Add(typeof(T), w);
return w;
}
private void W_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
Window w = sender as Window;
w.Hide();
}
public void ShowWindow<T>() where T : Window
{
Window w = null;
if (!this.windows.ContainsKey(typeof(T)))
w = this.GetWindow<T>();
w = this.windows[typeof(T)];
w.Show();
}
public void CloseWindow<T>() where T : Window
{
if (!this.windows.ContainsKey(typeof(T)))
throw new InvalidEnumArgumentException($"Failed to get existing Window of Type {typeof(T)}");
var w = this.windows[typeof(T)];
w.Hide();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
foreach (var window in this.windows)
{
var w = window.Value;
w.Close();
w.Closing -= W_Closing;
}
}
this.disposed = true;
}
}
}
WindowsManager implements IDisposable interface to close windows when disposed. Any other logic might be implemented based on your requirements.
To let the code work properly you have to use the WindowsManager instance when showing or closing Window and do not call WindowXXX.Show() or WindowXXX.Close() directly.
That seems fine. To re-use the window, you have to handle the Closing event and cancel it, then Hide the window instead of closing it. To open it up again you can call Show again.
I tried different solutions but had no luck... I don't know how to handle this. Following problem:
I have a main form (Form1) and a child form (splashScreen).
The code in my splashScreen:
public splashScreen()
{
InitializeComponent();
}
public splashScreen(Form1 frm1)
{
form1 = frm1;
InitializeComponent();
}
private static splashScreen m_instance = null;
private static object m_instanceLock = new object();
public static splashScreen GetInstance()
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen();
}
}
return m_instance;
}
In my Form1 I'm creating a new thread and starting my splashScreen. The way I'm calling controls in my splashScreen is the following:
splashScreen splashObj = splashScreen.GetInstance();
if (splashObj.InvokeRequired)
{
splashObj.Invoke((MethodInvoker)delegate()
{
splashObj.Show();
}
);
}
else
{
splashObj.Show();
}
Now the splashScreen gets started when my Form1 is working and shows the current process. On the splashScreen I have a button "Cancel". When I click on that button I want to change a variable "killProc" - which is in my Form1- to "true" so that the work in Form1 can be stopped through a return statement when at some point "if(killProc)" returns true.
How do I change the variable in my Form1 through my splashScreen or is there even a better way?
In the GetInstance method use the splashScreen(Form1 frm1) constructor to constructs an instance. They you have the reference to your parent from SplashScreen, which you could use the set property.
public static splashScreen GetInstance(Form1 frm1)
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen(frm1);
}
}
return m_instance;
}
So, from SplashScreen
form1.killProc = true;
I have some trouble accessing the ProgressBar and a certain Label in from my splashScreen. I made an own Form for the screen. In my Form1 I have the following method:
private void sign_Click(object sender, EventArgs e)
{
splashScreen splScreen = new splashScreen();
Thread thrd = new Thread(new ThreadStart(loadingScreenStart));
thrd.Start();
splScreen.percentage.Text = "0%";
var logIn = new LogIn(this);
logIn.checkUserInput(this);
thrd.Abort();
}
public void loadingScreenStart()
{
Application.Run(new splashScreen());
}
In my LogIn class I did:
public String checkUserInput(object sender)
{
splashScreen splScreen = new splashScreen();
//won't change my Label and PrpgressBar
I know it's probably because I create a new instance of the Form so it's empty but how to do this right? I don't know... Hope someone can help me.
Same requirement I too had where I need to use the same object but was having a limitation where i cannot use the static class. For that i have created a static object of the class and using lock. Try if it solves your requirement.
private static splashScreen m_instance = null;
private static object m_instanceLock = new object();
public static splashScreen GetInstance()
{
lock (m_instanceLock)
{
if (m_instance == null)
{
m_instance = new splashScreen();
}
}
return m_instance;
}
And whenever you want to create the object or access the already created object, you just need to give as:
SomeClass someobj= SomeClass.GetInstance();
With this code I can ensure that only one instance of the application is running. But I can not cause the window to be restored from the system tray. I tried window.Show() but not resolve.
public class SingletonApplication : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public App application { get; private set; }
Telas.wndLogin window;
[STAThread]
public static void Main(string[] args)
{
new SingletonApplication().Run(args);
}
public SingletonApplication()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
application = new App();
window = new Telas.wndLogin();
application.Run(window);
return false;
}
protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
{
//todo:
}
}