460 likes | 752 Views
Windows Programming. Introduction, Event Driven Architecture, Petzold 1, 3. Programming MS Windows Window System. Recall basic architecture of system: Now will begin learning “craft” of programming a particular windowing system: Microsoft Windows.
E N D
Windows Programming Introduction, Event Driven Architecture, Petzold 1, 3
Programming MS Windows Window System Recall basic architecture of system: Now will begin learning “craft” of programming a particular windowing system: Microsoft Windows
Challenges in Learning “Craft”of Window System Programming • Challenges in part arise from user interface programming in general: • ~ 50+% of applications code is user interface code! • Event driven software architectures • Simple complexity • Real-time requirements • Output 60 times/sec, keep up with mouse tracking - Multimedia: video, animations, sound, … • Need for robustness • No crashing on any input • Helpful error messages, graceful recovery • Allow abort and undo • Lower testability • E.g, difficult to test direct manipulation, same state • Little language support (for ui, and graphics primitives) • Primitives found in languages are bad for UIs (printf/scanf) • Special, complex, and enormous libraries required • Features like OOP, constraints, and collaborative systems • Complexity of tools and API
Programming a Window System, 1 • “regular programming” is (sort of) “top to bottom”: • … • a = 1 … • Scanf (b …) • Printf (a …) • … • “regular programming” typically has i/o through the screen display device and keyboard input device • It’s control flow is top-to-bottom (sequential) with iteration, decision, and function calls • It is not set up to handle asynchronous input and output • Is not “event-driven”, as we will see • i.e., not use an event driven architecture
Programming a Window System, 2 • In fact, there is are software layers (“window system”, etc.) between the input and output of “regular” programming • Accessing these intermediate layers, e.g., window system, allows programming of elements otherwise inaccessable • Such programming is through the “window system application program interface” • Window system api • Graphics systems also have api’s, e.g., OpenGL api • Allows output control of window titles scroll bars, changing pixels, … • Allows input of mouse movements, button presses, keyboard, …
Windowing Systems:Window System vs. Window Manager • Window Systems • Supports different screen regions • … called windows • Can be: • part of a program (Smalltalk) • a separate program (X) • A little bit of all (MS Windows) • Often divided into two layers: 1. Window Manager (base layer) • Implements the basic functionality of the windowing system • Often window manager (wm) and window system (ws) are blurred into one, since many systems (apple, windows, next) combine them as one • Others allow different wm on same ws (X) 2. Window System (UI layer) • Provides a programmer interface (API) that allows output of graphics to draw on the screen to a clipped region (window)
Windowing Systems:Window System vs. Window Manager • Window Systems • Supports different screen regions • … called windows • Can be: • part of a program (Smalltalk) • a separate program (X) • A little bit of all (MS Windows) • Often divided into two layers: 1. Window Manager (base layer) • implements the basic functionality of the windowing system • Allows end users to move windows, resize them, iconify them, select them, etc • Provides “decorations” on windows, such as, titles, borders, colors, icons, etc • Provides primitives for generating pictures, text on the output display: • output model • provides mechanisms for handling user input (keyboard, mouse): • input model • primary interface to the base layer is through a procedural interface, API
Windowing Systems:Window System vs. Window Manager • Window Systems • Supports different screen regions • … called windows • Can be: • part of a program (Smalltalk) • a separate program (X) • A little bit of all (MS Windows) • Often divided into two layers: 1. Window Manager (base layer) 2. Window System (UI layer) • Includes all aspects that are visible or apparent to the user • Including, presentation: what the user sees, windows, pictures, text, etc. • Provides a programmer interface (API) that allows output of graphics to draw on the screen to a clipped region (window) • output model. • Input channels from mouse/keyboard to appropriate window • input model • Commands: operations the user can use to manipulate windows and their contents
fyi - Window Manager and Win. System Evolution Early systems – and MS Windows today • Tightly coupled WM and WS • Assumed sophisticated graphics and toolkits would be built on top • Integral part of OS • Sapphire, sunwindows • Next generation • Incorporate into the window system the graphics and toolkits • Gave window manager same sophistication and look and feel as applications, applications • Would look more consistent • Cedar, Macintosh, Next, Windows X and others • Allows different WM and different toolkits • Still embeds sophisticated graphics packages • Allows different windowing system on same OS • Uses IPC and network for connection to applications • News, X
fyi - Window System: Output Model, 1 Graphics primitives (procedures) that an application can call to draw pictures, text, etc. All usually directed to a particular window so the drawing is ``clipped'' to the bounds of window Usually can only draw objects of the types provided by the window system Older systems (SunTools) simple primitives draw rectangles, text, lines operations on pictures: RasterOp or BitBlt advantage: easy to implement Newer systems (Macintosh, X) still have rectangles, lines, and text, but also filled polygons, splines, color, clipping all 2D objects, but extensions often available for 3D objects advantage: prettier images are easier for application to create
fyi - Window System: Output Model, 2 There are various graphics standards or styles: Postscript language invented by Adobe for sending pages to printers a complete textual programming language provides: arbitrary rotation and scaling complete hardware independence (coordinates are floats) used as an output model for some windowing systems: NeWS, DisplayPostscript, NeXT, DEC OpenGL 3D model from Silicon Graphics powerful rendering capabilities provides independence for 3D objects standard part of: Windows, X Other standards CORE (ran on top of SunView) PHIGS PEX = PHIGS + 3D for All new systems implement a graphics style as part of the windowing system (Macintosh, X, NeWS, Microsoft Windows).
fyi - Window Systems: Input Model, 1 Earlier systems (e.g., CORE/PHIGS) provided an input model that did not work well with the direct manipulation style of interaction For example, programs called a routine to request a value using a “virtual device”, ``locator'' for a pointing device position; a ``string'' for edited text; a ``choice'' for a menu selection; or a ``pick'' for selecting an object problem is model forced system to wait until the user provided input. Modern systems employ a ``mode-free'' style of interaction user can decide whether to make a menu choice, select an object, press a button, when desired. To handle the asynchronous, mode-free style of interaction, modern systems employ an event-driven input model: an event-driven (software) architecture a stream of events are sent to the currently active window (the one designated to receive events). an event record includes: event type (what kind of event): WindowClose, , LeftButtonDown, KeyUp mouse coordinates (x,y) timestamp key modifiers (e.g., is SHIFT or ALT pressed)
fyi - Window Systems: Input Model, 2, Event Driven Architecture To handle the asynchronous, mode-free style of interaction, modern systems employ an event-driven input model: an event-driven (software) architecture a stream of events are sent to the currently active window (the one designated to receive events). an event record includes event type (what kind of event): WindowClose, , LeftButtonDown, KeyUp mouse coordinates (x,y) timestamp key modifiers (e.g., is SHIFT or ALT pressed) The windowing system queues keyboard events, mouse button events, mouse movement events, and window operation events, and other special events to windows, their programs must decode the events and process them events are asynchronous Problems with event-driven model: Application must always be able to accept events Race conditions may occur since events are asynchronous Not device independent. Suppose you wanted to add a 5-button mouse to your system. Because the event records have fixed fields, there is no way for the standard event mechanism to determine the state of the extra buttons. No provision for special ``stop output'' (control-S) or ``abort'' (control-C)
fyi - Window Systems: Communication Window systems often are protected processes so bad applications will not crash entire machine. Not true for: (old) Windows 3.11, Macintosh True for: X, WindowsNT How do applications communicate with the window system? OS kernel - Sapphire, SunView, Windows Network protocols (e.g., TCP/IP, sockets) - SunTools, Macintosh Send messages to processes via network - X, NeWS
fyi - Window Manager: Commands How the user controls the windows: mouse and keyboard commands interaction with menus, buttons, etc one window must be the listener or have the focus: the chosen window receives keyboard and mouse events how is the focus determined? click-to-type: user must click mouse in window to select Macintosh, Microsoft Windows move-to-type: user must place mouse over desired window, In X, some window managers let you choose which style you prefer window commands move to front, send to back resize, move, iconify/minimize destroy, close
Interaction Handling: Sampling vs. Event-driven Sampling(or polling) vs. Event-driven • Basic issue of how to get and act upon user requests/actions/inputs • Entails “looking at” (getting information from) input devices Readln (...) - get character or numeric information - “sits and waits” With several asynchoronous devices (mouse loc & button, keyboard, ...) need new methods Example: Polling to detect mouse // general display, etc. // use past and current values of some event indicator to see if (new) input old_val = get_val_of (mouse_button_1) While (!quit) { . : new_val = get_val_of (mouse_button_1) if (new_val != old_val) { // do whatever you want to do upon mouse click event old_val = new_val } // check other devices too, and act if need to } This is process intensive as always checking - lots/mostly nothing new May be better to have scheme in which not just keep looking - polling
Interaction Handling: Event Driven Program perspective: Program handles events, thus event-driven programming // general initialization, first display While (!quit) { // program waits for user action wait_on (user_action) // just sit there until event occurs switch (user_action) { case mouse_button_1_clicked // do whatever upon mouse click // other cases to handle input (events) case mouse_button_2_clicked : } } When > 1 user action occurs before completing processing of another event, put event in queue, the event queue In fact there is a message for just about everything, mouse move, resize, etc., and events are passed to the program as messages and placed in the message queue
A Big Idea:“Windows Distributes Events to Appropriate Event Queues” Windows perspective: Program 1 Program 2 Program 3 Event queue 1 Event queue 2 Event queue 3 Windproc 1 Windproc 2 Windproc 3
Events, Queues, Main Prog., “WndProc” Events in window are called window messages: Each application has its own message queue(s) Each message queue is handled by a procedure, often named “WindowProc” Windows operating system places some messages into an application's queue, messages, are sent directly to the appropriate WindowProc() But first, each application (in its “main” program) has event loop polls queue for new messages: MSG msg; while (GetMessage (&msg, 0, 0, 0) == TRUE) { TranslateMessage(msg); DispatchMessage (msg); } Write code to perform application specific processing for messages of interest code is in the “WindowProc” for each window “Un-interesting” messages can be passed back to the Windows operating system for default processing by calling: DefWindowProc () but, all messages are available Periodic calls to GetMessage() are necessary to prevent an application from taking control of the machine
A Big Idea:“Windows Distributes Events to Appropriate Event Queues” Windows perspective: Program 1 Program 2 Program 3 Event queue 1 Event queue 2 Event queue 3 Windproc 1 Windproc 2 Windproc 3
Interaction Handling: Sampling vs. Event-driven Sampling(or polling) vs. Event-driven • Basic issue of how to get and act upon user requests/actions/inputs • Entails “looking at” (getting information from) input devices Readln (...) - get character or numeric information - “sits and waits” With several asynchoronous devices (mouse loc & button, keyboard, ...) need new methods Example: Polling to detect mouse // general display, etc. // use past and current values of some event indicator to see if (new) input old_val = get_val_of (mouse_button_1) While (!quit) { . : new_val = get_val_of (mouse_button_1) if (new_val != old_val) { // do whatever you want to do upon mouse click event old_val = new_val } // check other devices too, and act if need to } This is process intensive as always checking - lots/mostly nothing new May be better to have scheme in which not just keep looking - polling
Interaction Handling: Event Driven Program perspective: Program handles events, thus event-driven programming // general initialization, first display While (!quit) { // program waits for user action wait_on (user_action) // just sit there until event occurs switch (user_action) { case mouse_button_1_clicked // do whatever upon mouse click // other cases to handle input (events) case mouse_button_2_clicked : } } When > 1 user action occurs before completing processing of another event, put event in queue, the event queue In fact there is a message for just about everything, mouse move, resize, etc., and events are passed to the program as messages and placed in the message queue
Interaction Handling: Real MS Windows API Code Note similarity of Windows program to general structure: WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (iMsg) { case WM_CREATE : [process WM_CREATE message] return 0 ; case WM_PAINT : [process WM_PAINT message] return 0 ; case WM_DESTROY : [process WM_DESTROY message] return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; // lets windows handle what not handled here } Each “case” represents an event, and what to do when it occurs Should (soon) feel (more or less) comfortable with all aspects
Message Loop It is the main program which is responsible for making events/messages available to the procedure (WndProc) which handles them. The Windows operating system terminates an application when a WM_QUIT message occurs.
REAL “Hello World” Code Next, Recall Event Handling: WinMain and WndProc One last time … Program entry point is WinMain( ) WindowProc( ) is called repeatedly to handle events/messages WindowProc( ) is instantiated many many many … time Is going on and off the runtime stack repeatedly Hence, e.g., must use static variables
Hello World 1: ~60 lines –WinMain HELLOWIN.C – Petzold --- (main just sets things up – quite a few things – very low level) #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; // 1990’s object oriented (hack) wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; }(continued)
Old Familiar WinMain (cont’d) hwnd = CreateWindow (szAppName, // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent win handle NULL, // window menu handle hInstance, // prog inst handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; }
Hello World: WinProc, the Message Handler Note similarity to paradigm message handler of any event driven architecture: LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, L… lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: PlaySound (TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT: // “window redraws itself!” hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; // DefWindProc handles all message not handled in WndProc }
LOTS of “Windows functions” Calls Windows Function Calls HELLOWIN - 18 Windows functions:LoadIcon Loads an icon for use by a program. • LoadCursor Loads a mouse cursor for use by a program. • GetStockObjectObtains a graphic object, in this case a brush used for painting the window's background. • RegisterClass Registers a window class for the program's window. • MessageBox Displays a message box. • CreateWindow Creates a window based on a window class. • ShowWindow Shows the window on the screen. • UpdateWindow Directs the window to paint itself. • GetMessage Obtains a message from the message queue. • TranslateMessage Translates some keyboard messages. • DispatchMessage Sends a message to a window procedure. • PlaySound Plays a sound file. • BeginPaint Initiates the beginning of window painting. • GetClientRect Obtains the dimensions of the window's client area. • DrawText Displays a text string. • EndPaint Ends window painting. • PostQuitMessage Inserts a "quit" message into the message queue. • DefWindowProc Performs default processing of messages.
Help: All you want (and/or more), 1 DrawText (hdc, "Hello, Windows 98!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; The DrawText function draws formatted text in the specified rectangle. It formats the text according to the specified method (expanding tabs, justifying characters, breaking lines, and so forth). int DrawText( HDChDC, // handle to device context LPCTSTRlpString, // pointer to string to draw intnCount, // string length, in characters LPRECTlpRect, // pointer to structure with formatting dimensions UINTuFormat // text-drawing flags ); Parameters hDC Identifies the device context. lpString Points to the string to be drawn. If the nCount parameter is -1, the string must be null-terminated. nCount Specifies the number of characters in the string. If nCount is -1, then the lpString parameter is assumed to be a pointer to a null-terminated string and DrawText computes the character count automatically. lpRect Points to a RECT structure that contains the rectangle (in logical coordinates) in which the text is to be formatted.
Help: All you want (and/or more), 2 uFormat Specifies the method of formatting the text. It can be any combination of the following values: ValueDescription DT_CENTER Centers text horizontally. DT_LEFT Aligns text to the left. DT_RIGHT Aligns text to the right. DT_SINGLELINE Displays text on a single line only. Carriage returns and linefeeds do not break the line. DT_TOP Top-justifies text (single line only). DT_VCENTER Centers text vertically (single line only). Return Value If the function succeeds, the return value is the height of the text. Remarks The DrawText function uses the device context's selected font, text color, and background color to draw the text. Unless the DT_NOCLIP format is used, DrawText clips the text so that it does not appear outside the specified rectangle. All formatting is assumed to have multiple lines unless the DT_SINGLELINE format is specified. If the selected font is too large for the specified rectangle, the DrawText function does not attempt to substitute a smaller font. See Also GrayString, TabbedTextOut, TextOut, RECT
FYI, Handles Handles are values “managed” by Windows (the window manager/system) • vs. Windows, the operating system • the application program requests the value or allocation of a handle by a call to Windows (the window system/manager) e.g., hdc = GetDC (hwnd) In fact there are a finite number of handles of the several types, e.g., hIcon, hCursor In the previous program the following handles are used: It is necessary to “release” (or return to the pool of resources) any handle obtain e.g., ReleaseDC (hwnd, hdc) If all handles are used, the often a Windows program will simply stop (hang/crash) with no message Further, since the exact sequence of handle allocation and return typically depends on the particular interactions with a program, it can be most difficult to find such an error!
When program has to “redraw” client area: WM_PAINT and Control Flow, 1 “Events”, or messages in the message queue indicate window size, etc. changes and when part of the window (client area) has been “destroyed” • this is indicated by a WM_PAINT message • maybe should have been WM_NEEDS-REPAINT • the idea is to “let the application program know when to redraw itself” • in Windowese, the window has an invalid (needs redrawing) region That is, a window procedure receives a WM_PAINT message when: 1. When another window moved off the window 2. Window resized (if class style CS_H/VREDRAW) 3. Some kinds of “built in” scrolling occur 4. Various other times when Windows cannot recreate saved region (e.g., dialog box) 5. The program itself causes a WM_PAINT message to be “sent to itself” by calling the InvalidateRect or InvalidateRgn functions (Huh?) This is a way for a program to “control itself”, i.e., pass control to the WM_PAINT part of program
When program has to “redraw” client area: WM_PAINT and Control Flow, 2 Yet again, the paradigm control structure: WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (iMsg) { case WM_CREATE : [process WM_CREATE message] return 0 ; caseWM_PAINT : [process WM_PAINT message] return 0 ; case WM_DESTROY : [process WM_DESTROY message] return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
Example: Program Driven Control Flow(overview – and that’s all …) When mouse is clicked in window (client area), program alternates drawing rectangle to left, then right of center WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; static int cxClient, cyClient, iXcenter, iYcenter; // must be static, WndProc is a procedue, static bool bLeft = TRUE; // and so is coming on and off stack // local variables that are not static are lost switch (iMsg) { case WM_SIZE: // determine window client area size and use to find center for drawing cxClient = LOWORD (lParam) ; iXcenter = cxClient / 2; cyClient = HIWORD (lParam) ; iYcenter = cyClient / 2; return 0; case WM_LBUTTONUP: InvalidateRect (hwnd, NULL, TRUE) ; // marks window client area as “invalid” return 0 ; // resulting in WM_PAINT message sent to wind case WM_PAINT : // typically, “it all happens in WM_PAINT case” hdc = BeginPaint (hwnd) ; // Begin/EndPaint “validates” rectangle // so another WM_PAINT not generated if (bLeft) { Rectangle (hdc, iXcenter - 15, iYcenter - 15, iXcenter, iYcenter); bLeft = FALSE; } else Rectangle (hdc, iXcenter, iYcenter, iXcenter + 15, iYcenter + 15); bLeft = TRUE; } EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } // end switch return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
Another Windows function call Help: Rectangle The Rectangle function draws a rectangle. The rectangle is outlined by using the current pen and filled by using the current brush. BOOL Rectangle( HDChdc, // handle of device context intnLeftRect, // x-coord. of bounding rectangle's upper-left corner intnTopRect, // y-coord. of bounding rectangle's upper-left corn intnRightRect, // x-coord. of bounding rectangle's lower-right corner intnBottomRect // y-coord. of bounding rectangle's lower-right corner ); Parameters hdcIdentifies the device context. nLeftRect Specifies the logical x-coordinate of the upper-left corner of the rectangle. nTopRect Specifies the logical y-coordinate of the upper-left corner of the rectangle. nRightRect Specifies the logical x-coordinate of the lower-right corner of the rectangle. nBottomRect Specifies the logical y-coordinate of the lower-right corner of the rectangle. Return Value If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError. Remarks The current position is neither used nor updated by Rectangle. See Also RoundRect
An Aside (sort of): A Useful Debugging aid Just writing to the screen is non-trivial, use TextOut and sprintf for a shortcut (or MessageBox): Example 1 (always write in same place - which gets written over): Char szbuffer[80] : hdc = GetDC (hWnd); nLength = sprintf (szBuffer, "val of i = %d", i); TextOut (hdc, 10, 10, szBuffer, nLength); nLength = sprintf (szBuffer, "val of j = %d", j); TextOut (hdc, 10, 25, szBuffer, nLength); ReleaseDC (hWnd, hdc); Example 2 (writes down page and over on successive calls to WndProc): static int x_loc=10 , y_loc=10; : case WM_PAINT: y_loc = y_loc + 15; if (y_loc > 500) { x_loc = x_loc + 100; y_loc = 10; } hdc = GetDC (hWnd); nLength = sprintf (szBuffer, "val of i = %d", i); TextOut (hdc, x_loc, y_loc, szBuffer, nLength); nLength = sprintf (szBuffer, "val of j = %d", j); y_loc = y_loc + 15; TextOut (hdc, x_loc, y_loc, szBuffer, nLength); ReleaseDC (hWnd, hdc); return 0;
Window-ese: Device Context Though we’ll just be using the screen for output, notion of a device context generalizes to other things, e.g., printers, and is that generality is where the term comes from Again, action of getting and releasing a device context occurs in most every program WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; // handle to a device context PAINTSTRUCT ps ; // which is a big structure, as we’ll see RECT rect ; switch (iMsg) { : case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; // also function “getdevicecontext()” GetClientRect (hwnd, &rect) ; DrawText (hdc, "Hello, Windows 95!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; : } }
Window-ese: The paint information Structure Just a quick look (though in fact, it is possible to query and manipulate state) typedef struct tagPAINTSTRUCT { // ps HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT; The PAINTSTRUCT structure contains information for an application. This information can be used to paint the client area of a window owned by that application.
A lot, but…. • It is a closed system • Just complex, and perhaps new • Notion of event-driven control flow • API programming in general • Many API functions • Debugger does work • Program “defensively” and incrementally
Homework • See web site
Homework: WinMain 1(from Chap03) • #include <windows.h> • LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; • int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) • { • static TCHAR szAppName[] = TEXT ("HelloWin") ; • HWND hwnd ; • MSG msg ; • WNDCLASS wndclass ; • wndclass.style = CS_HREDRAW | CS_VREDRAW ; • wndclass.lpfnWndProc = WndProc ; • wndclass.cbClsExtra = 0 ; • wndclass.cbWndExtra = 0 ; • wndclass.hInstance = hInstance ; • wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; • wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; • wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; • wndclass.lpszMenuName = NULL ; • wndclass.lpszClassName = szAppName ; • if (!RegisterClass (&wndclass)) • { • MessageBox (NULL, TEXT ("This program requires Windows NT!"), • szAppName, MB_ICONERROR) ; • return 0 ; • }
Homework: WinMain 2 • hwnd = CreateWindow (szAppName, // window class name • TEXT ("The Hello Program"), // window caption • WS_OVERLAPPEDWINDOW, // window style • CW_USEDEFAULT, // initial x position • CW_USEDEFAULT, // initial y position • CW_USEDEFAULT, // initial x size • CW_USEDEFAULT, // initial y size • NULL, // parent window handle • NULL, // window menu handle • hInstance, // program instance handle • NULL) ; // creation parameters • ShowWindow (hwnd, iCmdShow) ; • UpdateWindow (hwnd) ; • while (GetMessage (&msg, NULL, 0, 0)) • { • TranslateMessage (&msg) ; • DispatchMessage (&msg) ; • } • return msg.wParam ; • }
Homework: WndProc • LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) • { • HDC hdc ; PAINTSTRUCT ps ; RECT rect ; • switch (message) • { • case WM_CREATE: • // PlaySound(TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ; • return 0 ; • case WM_PAINT: • hdc = BeginPaint (hwnd, &ps) ; • GetClientRect (hwnd, &rect) ; • DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; • EndPaint (hwnd, &ps) ; • return 0 ; • case WM_DESTROY: • PostQuitMessage (0) ; • return 0 ; • } • return DefWindowProc (hwnd, message, wParam, lParam) ; • } MessageBeep(0);