OpenGL4Net WM_PAINT does not exist? - c#

I'm trying to get OpenGL4Net working with C# in Microsoft Visual Studio Comunity 2015.
I've downloaded this file:
https://sourceforge.net/projects/ogl4net/files/Rev.%2037/x64/
And followed these instructions:
https://sourceforge.net/p/ogl4net/wiki/Tutorials/
At first with a console application but then starting again with a Windows Form application as it seems as if it was going to be using the window from that as opposed to making its own.
So far the various refrances have been added, form1.cs is untouched and Program.cs looks like this:
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenGL4NET;
namespace pads2
{
class Program : Form
{
RenderingContext rc;
static void Main(string[] args)
{
Program program = new Program();
program.Init();
Application.Run(program);
}
// required for open GL
void Init()
{
rc = RenderingContext.CreateContext(this);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
void Render()
{
gl.Clear(GL.COLOR_BUFFER_BIT);
// here is the right place to draw all your scene
rc.SwapBuffers();
}
// change window size
protected override void OnSizeChanged(EventArgs e)
{
gl.Viewport(0, 0, ClientSize.Width, ClientSize.Height);
// projection matrix may also need adjusting
}
// required for open GL
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Windows.WM_PAINT: Render(); break;
default: base.WndProc(ref m); break;
}
}
}
}
/*
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
/*
The compiler seems unhappy about the comment at the end of the code, however the main issue is that I recieve the error:
The type or namespace name 'WM_PAINT' does not exist in the namespace 'Windows' (are you missing an assembly reference?)
I've been unable to find what reference I need for WM_PAINT online, including a reference for System.Windows did not help.
Q: How can I solve this and am I setting this up correctly?

WM_PAINT is described in detail in its MSDN entry:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd145213(v=vs.85).aspx
The article however omits its POD value, being the Integer constant "15".

Had this problem earlier, the example forgets to add the reference, the case should be:
case OpenGL4NET.Windows.WM_PAINT: Render(); break;
(Would comment if rep allowed me too)

Related

OpenTK does not find OpenTK.Input.Keyboard.GetState();

So i was trying to detect the keywords with OpenTK and in their tutorial gave this code:
protected override void OnUpdateFrame(FrameEventArgs args)
{
//Get the state of the keyboard this frame
KeyboardState input = OpenTK.Input.Keyboard.GetState();
if (input.IsKeyDown(Key.Escape))
{
Exit();
}
base.OnUpdateFrame(args);
}
But what happens is that it gives an error at "Keyboard.GetState()". The error says: "The type or namespace name 'Keyboard' does not exist in the namespace 'OpenTK.Input' (are you missing an assembly reference?)".
Or if i dont add the 'OpenTK.Input', it wont let me import anything.
I have the same problem with "Key.Escape" and "Exit()"
Okey i solved it using KeyboardState.IsKeyDown(Keys.Space). With this i can take the space input. If any other key is wanted you change the the "Keys" class function.
An exemple with this would be:
protected override void OnUpdateFrame(FrameEventArgs args)
{
if (KeyboardState.IsKeyDown(Keys.Space))
{
Console.WriteLine("Somebody once told me");
}else if (KeyboardState.IsKeyDown(Keys.Escape))
{
this.Close();
}
base.OnUpdateFrame(args);
}
As you can see, the "Exit()" is replaced by "Close()" too!

Run time Error when Application.SetCompatibleTextRenderingDefault(false); is set

Trying to convert from a Console app to a Winform app. The following Winform code compiles fine, but at runtime I'm getting the following error. I went through various solutions of similar errors online, but was still a bit confused. Maybe, someone here can help for my following specific code:
NOTE: It's probably not relevant for the question of this post. But just in case: I'm referencing micaut 1.0 Type Library in my VS2017 project that is needed for the code below.
Error [on Winform]:
SetCompatibleTextRenderingDefault must be called before the first IWin32Window object is created in the application.
Code from Console app:
using System;
using System.Windows.Forms;
using micautLib;
namespace MathInputPanel
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MathInputControl ctrl = new MathInputControlClass();
ctrl.EnableExtendedButtons(true);
ctrl.Show();
ctrl.Close += () => Application.ExitThread();
Application.Run();
}
}
}
An attempt to convert the above code to Winform app [that gives the error]:
using System;
using System.Windows.Forms;
using micautLib;
private void button1_Click(object sender, EventArgs e)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); //error occurs here
MathInputControl ctrl = new MathInputControl();
ctrl.EnableExtendedButtons(true);
ctrl.Show();
ctrl.Close += () => Application.ExitThread();
Application.Run();
}
As the error is trying to tell you, you can only call that function before you create the first form.
Move that to Main() (if it isn't already there).

C# - getting information about Windows user local session [duplicate]

I want to track the windows unlock event in a windows application. How is it done? What is the event used for that? Does I need to import any namespace for that?
While a user unlocks the windows, the application needs to do some tasks.
As posted in this StackOverflow answer: https://stackoverflow.com/a/604042/700926 you should take a look at the SystemEvents.SessionSwitch Event.
Sample code can be found in the referred answer as well.
I just took the code shown in the referred StackOverflow answer for a spin and it seems to work on Windows 8 RTM with .NET framework 4.5.
For your reference, I have included the complete sample code of the console application I just assembled.
using System;
using Microsoft.Win32;
// Based on: https://stackoverflow.com/a/604042/700926
namespace WinLockMonitor
{
class Program
{
static void Main(string[] args)
{
Microsoft.Win32.SystemEvents.SessionSwitch += new Microsoft.Win32.SessionSwitchEventHandler(SystemEvents_SessionSwitch);
Console.ReadLine();
}
static void SystemEvents_SessionSwitch(object sender, Microsoft.Win32.SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
{
//I left my desk
Console.WriteLine("I left my desk");
}
else if (e.Reason == SessionSwitchReason.SessionUnlock)
{
//I returned to my desk
Console.WriteLine("I returned to my desk");
}
}
}
}

Bitmap ArgumentException

I'm trying to create an example program and I'm having issues creating the Bitmap needed for it. When I try running the code below I'm getting an ArgumentException.
I think this is being thrown because it cannot find the file on the disk. If this is the case where do I put the file in my project so it can find it? I've tried putting the file in the main project directory and have tried placing it within the debug and release folders.
If this is not what is causing the issue can someone point me in the right direction?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
namespace Given
{
public class Photo : Form
{
Image image;
public Photo()
{
image = new Bitmap("jug.jpg"); // ArgumentException thrown here
this.Text = "Lemonade";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(Object source, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 30, 20);
}
}
}
namespace Photo_Decorator
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Given.Photo());
}
}
}
It's throwing this because it can't find the JPG, and therefore can't create a proper bitmap object. You need to either place the image file in the same folder as the EXE (Debug? Release?), or specify the entire path to the image (e.g C:/jug.jpg). Hope this helps :)
You'd need to put the file in the same folder as the executable (bin\Debug or bin\Release). You could place it in the bin folder and just use #"..\jug.jpg" as the path instead so it worked in both Debug and Release modes.

How do I handle Command Line Arguments in Winforms if I don't want to load Main form?

I want to create an app that behaves as follows:
On no argument it displays the main form
On argument "a" does a job but the main form isn't loaded.
On argument "b" the form loads using the argument passed (load that document)
For the 1 and 3 I can handle the arguments in the form's constructor as follows:
public ConfigurationActionManagerForm()
{
InitializeComponent();
Environment.GetCommandLineArgs();
// do stuff with that argument
}
But this approach doesn't allow me to apply the behavior of 2. in the list.
In program.cs I can edit it to handle the arguments before the form is even created, but what is the correct approach on using Application.Run() if I don't want to pass a form? How am I going to inform Program class instance that I need to terminate or show a message that something went wrong or even show a little taskbar icon that the process is doing stuff (Think of it like the unzipping process).
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ConfigurationActionManagerForm());
}
Would this approach from MSDN be correct to my application?
Do you mean in the same way that Visual Studio works?
If so then you can't do this in a normal Windows application - Visual Studio cheats.
The problem is that a Windows application can either be a Windows Forms application or a Console application, but it can't be both - its decided at compile time (for .Net applications this is in the project properties window). Your options are:
Make your application a Windows Forms application
In this case #1 and #3 will work perfecty, but for #2 you will find that you can't read from / write to the console (because there isn't one!). If your appliction doesn't need to give any feedback then this might be fine - do your work as you normally would and just don't display a form:
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
// Handle #2 here
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ConfigurationActionManagerForm());
}
}
Make your application a console application
In this case #2 will work perfectly, however although #1 and #3 will work fine you will always have console window open in the background - if you close the console window your application will end.
Again this might be fine, but personally I find this to be a hack.
Cheat (do what Visual Studio Does)
Visual Studio cheats by having 2 separate applications - one is a Console Application and the other is a Windows Forms application. The easy solution is to leave it at that and require that users start a different executable when running the command line version (e.g. myprogram_g.exe and myprogram_w.exe).
Visual Studio goes one step further however and has a single entry point, devenv. It does this by using the fact that for compatability reasons the Windows shell will always run a .com file instead of a .exe if there is any ambiguity. Wheras all shortcuts etc.. point to the executable, if you run devenv on the command line the devenv.com application will run instead which uses magic to sort out whether or not it runs as a console or windows application.
My advice would be to create two different applications and leave it at that.
See How do I write a program that can be run either as a console or a GUI application? for more detail (make sure to read the comments which have additional useful suggestions).
Also see How to make an application as both GUI and Console application? for how ildasm does this.
You can call Application.Run() without a form instance.
That way, it will start the message loop without opening a form.
You can call MessageBox.Show() before calling .Run(), too.
You can even create and open a form, and then call Run() without specifying an argument - it just means that closing the form doesn't automatically exit the application.
E.g.
MessageBox.Show("Messaage!");
Form1 f = new Form1();
f.Show();
Application.Run();
As stated above, this way of doing Run() means that closing the forms doesn't automatically close the application. You need to handle this in the form's Close event handler. (Application.Exit())
MSDN online can help you out with this - check the help entry for Application.Run().
Basically you want a console applcation with a few changes.
Here's an example of how to get started, using a default aboutbox class:
using System;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("No Arguments");
}
else
{
if (args[0] == "a")
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AboutBox1());
}
}
}
}
}
And AboutBox1 class:
using System.Reflection;
using System.Windows.Forms;
namespace ConsoleApplication1
{
partial class AboutBox1 : Form
{
public AboutBox1()
{
InitializeComponent();
this.Text = String.Format("About {0} {0}", AssemblyTitle);
this.labelProductName.Text = AssemblyProduct;
this.labelVersion.Text = String.Format("Version {0} {0}", AssemblyVersion);
this.labelCopyright.Text = AssemblyCopyright;
this.labelCompanyName.Text = AssemblyCompany;
this.textBoxDescription.Text = AssemblyDescription;
}
#region Assembly Attribute Accessors
public string AssemblyTitle
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
if (titleAttribute.Title != "")
{
return titleAttribute.Title;
}
}
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
}
}
public string AssemblyVersion
{
get
{
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
public string AssemblyDescription
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyDescriptionAttribute)attributes[0]).Description;
}
}
public string AssemblyProduct
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyProductAttribute)attributes[0]).Product;
}
}
public string AssemblyCopyright
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
}
}
public string AssemblyCompany
{
get
{
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
if (attributes.Length == 0)
{
return "";
}
return ((AssemblyCompanyAttribute)attributes[0]).Company;
}
}
#endregion
private void okButton_Click(object sender, EventArgs e)
{
Close();
}
}
}
I found a neat and simple to implement solution using the example in my question provided by microsoft.
I created this application context class that is responsible for everything in the application and I use this instead of a form in the Application.Run() as shown below.
To achieve the behavior in the question, I am using a second form that is hidden and only the taskbar icon is shown. If the user wants to see how the process is doing, they can click the taskbar icon and see the logging window, which is actually the ConfigurationApplierForm in the example bellow.
class AnApplicationContext: ApplicationContext
{
private Form _currentForm;
Note the constructor is private, the main is inside this class and declared static.
private AnApplicationContext()
{
Application.ApplicationExit += new EventHandler(this.OnApplicationExit);
// choose which form to show based on arguments
if(Environment.GetCommandLineArgs().Contains("-apply"))
{
_currentForm = new ConfigurationApplierForm();
}
else
{
_currentForm = new ConfigurationActionManagerForm();
}
// initialize the form and attach event handlers
_currentForm.FormClosed += new FormClosedEventHandler(this.OnCurrentFormClosed);
_currentForm.ShowDialog();
}
Main is here, a little bit different from the original. Notice the argument in the Run method
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// context is passed instead of a form
Application.Run(new AnApplicationContext());
}
private void OnCurrentFormClosed(object sender, EventArgs e)
{
ExitThread();
}
private void OnApplicationExit(object sender, EventArgs e)
{
/* is there anything to do when all forms are closed
and the application is going to die?*/
}
}
Also, we need to tell the project that this is the startup project.
Project Properties -> Application -> Startup Project

Categories

Resources