1. Trang chủ
  2. » Công Nghệ Thông Tin

C++ Programming for Games Module II phần 6 ppt

31 269 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề C++ Programming for Games Module II phần 6 ppt
Trường học University of Science and Technology of Vietnam (USTH)
Chuyên ngành C++ Programming for Games
Thể loại Lecture notes
Năm xuất bản Unknown
Thành phố Hà Nội
Định dạng
Số trang 31
Dung lượng 1,22 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Each shape will know how to draw itself correctly based on its concrete dynamic type that is, if it is a LineShape then it will know to draw a line, if it is a RectShape then it will kno

Trang 1

Next, we create a global vector of Shape pointers, gShapes, which will maintain all the shapes we have created so that we can draw all the shapes whenever a WM_PAINT message is generated In addition, we keep a global shape pointer gShape, which will be the temporary shape we will draw while the user is moving the mouse around and deciding where exactly to make the shape permanent Notice how we can talk about shapes in general This is because of the polymorphism Each shape will know how to draw itself correctly based on its concrete dynamic type (that is, if it is a LineShape then it will know to draw a line, if it is a RectShape then it will know to draw a rectangle, and so on)

Figure 15.17: User can select which type of shape to draw via the menu

We need to keep track of which primitive menu item is selected so that we know which kind of shape to create To facilitate this, we keep a global variable that keeps track of the currently selected primitive:

int gCurrPrimSel = ID_PRIMITIVE_LINE;

Later in the WM_LBUTTONDOWN message handler, we create the shape based on the currently selected type:

Trang 2

int gCurrPenColSel = ID_PENCOLOR_BLACK;

int gCurrBrushColSel = ID_BRUSHCOLOR_BLACK;

int gCurrPenStyleSel = ID_PENSTYLE_SOLID;

int gCurrBrushStyleSel = ID_BRUSHSTYLE_SOLID;

The values to which these global variables are initialized are the program’s “default” selected values Therefore, we also need to check the corresponding menu items at the start of the program so that the default selections are checked We implement this functionality in the WM_CREATE message:

case WM_CREATE:

CheckMenuItem(ghMenu, ID_PRIMITIVE_LINE, MF_CHECKED);

CheckMenuItem(ghMenu, ID_PENCOLOR_BLACK, MF_CHECKED);

CheckMenuItem(ghMenu, ID_BRUSHCOLOR_BLACK, MF_CHECKED);

CheckMenuItem(ghMenu, ID_PENSTYLE_SOLID, MF_CHECKED);

CheckMenuItem(ghMenu, ID_BRUSHSTYLE_SOLID, MF_CHECKED);

return 0;

This way, the default-selected menu items will be checked when the window is first created

We also keep a global instance of a LOGPEN and LOGBRUSH:

CheckMenuItem(ghMenu, ID_PENSTYLE_DOTTED, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrPenStyleSel, MF_UNCHECKED);

When a shape is created, we pass gLogPen and gLogBrush into the constructor For example,

gShape = new LineShape(p0, p1, gLogPen, gLogBrush);

Because we update gLogPen and gLogBrush immediately as the user selects new colors and styles from the menu, these objects always reflect the current user menu selections Therefore, any object created will always be created with the currently selected pen and brush colors, and pen and brush styles, which is the exact functionality which should happen

The majority of code in the paint-drawing program has to do with the menu and updating the primitive type that is selected, the colors of the pen and brush, and the styles of the pen and brush The code is

Trang 3

long, but simple For example, the part of the code that checks for which primitive type the user selected is as follows:

CheckMenuItem(ghMenu, ID_PRIMITIVE_LINE, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrPrimSel, MF_UNCHECKED);

gCurrPrimSel = ID_PRIMITIVE_LINE;

return 0;

case ID_PRIMITIVE_RECTANGLE:

CheckMenuItem(ghMenu, ID_PRIMITIVE_RECTANGLE, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrPrimSel, MF_UNCHECKED);

gCurrPrimSel = ID_PRIMITIVE_RECTANGLE;

