Open GL and Windows Forms Programming Roger Crawfis

  • Slides: 36
Download presentation
Open. GL and Windows Forms Programming Roger Crawfis

Open. GL and Windows Forms Programming Roger Crawfis

Creating a nice GUI • The next several slides will walk you thru a

Creating a nice GUI • The next several slides will walk you thru a particular design that I like for my applications. • The order can be a little finicky, so if you mess up, delete all files and start over!!! • The design consists of a GUI panel on the left and a view panel on the right, with a status bar and a main menu.

Note: VS 2003 shown • The following slides and images are old, create a

Note: VS 2003 shown • The following slides and images are old, create a new project using 2005. • Also, note there is a new Split. Container that works better for this style of GUI. – Use it rather than the Panel/Splitter/Panel approach.

Create a new Project • Start Visual Studio. NET

Create a new Project • Start Visual Studio. NET

Create a new Project • Select a C++ Windows Forms Application

Create a new Project • Select a C++ Windows Forms Application

Add your GUI elements • Resize the Form to be about 800 by 600,

Add your GUI elements • Resize the Form to be about 800 by 600, or whatever you like. • In this order, add the following elements from the Toolbox->Windows Forms. – Status. Bar – Panel – Splitter – Panel

GUI design • In the Properties window you can make changes to the content

GUI design • In the Properties window you can make changes to the content and appearance of these controls. – Change the Back. Color of the splitter. – Change the Dock property of panel 1 to Left. – Change the Dock property of panel 2 to Fill (the center icon). – Click on the Collections property of the status. Bar and add three tabs. Type in some text. – On the Status. Bar properties, set Show. Panels to true.

GUI Design • Build (Build->Build Solution) and run (Debug->Start without Debugging) your application. It

GUI Design • Build (Build->Build Solution) and run (Debug->Start without Debugging) your application. It should look something like this:

GUI Design • In the GUI panel, let’s make one large tabbed dialogue. •

GUI Design • In the GUI panel, let’s make one large tabbed dialogue. • Drag a tab. Control over to the GUI panel. • Set its dock to Fill. • In the properties select the Collection button and add four tab panels. – – Lab 2 Extra Grading Readme

GUI Design • Your program should now look like this. New Title added Background

GUI Design • Your program should now look like this. New Title added Background image added

Examine the code • Okay. We have the basic lay-out. Notice we have not

Examine the code • Okay. We have the basic lay-out. Notice we have not done any programming yet. • Right-click the Form 1. h file in the Solution panel and select Edit Code. We have: – A public constructor – A protected Dispose – A private Initialize. Components • What is this! The source code is in the. h file? • Look at the Form 1. cpp file.

Initialize. Components • There is a tree view structure in the code views with

Initialize. Components • There is a tree view structure in the code views with Visual Studio. You can collapse a method, class or region of code to hide the details as you work on other parts of the code. • The Initialize. Components method is collapsed by default. This is automatically generated by the Designer Window. It has all of the natty details on setting up the controls. • Uncollapse it and examine the code.

Lab 2 • Okay, we have the basic lay-out, now we need to embed

Lab 2 • Okay, we have the basic lay-out, now we need to embed the business logic. • What are the lab requirements? • More specifically, what controls do we need? – Specifying the number of lines / points. – Reading in (selecting) an image file. – Specifying the line-width or point size. – Specify two color values.

Lab 2 Controls • Selecting an image file. – Possible Options: 1. Add a

Lab 2 Controls • Selecting an image file. – Possible Options: 1. Add a text box and have the user type the path / filename into the textbox. (umm Yuck!!!) 2. Pre-load a set of image files and have the user select from this set. (lacks flexibility). 3. Bring up a dialog asking the user to select an image. Limit the selection to only the proper type of files. • • How do we bring up the dialog? What do we have to do to show the dialog?

Image file Dialogue • • This is why you use a higher-level API. With

Image file Dialogue • • This is why you use a higher-level API. With windows forms and. Net 1. 1 this is really trivial. Follow these simple steps: 1. Drag an Open. File. Dialog control to anywhere on your Form. Notice that it places it in a special window pane below your design. 2. Drag a Button control to the Lab 2 tab panel. This will be used to bring up the dialog.

