Basic Techniques and Knowledge 01-P1368 11/13/00 2:53 PM Page 2
Total Page:16
File Type:pdf, Size:1020Kb
01-P1368 11/13/00 2:53 PM Page 1 CHAPTER 1 Basic Techniques and Knowledge 01-P1368 11/13/00 2:53 PM Page 2 2 Chapter 1 Basic Techniques and Knowledge We are about to begin our adventure into the Windows graphics system, from the sur- face of the Win32 API to the rock bottom of display/printer drivers. There are lots of important areas in the Windows graphics system. We will focus on the most impor- tant parts: the Win32 GDI (Graphics Device Interface) and the DirectDraw portion of DirectX. Win32 GDI APIs are implemented on multiple platforms like Win32s, Win95/ 98, Win NT 3.5/4.0, Windows 2000, and WinCE, with significant differences among them. For example, Win32s and Win95/98 are based on the old 16-bit GDI imple- mentation that has lots of restrictions, while the true 32-bit implementations on Win- dows NT 3.5/4.0 and Windows 2000 are much more powerful. The DirectDraw in- terfaces are implemented on Win95/98, Win 4.0, and Windows 2000 platforms. This book will be targeted mainly at the Windows NT 4.0 and Windows 2000 platforms, the most powerful implementation of those APIs. Special notes for other platforms will be added as appropriate. Before we go deeply into the Windows graphics system, we need to review a few basic techniques that will be vital to our exploration. In this chapter, we will cover simple Windows programming in C /C++, a little bit of assembly-language program- ming, program development and debugging tools, the format of the Win32 execution file, and the architecture of the Windows Operating System. It is assumed that readers are intermediate to advanced Windows programmers, so the coverage of those techniques Note is very brief. Readers will be referred to other books for in- depth coverage of those topics. 1.1 BASIC WINDOWS PROGRAMMING IN C/C++ The working languages of our profession have developed dramatically from the dark age of machine languages to the modern-day programming languages like C, Visual Basic, Pascal, C++, Delphi, and Java. It’s said that the number of lines of code a pro- grammer writes a day is almost the same no matter what language he or she uses. So, naturally, with languages moving higher and higher in level of abstraction, program- mers’ productivity gets higher and higher. The most common single language used for Windows programming may be C, as can be seen from the sample programs that come with the Microsoft Platform Software Development Kit (Platform SDK) and Device Driver Kit (DDK). Object- 01-P1368 11/13/00 2:53 PM Page 3 1.1 Basic Windows Programming in C/Cϩϩ 3 oriented languages like C++, Delphi, and Java are catching up quickly, to replace C and Pascal as the new-generation languages for Windows programming. Object-oriented languages are definitely improvements over their predecessors. C++, for example, even without its pure object-oriented features such as class, inheri- tance, and virtual function, improves upon C with modern features such as strict func- tion prototyping, inline function, overloading, operator, and template. But writing object-oriented Windows programs is not an easy job, mainly be- cause the Windows API was not designed to support object-oriented languages. For example, callback functions like the Windows message procedure and the dialog mes- sage procedure must be global functions. The C++ compiler will not let you pass a nor- mal class member function as a callback function. Microsoft Foundation Class (MFC) is designed to wrap the Windows API in a class hierarchy, which has now almost be- come the de facto standard for writing object-oriented Windows programs. MFC goes to great length to bridge objected-oriented C++ and C oriented Win32 API. MFC passes a single global function as the generic window message procedure, which uses a map from HWND to a CWnd object pointer to translate a Win32 window handle into a pointer to a C++ window object. Even Microsoft is worried about the size and complexity of MFC when OLE, COM, and Active X are becoming popular, so the recommended class library to write lightweight COM server and Active X controls is yet another class library from Microsoft, Active Template Library (ATL). Following the trend of moving toward object-oriented programming, the sample code presented in this book is mostly C++, rather than C. To make the sample code readily useable to C programmers, C++ programmers, MFC programmers, ATL pro- grammers, C++ builder programmers, or even Delphi and Visual BASIC program- mers, neither fancy features of C++ nor MFC /ATL are used in this book. Hello World Version 1: Starting Your Browser Let’s get down now to the business of writing a basic Windows program in C. Here is our first Windows program: // Hello1.cpp #define STRICT #include <windows.h> #include <tchar.h> #include <assert.h> const TCHAR szOperation[] = _T("open"); const TCHAR szAddress[] = _T("www.helloworld.com"); 01-P1368 11/13/00 2:53 PM Page 4 4 Chapter 1 Basic Techniques and Knowledge int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR lpCmd, int nShow) { HINSTANCE hRslt = ShellExecute(NULL, szOperation, szAddress, NULL, NULL, SW_SHOWNORMAL); assert( hRslt > (HINSTANCE) HINSTANCE_ERROR); return 0; } Sample programs accompanying the book are put into in- dividual subdirectories for each chapter, named Chapt_01, Note Chapt_02, etc. An extra directory on the same level, called include, contains all the common shared codes. Each chap- ter directory has one Microsoft Visual C++ workspace file, which contains all the projects within the chapter. Each project resides in its own subdirectory. For example, the Hello1 project is in the Chapt_01\Hello1 directory. Toref- erence common files like win.h, relative paths like “..\..\ include\win.h” are used in the source code. This “Hello World” program is not just another hello world program, it’s the hello world program for the Internet age. If you could run this program, your browser would bring up a web page through a powerful Win32 API call, ShellExecute. A few points may worth mentioning in this simple program, as it may not look the same as the skeleton program shown in other books. These points are included here to encourage good programming habits. The program starts by defining a macro STRICT, which tells the Windows in- clude file to treat different object types differently, making it easier for the compiler to give programmers warning messages if they mix HANDLE with HINSTANCE, or HPEN with HBRUSH. If you hear a reader complaining that sample programs from certain books can’t even compile, it is likely that the sample programs were not tested with the macro STRICT defined. This happens because the newer versions of Win- dows include files that turn STRICT on by default, while the older versions do not. Including <tchar.h> makes the single source code compilable both for non- UniCode and UniCode versions of binary code. Programs targeted for Windows 95/ 01-P1368 11/13/00 2:53 PM Page 5 1.1 Basic Windows Programming in C/Cϩϩ 5 98 lines of OS are not recommended to be compiled in UniCode mode unless the programmer is extremely careful in avoiding UniCode-based API, which are not im- plemented on Win95/98. Be careful that the lpCmd parameter to WinMain is always non-UniCode; you have to use the GetCommandLine() to get the TCHAR version of the full command line. Including <assert.h> is for defensive programming. It’s highly recommended that programmers step through every line of their code in a debugger to catch possible er- rors. Putting asserts on incoming parameters and function return results helps check for unexpected situations efficiently over the whole development phase. Another way to contain programming errors is to add exception handling to your code. The two “const TCHAR” array definitions ensure that those constant strings are put into the read-only data section in the final binary code generated by the compiler and linker. If you include strings like _T(“print”) directly in the call to ShellExecute, it will likely end up in the read-write data section of the binary code. Putting constants into the read-only section ensures that they are really read-only, so that attempts to write to them will generate protection faults. It also makes them shareable among mul- tiple instances, thus reducing physical RAM usage if multiple instances of the same module are loaded on a system. The program does not name the second parameter of WinMain, normally called hPrevInstance, because it’s not used by Win32 programs. The hPrevInstance is sup- posed to be the instance handle of the previous instance of the current program for Win16 programs. For Win32 programs, all programs have separate address spaces. Even if there are multiple instances of the same program running, they can’t normally see each other. It’s hard, if not impossible, to write the perfect source code, yet we can learn some tricks to tell the compiler to build the perfect binary code. The important thing is to select the right CPU, runtime library, optimization, structure alignment, and DLL base address. Adding debug information, a map file, or even an assembly code listing will help you debug, analyze defect reports, or fine-tune performance. Another idea is to use map file, the quick viewer feature of Windows 95/96/NT Explorers, or Dumpbin to analyze your binary code to see that the right functions are exported, no strange functions are imported, and no section within the binary code surprises you. For ex- ample, if your code imports oleauto32.dll function 420, your code would not run on earlier releases of Win95.