return 0;

case ID_PRIMITIVE_ELLIPSE:

CheckMenuItem(ghMenu, ID_PRIMITIVE_ELLIPSE, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrPrimSel, MF_UNCHECKED);

gCurrPrimSel = ID_PRIMITIVE_ELLIPSE;

return 0;

It is all quite redundant We simply update which menu items should be checked, and update the global

gCurrPrimSel variable so that it reflects the currently selected item We execute similar code for the pen color menu items, the brush color menu items, the pen style menu items, and the brush style menu items As mentioned, the code is all largely the same, so we will not discuss it further

You should now be able to understand the drawing program The code is listed in Program 15.5

Program 15.5: Paint drawing program

const COLORREF BLACK = RGB(0, 0, 0);

const COLORREF WHITE = RGB(255, 255, 255);

const COLORREF RED = RGB(255, 0, 0);

const COLORREF GREEN = RGB(0, 255, 0);

const COLORREF BLUE = RGB(0, 0, 255);

HWND ghMainWnd = 0;

HINSTANCE ghAppInst = 0;

HMENU ghMenu = 0;

Trang 4

vector<Shape*> gShapes;

Shape* gShape = 0;

bool gMouseDown = false;

int gCurrPrimSel = ID_PRIMITIVE_LINE;

int gCurrPenColSel = ID_PENCOLOR_BLACK;

int gCurrBrushColSel = ID_BRUSHCOLOR_BLACK;

int gCurrPenStyleSel = ID_PENSTYLE_SOLID;

int gCurrBrushStyleSel = ID_BRUSHSTYLE_SOLID;

CheckMenuItem(ghMenu, ID_PRIMITIVE_LINE, MF_CHECKED);

CheckMenuItem(ghMenu, ID_PENCOLOR_BLACK, MF_CHECKED);

CheckMenuItem(ghMenu, ID_BRUSHCOLOR_BLACK, MF_CHECKED); CheckMenuItem(ghMenu, ID_PENSTYLE_SOLID, MF_CHECKED);

CheckMenuItem(ghMenu, ID_BRUSHSTYLE_SOLID, MF_CHECKED);

return 0;

case WM_COMMAND:

