Programming Windows, Fifth Edtion学习笔记
鼹鼠
This book shows you how to write programs that run under Microsoft Windows 98, Microsoft Windows NT 4.0, and Windows NT 5.0. These programs are written in the C programming language and use the native Windows application programming interfaces (APIs). As I'll discuss later in this chapter, this is not the only way to write programs that run under Windows. However, it is important to understand the Windows APIs regardless of what you eventually use to write your code.
You should know C. If you don't know C, Windows programming is probably not a good place to start. I recommend that you learn C in a character-mode environment such as that offered under the Windows 98 MS-DOS Command Prompt window. But for the most part, you should have a good working familiarity with the language, particularly with C structures and pointers. Some knowledge of the standard C run-time library is helpful but not required.
I'll be assuming that you're using Microsoft Visual C++ 6.0, which can be purchased separately or as a part of the Visual Studio 6.0 package.
That's it. I'm not going to assume that you have any experience at all programming for a graphical user interface such as Windows.
Central to the workings of Windows is a concept known as "dynamic linking."
Your First Windows Program
Now it's time to do some coding. Let's begin by looking at a very short Windows program and, for comparison, a short character-mode program. These will help us get oriented in using the development environment and going through the mechanics of creating and compiling a program.
以下是在纯文本方式下运行的程序:
main ()
{
printf ("hello, world\n") ;
}
是的,c语言使用了C运行时库的函数时(如上面的printf)可以不用声明。但是现在是90年代以后了,我们习惯于告诉我们的编译器如何来寻找运行时库。以下是修改过后的代码:
#include <stdio.h>
main ()
{
printf ("hello, world\n") ;
}
这个程序仍然不会像看起来那么小。它当然能够编译和运行,但是许多程序员更喜欢在ANSI中忽略main函数的返回值。
#include <stdio.h>
int main ()
{
printf ("hello, world\n") ;
return 0 ;
}
我们应该给main加上更多的参数,但是先把焦点从这里移开。
The Windows Equivalent
Windows中的"Hello, world"程序仍然是用了字符模式版本的组件。有一个include语句,一个程序的进入点,函数调用,和一个返回语句,如下:
/*--------------------------------------------------------------
HelloMsg.c -- Displays "Hello, Windows 98!" in a message box
(c) Charles Petzold, 1998
--------------------------------------------------------------*/
#include <windows.h>
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MessageBox (NULL, TEXT ("Hello, Windows 98!"), TEXT ("HelloMsg"), 0) ;
return 0 ;
}
先在VC中创建一个空的Win32的应用程序,然后的事情应该很简单的了!
新建一个工程后不管用什么方式都增加一个C代码吧,代码就是上面的东西!
在结构上,该C程序等价与字符模式中的"hello, world"程序。但是你要注意,头文件stdio.h已经被windows.h替换了,入口点main也被WinMain所替换了,C的运行时库函数printf当然也用了Windows API的函数MessageBox。然而,还是有很多东西是新的,包括个别的奇形怪状的大写标志符。
从头开始!
The Header Files
HELLOMSG.C以一个预处理程序指示,每个用C写的Windows程序中都包括这样的顶极预处理指示:
#include <windows.h>
WINDOWS.H是包含文件的主体,它包括了其他的Windows的头文件,这些头文件中甚至可以包括另外的头文件。这或许可以叫做嵌套包含文件吧。在这些头文件中最重要和最基本的是:
WINDEF.H Basic type definitions.
WINNT.H Type definitions for Unicode support.
WINBASE.H Kernel functions.
WINUSER.H User interface functions.
WINGDI.H Graphics device interface functions.
这些头文件定义了所有Windows的数据类型,函数调用,数据结构和常量标志符。他们是Windows文档的重要组成部分。可能你会发现使用Edit菜单中的Find In Files选项来搜索这些头文件很便利。你可以在Developer Studio中打开并且直接测试他们。
Program Entry Point
WinMain作为Windows程序的入口点,也可以叫做执行点,经常会这样编写:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
这个入口点在/Platform SDK/User Interface Services/Windowing/Windows/Window Reference/Window Functions中被证明。它声明在WINBASE.H中:
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
);
你一定注意到了在HELLOMSG.C中有几个改变。第三个参数是LPSTR在WINBASE.H中,但是我们用的是PSTR。这两种数据类型都在WINNT.H中定义为字符或字符串的指针。那个LP前缀的代表长指针并且是16位Windows的产物。
我已经重WinMain的定义中改变呢两个参数名称;许多windows程序使用系统调用“匈牙利符号”来命名变量。
WinMain函数声明了一个整型的返回类型。WINAPI标志符在WINDEF.H中的这条语句定义:
#define WINAPI __stdcall
这条语句指定了调用转换,包含了机器编码如何在栈中放置函数调用的参数。大部分的Windows函数调用被声明成WINAPI。
The first parameter to WinMain is something called an "instance handle." In Windows programming, a handle is simply a number that an application uses to identify something. In this case, the handle uniquely identifies the program. It is required as an argument to some other Windows function calls. In early versions of Windows, when you ran the same program concurrently more than once, you created multiple instances of that program. All instances of the same application shared code and read-only memory (usually resources such as menu and dialog box templates). A program could determine if other instances of itself were running by checking the hPrevInstance parameter. It could then skip certain chores and move some data from the previous instance into its own data area.
In the 32-bit versions of Windows, this concept has been abandoned. The second parameter to WinMain is always NULL (defined as 0).
The third parameter to WinMain is the command line used to run the program. Some Windows applications use this to load a file into memory when the program is started. The fourth parameter to WinMain indicates how the program should be initially displayed—either normally or maximized to fill the window, or minimized to be displayed in the task list bar. We'll see how this parameter is used in Chapter 3.
MessageBox函数
MessageBox函数被设计为显示一个简短的消息。
MessageBox函数的第一个参数是一个window handle,关于window handle可以在第三章中看到。第二个参数是在消息框中主题文字,第三个参数是在消息框的标题栏中的文字。
第四个参数可以用前缀MB_开始,这个定义在WINUSER.H中,你可以从中选择你要显示的按钮:
#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
当你给第四个参数设置为0,那么只有OK按钮显示,你可以使用C或者(|)来组合这些按钮:
#define MB_DEFBUTTON1 0x00000000L
#define MB_DEFBUTTON2 0x00000100L
#define MB_DEFBUTTON3 0x00000200L
#define MB_DEFBUTTON4 0x00000300L
你也可以使用在消息框中显示图标的实例:
#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L
一些图标有可变的名称:
#define MB_ICONWARNING MB_ICONEXCLAMATION
#define MB_ICONERROR MB_ICONHAND
#define MB_ICONINFORMATION MB_ICONASTERISK
#define MB_ICONSTOP MB_ICONHAND
There are a few other MB_ constants, but you can consult the header file yourself or the documentation in /Platform SDK/User Interface Services/Windowing/Dialog Boxes/Dialog Box Reference/Dialog Box Functions.
In this program, the MessageBox function returns the value 1, but it's more proper to say that it returns IDOK, which is defined in WINUSER.H as equaling 1. Depending on the other buttons present in the message box, the MessageBox function can also return IDYES, IDNO, IDCANCEL, IDABORT, IDRETRY, or IDIGNORE.
Is this little Windows program really the equivalent of the K&R "hello, world" program? Well, you might think not because the MessageBox function doesn't really have all the potential formatting power of the printf function in "hello, world." But we'll see in the next chapter how to write a version of MessageBox that does printf-like formatting.
Compile, Link, and Run
本章学习技术,但是还牵扯到其他的一些问题,有些地方还没有深入看下去,而且理解可能还有错,所以请各位看官能够指正一二。