Computer Engineering II Developing Windows Applications using MFC
FH-Prof. Christian V. Madritsch Systems Engineering
www.cti.ac.at/rts
Copyright Notice All rights reserved. No part of this publication
may be reproduced, stored in a retrieval system or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the author except for student usage. Copyright © 2008 by Christian V. Madritsch
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
2
1
Bibliography Inside Visual C++, David Kruglinski,
Microsoft Press, current distribution On the web: http://www.functionx.com/visualc/ http://www.borngeek.com/code/
31.03.2008
[email protected]
3
Windows Programming using C: Win32 API Subsystem Win32 API Subsystem: 1800 Functions Application Entry-Point: WinMain(); Construction of the Main Window Processing of Windows Messages Graphics Device Interface – GDI: Abstraction of Graphics and Printing GDI Function Interface - Device Context Resources Support WYSIWYG-Editor Menu, Dialogs, Control Bar, etc. 31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
4
2
Win32 API Example: Hello World One Window and Child Window GDI text output “Hello World” Application Title and Icon Menu Bar Minimize/Maximize/
Close
31.03.2008
[email protected]
5
Win32 API Example: Hello World (i) int WinMain(HINSTANCE hInstance, int nCmdShow) MSG msg;
{
// Perform instance initialization: if (!InitApplication(hInstance)) { return (FALSE); } // Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); } // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); }
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
6
3
Win32 API Example: Hello World (ii) int WinMain(HINSTANCE hInstance, int nCmdShow) { MSG msg; BOOL InitApplication(HINSTANCE hInstance) { WNDCLASS wc; HWND hwnd;
// Perform instance initialization: if (!InitApplication(hInstance)) { return (FALSE); }
wc.style wc.lpfnWndProc wc.cbClsExtra wc.cbWndExtra wc.hInstance wc.hIcon
CS_HREDRAW | CS_VREDRAW; (WNDPROC)WndProc; 0; 0; hInstance; LoadIcon (hInstance, szAppName); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = szAppName; wc.lpszClassName = szAppName; return RegisterClass(&wc);
// Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); } // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
= = = = = =
}
return (msg.wParam); }
31.03.2008
[email protected]
7
Win32 API Example: Hello World (iii) int WinMain(HINSTANCE hInstance, int nCmdShow) { MSG msg;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd;
// Perform instance initialization: if (!InitApplication(hInstance)) { return (FALSE); }
hInst = hInstance; hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return (FALSE); }
// Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); } // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return (TRUE); }
return (msg.wParam); }
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
8
4
Win32 API Example: Hello World (iv) int WinMain(HINSTANCE hInstance, int nCmdShow) { MSG msg;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc;
// Perform instance initialization: if (!InitApplication(hInstance)) { return (FALSE); }
switch (message) { case WM_PAINT: hdc = BeginPaint (hWnd, &ps); TextOut(hdc, 100, 100, "Hello World!"); EndPaint (hWnd, &ps); break;
// Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); }
case WM_DESTROY: PostQuitMessage(0); break;
// Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); }
return (msg.wParam); }
31.03.2008
[email protected]
9
Windows Programming using C++: MFC and Application Framework Microsoft Foundation Class Library: More than 200 classes Encapsulation of most Win32 API functions Class hierarchy based on CObject General Classes (CString, CTime, …) Evolution with Win32 API Application Framework: Standardized application structures (SDI, MDI) Application- and Class-Wizard support reduces development time 31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
10
5
MFC Library Overview
31.03.2008
[email protected]
11
MFC Library: CCmdTarget
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
12
6
MFC Library: CWnd
31.03.2008
[email protected]
13
MFC Library: Other classes
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
14
7
MFC Example: Hello World class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; class CMyFrame : public CFrameWnd { public: CMyFrame(); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() };
#include #include "gerericmfc.h" BOOL CMyApp::InitInstance() { m_pMainWnd = new CMyFrame(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } CMyFrame::CMyFrame() { Create(NULL, "Generic MFC"); } void CMyFrame::OnPaint() { CPaintDC dc(this); dc.TextOut(100,100,"Hello World"); } CMyApp theApp; BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP()
31.03.2008
[email protected]
15
Windows Programming using C#: .NET Framework .NET Framework: Abstraction Layer between the OS and the App to enable:
Platform independence and portability Code and Type safety = Execution safety
Mixed Language development
C# Language: Evolution of C++
component oriented development
Key paradigms:
“Everything is a class” and “There are no pointers”
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
16
8
.NET Framework: Structural Overview .cpp
.il
C# Language
Intermediate Language Compiler
.NET Framework Class Library
Common Type System CTS
.exe
Just In Time JIT Compiler
+
Common Language Runtime CLR
Platform Win32, MAC, Linux,
Common Language Specification CLS
C++ Language
31.03.2008
VB Language
Delphi Language
Platform Specific
[email protected]
17
.NET Framework Example: Hello World using System; public class Hello { public static void Main() { Console.WriteLine("Hello World"); } }
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
18
9
Development Components
31.03.2008
[email protected]
19
Application Wizard (i)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
20
10
Application Wizard (ii)
31.03.2008
[email protected]
21
Application Wizard (iii)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
22
11
Application Wizard (iv)
31.03.2008
[email protected]
23
Application Wizard (v)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
24
12
Application Wizard (vi)
31.03.2008
[email protected]
25
Application Wizard (vii)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
26
13
Application Wizard (viii)
31.03.2008
[email protected]
27
Application Wizard (ix)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
28
14
Resulting Application Framework
31.03.2008
[email protected]
29
Exercise 1 Create a MFC-based SDI Application: User input: Left Mouse-button Down
User input: Right Mouse-button Down
Delete the circle
Condition 1:
Draw a circle of constant size at the position of the mouse cursor
If the window gets moved or redrawn, the circle stays persistent
Condition 2:
There is a maximum of one circle visible at a time
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
30
15
Command Handlers Messages
Prerequs: Properties Window: Alt + Enter Choose CxView Class in Class View
void CTestView::OnLButtonDown(CPoint point) { SavePoint(point); InvalidateRect(NULL); } void CTestView::OnDraw(CDC* pDC) { pDC->Ellipse(m_point.x, m_point.y, m_point.x+100, m_point.y+100); }
31.03.2008
[email protected]
31
Menu Resources (i)
Prerequs: Choose Resource View 31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
32
16
Menu Resources (ii)
31.03.2008
[email protected]
33
Menu Resources (iii) Events
Prerequs: Choose View Class in Class View
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
34
17
Exercise 1 - Extensions Extension 1:
User input: Left Mouse Button Down
User input: Left Mouse Button Up
Draw a circle with the size Pos_1.x, Pos_1.y and Pos_2.x, Pos_2.y
Store the actual position of the mouse cursor (Pos_1) Store the actual position of the mouse cursor (Pos_2)
Extension 2:
User input: Mouse Move (and Left Mouse Button Down)
Update the Circle Size while the mouse is moving
Extension 3:
There are more than one circles visible at a time
Extension 4:
Create a menu entry which allows the selection of different shapes (e.g. Circles, Rectangles)
31.03.2008
[email protected]
35
Exercise 2 Extend Application Exercise 1: User input: Menu Shape/ShapeCount A dialog box opens:
“Enter the maximum number of shapes” – Edit control
OK button to save selection CANCLE button to discard selection
Condition 1:
Default maximum number of shapes: 10
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
36
18
Exercise 2
31.03.2008
[email protected]
37
Connect Dialog to Class Prerequs: Double Click on Dialog Resource
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
38
19
Edit Resource (i)
31.03.2008
[email protected]
39
Edit Resource (ii)
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
40
20
Connect Edit Control to Class Member Prerequs: Right Click on Edit Control
31.03.2008
[email protected]
41
Open Dialog in View Class Prerequs: Right Click on View Class to Add Variable
void CTestView::OnShapesShapecount() { dlgShapeCount.m_shapecount = m_ShapeCount; dlgShapeCount.DoModal(); m_ShapeCount = dlgShapeCount.m_shapecount; }
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
42
21
Exercise 2 - Extensions Extension 1: Increase dialog functionality by adding complex controls
Slider: to change line width Check Box/Radio Button: to select shape List Box: to change line color Picture: to display a logo
31.03.2008
[email protected]
43
FormView Class Properties Enables a “dialog like” communication with UI
control elements:
Use View Class Constructor to initialize by “Value” connected control items (e.g. Edit Control) Use OnInitialUpdate member function to initialize by “Class” connected control items (e.g. Slider Control) UpdateData performs data exchange between
dialog items and member variables (by Value only)
UpdateData(TRUE); // to retrieve data from dialog UpdateData(FALSE); // to initialize data in dialog 31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
44
22
Exercise 3 Create a MFC-based SDI FormView application
to communicate via the serial COM interface (using non-overlapped I/O):
Config-Button opens Dialog to configure RS232 settings (COM, BaudRate, Parity, etc.) Init-Button initializes RS232 interface Shutdown-Button closes RS232 communication Send-Button to send text
Edit-Control to enter text to be sent
Receive-Button to receive text
Edit-Control (read-only) to display received text
31.03.2008
[email protected]
45
Exercise 3 - Extensions Modify previous application to support
overlapped I/O:
Create a Receive Thread, which automatically receives text and displays it in the Receive Edit Control Periodically (T=1s) send the text entered in the Send Edit Control
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
46
23
Threads and Events Create a Thread: CWinThread* = AfxBeginThread( ThreadFuntion, // function pointer GetSafeHwnd()); // LPVOID SetThreadPriority (HANDLE hThread, int nPriority);
Event Management: HANDLE CreateEvent( NULL, BOOL bManualReset, // manual or auto reset BOOL bInitialState, // TRUE or FALSE NULL); SetEvent(hEvent); ResetEvent(hEvent); WaitForSingleObject(hEvent, INFINITE); // msec
31.03.2008
[email protected]
47
User Defined Messages Message definition: #define WM_MY_MESSAGE WM_USER + 1
Message Handling: BEGIN_MESSAGE_MAP( CMyWnd, CMyParentWndClass) //{{AFX_MSG_MAP( CMyWnd ON_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //}}AFX_MSG_MAP END_MESSAGE_MAP( )
Message Handler: LRESULT OnMyMessage(WPARAM wp, LPARAM lp);
Send Message: PostMessage(hWnd, WM_MYMESSAGE,0,0);
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
48
24
Using Timers Setting and resetting: SetTimer(UINT nIDEvent, UINT nElapse); KillTimer(UINT nIDEvent);
// Timer ID // msec
Handling Time Event Messages: Connect WM_TIMER Message to OnTimer member function OnTimer(UINT nIDEvent);
Other Time-Handling Devices:
High Performance Counters: QueryPerformanceFrequency // Counts per sec QueryPerformanceCounter // Counter Value int64
Waitable Counters Delays Sleep(time)
// msec
31.03.2008
[email protected]
49
Summary What are the acquired skills: MFC-based SDI application development Application Wizard and Class Wizard handling GDI programming Windows messages, user defined messages Dialogs, FormView View-Class, Simple and Complex Control Elements, Data Exchange Threads and Events RS232 communication, Timer What is left: Databases, Networking, COM and ATL
31.03.2008
(c) FH-Prof. Christian V. Madritsch
[email protected]
50
25