switch( LOWORD(wParam) ) {

//=======================================

// File Menu //=======================================

return 0;

case ID_PRIMITIVE_RECTANGLE:

Trang 5

CheckMenuItem(ghMenu, ID_PRIMITIVE_RECTANGLE, MF_CHECKED); CheckMenuItem(ghMenu, gCurrPrimSel, MF_UNCHECKED); gCurrPrimSel = ID_PRIMITIVE_RECTANGLE;

return 0;

case ID_PRIMITIVE_ELLIPSE:

CheckMenuItem(ghMenu, ID_PRIMITIVE_ELLIPSE, MF_CHECKED); CheckMenuItem(ghMenu, gCurrPrimSel, MF_UNCHECKED); gCurrPrimSel = ID_PRIMITIVE_ELLIPSE;

return 0;

//=======================================

// Pen Colors //=======================================

case ID_PENCOLOR_BLACK:

CheckMenuItem(ghMenu, ID_PENCOLOR_BLACK, MF_CHECKED); CheckMenuItem(ghMenu, gCurrPenColSel, MF_UNCHECKED); gCurrPenColSel = ID_PENCOLOR_BLACK;

return 0;

//=======================================

// Brush Colors //=======================================

case ID_BRUSHCOLOR_BLACK:

CheckMenuItem(ghMenu, ID_BRUSHCOLOR_BLACK, MF_CHECKED); CheckMenuItem(ghMenu, gCurrBrushColSel, MF_UNCHECKED); gCurrBrushColSel = ID_BRUSHCOLOR_BLACK;

return 0;

Trang 6

case ID_BRUSHCOLOR_RED:

CheckMenuItem(ghMenu, ID_BRUSHCOLOR_RED, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrBrushColSel, MF_UNCHECKED); gCurrBrushColSel = ID_BRUSHCOLOR_RED;

return 0;

//=======================================

// Pen Styles //=======================================

case ID_PENSTYLE_SOLID:

CheckMenuItem(ghMenu, ID_PENSTYLE_SOLID, MF_CHECKED);

CheckMenuItem(ghMenu, gCurrPenStyleSel, MF_UNCHECKED); gCurrPenStyleSel = ID_PENSTYLE_SOLID;

gLogPen.lopnStyle = PS_DASH;

return 0;

//=======================================

// Brush Styles //=======================================

case ID_BRUSHSTYLE_SOLID:

CheckMenuItem(ghMenu, ID_BRUSHSTYLE_SOLID, MF_CHECKED); CheckMenuItem(ghMenu, gCurrBrushStyleSel, MF_UNCHECKED); gCurrBrushStyleSel = ID_BRUSHSTYLE_SOLID;

Trang 7

gCurrBrushStyleSel = ID_BRUSHSTYLE_DIAGONAL; gLogBrush.lbStyle = BS_HATCHED;

// Create the shape based on what shape the user has

// selected in the menu

switch( gCurrPrimSel ) {

// Current mouse position is stored in the lParam p1.x = LOWORD(lParam);

p1.y = HIWORD(lParam);

// Update the end point of the current temporary

// shape based on the mouse position

gShape->setEndPt(p1);

// Repaint the window so the temporary shape

Trang 8

// is redrawn interactively as the mouse moves InvalidateRect(hWnd, 0, true);

} return 0;

// Update the end point of the current temporary shape

// based on the mouse position

gShape->setEndPt(p1);

// The user lifted the left mouse button, so the shape // becomes permanent, so add it to the shape container gShapes.push_back( gShape );

// Repaint the window so the new permanent shape will // be displayed.

// Draw all the permenent shapes

for(int i = 0; i < gShapes.size(); ++i) gShapes[i]->draw(hdc);

// Forward any other messages we didn't handle to the

// default window procedure

return DefWindowProc(hWnd, msg, wParam, lParam);

}

Trang 9

// WinMain: Entry point for a Windows application

int WINAPI

WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR cmdLine, int showCmd)

wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);

wc.hCursor = ::LoadCursor(0, IDC_ARROW);

// Step 4: Create the window, and save handle in globla

// window handle variable ghMainWnd

ghMenu = LoadMenu(ghAppInst, MAKEINTRESOURCE(IDR_MENU1));