Image file Dialogue • Adjust the Button’s properties: 1. • Change the text to

Image file Dialogue • Adjust the Button’s properties: 1. • Change the text to “Load Texture” Adjust the Open. File. Dialog’s properties 1. 2. 3. 4. 5. Change the Title to “Select an image file for the texture” In the Filter property add a string to aid in the right file type selection. Something like this: “All files (*. *)|*. *|Jpeg (*. jpg)|*. jpg|Png (*. png)|*. png”. Each pair here has the format (Text string to display | regular expression). Note that adding a space before the asterisk results in a different regular expression. Set the Filter index to 2, such that jpeg is the default format. Set the Add. Extension to False. Make sure the Multiselect property is False.

Image file Dialogue • Okay, we have now defined everything, such that the constructor

Image file Dialogue • Okay, we have now defined everything, such that the constructor is called and the properties are set. Nothing will happen though, we need to add some logic. • Double click the “Load Texture” button. This adds some template code and brings up the source code window (Form 1. h). • It also added this line inside the Initialize. Components: this->button 1 ->Click += new System: : Event. Handler(this, button 1_Click); • Add the following line in button 1_Click: this->open. File. Dialog 1 ->Show. Dialog();

Image file Dialogue • Run and test the program. Clicking on the button should

Image file Dialogue • Run and test the program. Clicking on the button should bring up the open. File. Dialog.

Image file Dialogue • Note that the dialog simply selects the file, it does

Image file Dialogue • Note that the dialog simply selects the file, it does not open it or perform any logic yet. • We will address actually opening the file, reading in the image and creating a texture map from it later.

Lab 2 Controls • Number of primitives – There are several choices here. •

Lab 2 Controls • Number of primitives – There are several choices here. • Textbox (you would need to validate that it only contained numbers). • Numeric Up/Down control (it has two speeds, both of which you can configure in the Properties page). • Trackbar or slider control (you may need to provide a text label that indicates the current value). – The reference lab uses both a numeric. Up. Down and a Trackbar tightly coupled together.

Accessibility • Most controls have accessibility features built into them. • This allows for

Accessibility • Most controls have accessibility features built into them. • This allows for a mouse free control. • You can hit the tab key to reach the Numeric. Up. Down and Trackbar controls and then use the arrow keys to change their values. • Holding down the key accelerates the change.

Trackbar • Let’s use the trackbar. • Drag a track. Bar control to the

Trackbar • Let’s use the trackbar. • Drag a track. Bar control to the Lab 2 tab panel. • In the Properties page: – – – Set the Maximum value to 100, 000 (or higher) Set the (initial or current) Value to 10, 000 Set the Large. Change to 5, 000 Set the Small. Change to 1, 000 Set the Tick Frequency to 10, 000 • Also add a Label control (static text) above the track. Bar to describe its purpose.

Trackbar • We should now have something like:

Trackbar • We should now have something like:

Trackbar • Okay, we have a control and it can change values, etc. but

Trackbar • Okay, we have a control and it can change values, etc. but we do not have anything useful connected to it. Business logic: • – There are many ways you can use this: 1. 2. 3. The lazy way – simply read the control’s value whenever you need it. This mixes the business logic and the GUI logic. The global document way – Whenever the value changes, change a corresponding data value in some document class. This still mixes the logic. Bad data hiding. The document/view way – Whenever the value changes, call a method on the document’s class. The document now knows it’s value has changed. • • Perform some action (update display, verify data, etc. ) Keep a history for undo/redo.

Document Class • Okay, I will admit it, I used method #1 in the

Document Class • Okay, I will admit it, I used method #1 in the reference lab. But I am going to make you follow method #3. • Create and add a new class to your project. – Right-click on the solution and select Add->Add Class from the context menu. – Select a generic C++ class and give a name. – Change it to managed C++ by changing class to public __gc class in the header file. – Add the following private members: – int num. Primitives; – float line. Width; – Color color 1, color 2;