ghMainWnd = ::CreateWindow("MyWndClassName", "My Paint Program",

// Step 6: Enter the message loop and don't quit until

// a WM_QUIT message is received

Trang 10

15.8 Summary

1 Windows sends a window a WM_PAINT message whenever a window needs to repaint its client area (or a region of the client area) A window may need to repaint its client area when it is resized, or when a previously obscured part of it becomes visible The program can explicitly send a WM_PAINT message with the InvalidateRect function A Windows program should know how to draw all of its data, so that if all or part of its client area drawing data is erased (by resizing the window or obscuring the window, for example) it can all be restored at the appropriate time when the next WM_PAINT is sent to the window

2 A device context is a software abstraction of a display device, such as the video card or a printer

We do all drawing operations through the device context (abbreviated as DC) As such, we must pass a handle to a device context (HDC) to all GDI related functions One way to obtain an HDC is with the BeginPaint function

3 To draw text onto the client area of a window, we use the TextOut function To draw a line onto the client area of a window, we use the MoveToEx function to specify the line’s start point, and the LineTo function to specify the line’s end point To draw a rectangle onto the client area

of a window, we use the Rectangle function Finally, to draw an ellipse onto the client area of

a window, we use the Ellipse function Recall that when specifying an ellipse we specify its bounding rectangle; that is, an ellipse that fits tightly into that bounding rectangle will be drawn

4 A bitmap is a matrix of color elements, or pixels To load a bitmap we must first load the bmp file as a resource After that, we can load the bitmap resource into our program and obtain a handle to it with the LoadBitmap function To copy the pixels in the bitmap to the window’s client area we use the BitBlt function When we are finished with a bitmap, we should delete

it with the DeleteObject function

5 Pens and brushes allow us to alter the way in which shapes are drawn with GDI In particular,

we can draw shapes with different colors, styles, and patterns Pens are used to draw lines, curves, and also to draw the border of solid shapes like rectangles and ellipses The properties of

a pen are described with the LOGPEN structure Brushes are used to fill in the interiors of solid shapes like rectangles and ellipses The properties of a brush are described with the LOGBRUSH

structure

6 Menus allow the user to make selections To load a menu, we must first create a menu resource

in the Visual C++ resource editor After we have finished editing the menu resource, we can load it with the LoadMenu function To attach the menu to a window, we can pass in a handle to the menu (HMENU returned from LoadMenu) to the hMenu parameter of CreateWindow We can check/uncheck a menu item with the CheckMenuItem function When the user selects a menu item, Windows sends the window a WM_COMMAND message The lower 16-bits of the

wParam parameter of this message specify the numeric resource ID of the menu item that was selected In this way, we can test which menu item was selected and execute the appropriate consequential code

Trang 11

15.9.3 Cube

Figure 15.18 shows a cube As you can see, a cube is made up of twelve lines Write a function that draws a cube to the client area of a window Then add a new “cube” primitive to Program 15.5 that the user can select from the menu and draw

Figure 15.18: A cube outline drawn with twelve lines

15.9.4 Undo Feature

Modify Program 15.5 by implementing an undo feature that erases the last shape that was drawn (add an undo menu item) Be sure to avoid memory leaks

Trang 12

Chapter 16

Introduction to Dialogs and Controls

Trang 13

Introduction

The final Win32 API-related topics we need to discuss are dialog boxes and controls A dialog box is a type of window, which is commonly used to display a variety of controls the user can set and configure Figure 16.1 shows a dialog box that is used in the demos programs for the DirectX Graphics Programming course here at Game Institute

Figure 16.1: An example of a dialog box with controls

As you can see from Figure 16.1, controls and dialog boxes go hand in hand

Chapter Objectives

• Learn how to create modal and modeless dialog boxes, and how to distinguish between the two

• Discover how to create and design dialog boxes with the Visual C++ resource editor

• Become familiar with several Win32 controls such as static text controls, picture box controls, edit box controls, radio button controls, button controls, and combo box controls

Note: As with the previous two Win32 API chapters in this book, we cannot possibly cover everything

Therefore, if you are interested in learning how to create the various other Win32 controls you may have seen, but which we do not cover here (e.g., slider controls, color controls, spin controls, tree controls), then you will need to consult MSDN or a book devoted to the Win32 API The standard “bible” text on the Win32 API is Programming Windows 5 th Edition By Charles Petzold

Trang 14

16.1 Modal Dialog Boxes; The Static Text Control; The Button Control

A modal dialog box is a dialog box that does not close until the user has made some sort of selection

(i.e., the user cannot switch to another window until the modal dialog box has ended) Typically, an application will use a modal dialog box when it needs immediate input from the user, and cannot continue until it receives that input For our first program, we will illustrate a modal dialog box by creating a simple window that can display an “About” dialog box Figure 16.2 shows our goal:

Figure 16.2: The dialog box is launched by going to File and selecting the “About” menu item

16.1.1 Designing the Dialog Box

Dialogs are created and edited in the Visual C++ Resource editor, just like menus and icons Select the

Add Resource button and select a “Dialog” from the “Add Resource” dialog and then select the “New”

button—Figure 16.3

Trang 15

Figure 16.3: Select “Dialog” and then press the “New” button

At this point, the Dialog Editor will open up Before we begin designing the dialog box, let us rename the dialog resource ID to IDD_ABOUTBOX—Figure 16.4

Figure 16.4: Renaming the dialog resource ID to IDD_ABOUTBOX

Now, design your dialog box as Figure 16.5 shows

Ngày đăng: 05/08/2014, 09:45

TỪ KHÓA LIÊN QUAN