Document Class • You also need to include: using namespace System: : Drawing; •

Document Class • You also need to include: using namespace System: : Drawing; • Add public methods to set (and optionally get) each of these. For instance: void Set. Num. Primitives( const int n. Lines ) { num. Primitives = n. Lines; } •

Document Class • Okay, now we can wire that to the track. Bar. •

Document Class • Okay, now we can wire that to the track. Bar. • Double-click the track. Bar in the designer. • In the code template, add something like: impressionism. Doc->Set. Num. Primitives( track. Bar 1 ->Value ); • We need to create and add an instance of our document. Declare a private pointer to an instance. private: Impressionism *impressionism. Doc; • In the constructor for Form 1 create a new instance. impressionism. Doc = new Impressionism();

Lab 2 Status • Okay, we are about 1/3 of the way to having

Lab 2 Status • Okay, we are about 1/3 of the way to having some implementation for lab 2. • You need to add an Open. GLPanel as in HW #1 and Lab 1 and create the Open. GL drawing calls. • We also still need to add the image file and texture map, as well as the other controls.

Done • The End • Ignore the following slides!!

Done • The End • Ignore the following slides!!

Ohio. State: : Open. GLPanel • The simplest possible canvas or rendering context. •

Ohio. State: : Open. GLPanel • The simplest possible canvas or rendering context. • No assumptions are made (single buffer, double buffer, etc. ) • Burden on user to provide all information and event processing. • Can be used as a base-class for more intelligent classes.

Open. GLPanel : Forms: : Control • All of the functionality of a Control.

Open. GLPanel : Forms: : Control • All of the functionality of a Control. • Creates the Open. GL rendering context. • Overrides: – protected On. Paint. Background – protected On. Paint – protected On. Resize – public set_Back. Color property

Public methods • Open. GLPanel( PIXELFORMATDESCRIPTOR pfd ); • void Add. Pre. Render. Callback(

Public methods • Open. GLPanel( PIXELFORMATDESCRIPTOR pfd ); • void Add. Pre. Render. Callback( Open. GLRender. Callback *callback ); • void Add. Post. Render. Callback( Open. GLRender. Callback *callback ); • void Add. Resize. Callback( Open. GLResize. Callback *callback ); • int Get. Frame. Number() { return frame. Number; }; • void Make. Current(); • void Swap. Buffers();

The Constructor • No assumptions, so the user passes in the PIXELFORMATDESCRIPTOR which indicates

The Constructor • No assumptions, so the user passes in the PIXELFORMATDESCRIPTOR which indicates the number of color bits, stencil bits, etc. • Make sure the dwflag entry includes PFD_SUPPORT_OPENGL. • See the sample and the MSDN help for more information.

Callbacks • The Open. GLPanel is structured around registered callbacks. These are pointers to

Callbacks • The Open. GLPanel is structured around registered callbacks. These are pointers to a function, or delegates. • Two publicly defined Delegate types: – public __delegate void Open. GLRender. Callback( const int frame. Number ); – public __delegate void Open. GLResize. Callback( const int width, const int height ); • These are really type definitions: – A pointer to a function that returns void and takes one parameter of type const int.

Callbacks • Like any other type, you create and instance: thank-you garbage collection gl.

Callbacks • Like any other type, you create and instance: thank-you garbage collection gl. Panel->Add. Render. Callback( new Ohio. State: : Open. GLRender. Callback( this, Draw. Scene ) ); • Draw. Scene is a public method of this, or Form 1 here. • Can also use static methods, in which case, this would be replaced with the class type.

Using Open. GLPanel • Checklist: – Create a Forms: : Panel (in the designer).

Using Open. GLPanel • Checklist: – Create a Forms: : Panel (in the designer). – In the Form 1 constructor: • Create an Open. GLPanel and add it to the panel (call this gl. Panel). • Put all of your drawing code into a method that returns void and takes a single const int. • Create a callback instance and add it to gl. Panel. • Create a resize function, wrap it in a callback and add it to gl. Panel.