本文翻译自MSDN,由于本人英文水平一般,如果有什么差错,请大家积极指出,本人一定知错就改。
原文链接:http://msdn.microsoft.com/library/en-us/winprog/winprog/a_generic_sample_application.asp
本文适合于Win32 API的初学者
A Generic Sample Application
一个Generic实例应用程序
This section introduces the source code components of a generic Windows-based application, named Generic. This section assumes that you have used Windows-based applications and therefore are already familiar with windows, menus, and dialog boxes in Microsoft? Windows?.
这个部分介绍一个基于Windows的应用程序的源代码的组成部分,我们这个程序叫做Generic。我们假定你已经使用过基于Windows的应用程序,因此你应该对Windows中的窗口、菜单与对话框都比较熟悉。
The Generic application described here consists of the following parts:
这里讲述的Generic应用程序由以下部分组成:
The entry-point function
入口函数
The menu
菜单
The window procedure
窗口过程
The About dialog box
About对话框
The complete code is shown in Source Code.
完整的代码被列在“Source Code”这个部分。
The Entry-Point Function
入口函数
Every application must have an entry-point function. The name commonly given to the entry point is the WinMain function.
每个应用程序都必须有一个入口函数。通常入口点的名称是WinMain。
As in most Windows-based applications, the WinMain function for the Generic application completes the following steps:
与大部分基于Windows的应用程序一样,Generic应用程序中的WinMain函数都完成以下一些步骤:
Registering the window class
注册窗口类
Creating the main window
创建主窗口
Entering the message loop
进入消息循环
Registering the Window Class
注册窗口类
Every window must have a window class. A window class defines the attributes of a window, such as its style, its icon, its cursor, the name of the menu, and the name of the window procedure.
每个窗口都必须有一个窗口类。这个窗口类定义了一个窗口的属性,例如它的风格、图标、光标指针、菜单名与窗口过程的名称。
The first step is to fill in a WNDCLASS structure with class information. Next, you pass the structures to the RegisterClass function. The Generic application registers the GenericAppClass window class as follows:
第一步是用类的信息来填充一个WNDCLASS结构。下一步,将这个结构传递给RegisterClass函数。Generic应用程序依照下列代码来注册GenericAppClass窗口类:
HINSTANCE hInstance;
WNDCLASS wc;
wc.lpszClassName = "GenericAppClass";
wc.lpfnWndProc = MainWndProc;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = "GenericAppMenu";
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClass(&wc);
For more information on the menu, see The Menu. For more information on the window procedure, see The Window Procedure.
至于菜单方面的更多信息,请参考“The Menu”这个部分。而关于窗口过程方面的更多信息,请参考“The Window Procedure”。
Creating the Main Window
创建主窗口
You can create the window by calling the CreateWindow function. The Generic application creates the window as follows:
你可以通过调用CreateWindow函数来创建窗口。Generic应用程序依照下列代码来创建窗口:
hWnd = CreateWindow("GenericAppClass",
"Generic Application",
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
The first parameter is the name of the class that we registered. The remaining parameters specify other window attributes. This call creates the window, but the system does not display a window until the application calls the ShowWindow function. The Generic application displays the window as follows:
第一个参数是我们已注册的窗口类的名称。剩下的参数用来指定其它的窗口属性。这个函数调用创建一个窗口,但是系统不会显示它,除非你再调用ShowWindow这个函数。Generic应用程序依照下列代码来在屏幕上显示该窗口:
ShowWindow( hWnd, nCmdShow );
Entering the Message Loop
进入消息循环
Once the main window is created and displayed, the WinMain function can begin its primary task, which is to read messages from the application queue and dispatch them to the appropriate window.
一旦主窗口已被创建并显示,WinMain函数就可以开始它的主要任务,那就是从应用程序的消息队列中读取消息并把它发送到合适的窗口中去。
The system does not send input directly to an application. Instead, it places all mouse and keyboard input from the user into a message queue, along with messages posted by the system and other applications. The application must read the message queue, retrieve the messages, and dispatch them so that the window procedure can process them.
系统不会将输入直接发送到一个应用程序。代替的是,它把来自用户的鼠标与键盘输入放入到一个消息队列,连同系统与其它应用程序所发送的消息放在一起。应用程序必须从消息队列中读取消息,检索并将它们发送到窗口过程,这样做是为了让窗口过程能够处理它们。
The Generic application uses the following message loop:
Generic应用程序使用以下的消息循环:
BOOL bRet;
while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0 )
{
if (bRet == -1)
{
//handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
The GetMessage function retrieves a message from the queue. The DispatchMessage function sends each message to the appropriate window procedure. The TranslateMessage function translates virtual-key message into character messages. In Generic, this is necessary to implement menu access keys.
GetMessage函数从消息队列中获取消息。DispatchMessage函数将每个消息发送到合适的窗口过程。TranslateMessage函数将虚拟键消息转换为字符消息。一般的,这是为了实现菜单快捷键的需要。
The Menu
菜单
Most applications include a menu to provide a means for the user to select commands. The most common way to create a menu is to define it as a resource in the resource-definition file. The Generic application has a single menu, named Help, with a single command, About. The resource is defined as follows:
大多数应用程序包含一个菜单都是为了给用户选择命令提供一种手段。创建菜单的最普通的方法是在资源定义文件中定义一种菜单资源。Generic应用程序只有一个菜单,叫做Help;这个菜单只有一个命令,About。这个资源依照下列代码来定义:
GenericAppMenu MENU
{
POPUP "&Help"
{
MENUITEM "&About", IDM_ABOUT
}
}
The name of the menu resource is specified when registering the window class.
当注册窗口类时,菜单资源的名称在窗口类中指定。
Selecting the About command causes Generic to display the About dialog box.
选择About命令将会使Generic应用程序在屏幕上显示About对话框。
The Window Procedure
窗口过程
Every window must have a window procedure. The name of the window procedure is user-defined. The Generic application uses the following window procedure for the main window:
每个窗口都必须有一个窗口过程。窗口过程的名称是用户定义的。Generic应用程序使用以下窗口过程作为主窗口的窗口过程:
LRESULT WINAPI MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
The WINAPI modifier is used because the window procedure must be declared with the standard call calling convention.
使用WINAPI修饰词是因为窗口过程必须被声明为标准call调用约定。
The window procedure receives messages from the system. These may be input messages or window-management messages. You can optionally handle a message in your window procedure or pass the message to the system for default processing by calling the DefWindowProc function. The Generic application processes the WM_PAINT, WM_COMMAND, and WM_DESTROY messages, using a switch statement that is structured as follows:
窗口过程从系统中接收消息。这些消息可能是用户的输入消息,或者是窗口管理消息。你可以在窗口过程中有选择地处理一条消息,或者通过调用DefWindowProc函数来将消息传递到系统中作默认的处理。Generic应用程序处理WM_PAINT、WM_COMMAND与WM_DESTROY消息,它使用switch条件语句来将这些消息处理构造成如下代码:
switch (uMsg)
{
case WM_PAINT:
...
case WM_COMMAND:
...
case WM_DESTROY:
...
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
The WM_PAINT message indicates that you should redraw what's in all or part of your application's window. Use the BeginPaint function to get a handle to a device context, then use the device context for drawing within the application's window, with functions like TextOut. Use EndPaint to release the device context. The Generic application displays a text string, "Hello, World!", in the window using the following code:
WM_PAINT消息指示你应该重画整个应用程序窗口或者其中一部分。使用BeginPaint函数来获得一个设备描述表的句柄,然后使用设备描述表句柄和TextOut这些函数来在应用程序的窗口中绘图。最后使用EndPaint函数来释放设备描述表。Generic应用程序使用以下代码来在窗口中显示一个字符串“Hello, World!”:
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
TextOut(hDC, 10, 10, "Hello, World!", 13);
EndPaint(hWnd, &ps);
break;
The WM_COMMAND message indicates that a user has selected a command item from a menu. The Generic application uses the following code to check if its About menu item has been selected:
WM_COMMAND消息表示用户已经从菜单中选择了一个命令选项。Generic应用程序使用以下代码来判断About这个菜单项是否已经被选中了:
case WM_COMMAND:
switch (wParam)
{
case IDM_ABOUT:
...
break;
}
Most window procedures process the WM_DESTROY message. The system sends this message to the window procedure immediately after destroying the window. The message gives you the opportunity to finish processing and post a WM_QUIT message in the application queue. The Generic application handles the WM_DESTROY message as follows:
大部分窗口过程都会处理WM_DESTROY这个消息。在清除窗口之后系统会立即将这个消息发送到窗口过程。这个消息让你有机会完成一些数据处理,并将WM_QUIT这个消息放入到应用程序的消息队列中去。Generic应用程序依照下列代码来处理WM_DESTROY消息:
case WM_DESTROY:
PostQuitMessage(0);
break;
The About Dialog Box
About对话框
A dialog box is a temporary window that displays information or prompts the user for input. The Generic application includes an About dialog box. Every application should include an About dialog box. The dialog box displays such information as the application's name and copyright information.
对话框是一个临时窗口,它用来显示信息或者提示用户输入。Generic应用程序包含了一个About对话框。每个应用程序都应该包含一个About对话框。它一般用来显示一些信息,例如应用程序的名称以及版权信息。
You create and display a dialog box by using the DialogBox function. This function takes a dialog box template and creates a dialog box.
你可以通过用DialogBox函数来创建并显示一个对话框。这个函数采用一个对话框模板来创建对话框。
The Generic application includes the following dialog box template in the resource-definition file:
Generic应用程序在资源定义文件中包含了以下一个对话框模板:
AboutDlg DIALOG FIXED 6, 21, 198, 99
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "About Generic"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "&OK", IDOK, 72, 74, 40, 14
LTEXT "Generic Application", 104, 45, 14, 128, 8
LTEXT "Written as a sample", 105, 45, 35, 59, 8
LTEXT "Microsoft Corporation", 106, 45, 45, 98, 8
LTEXT "Copyright (c) 2004", 107, 45, 54, 138, 8
END
The name of the source is specified as AboutDlg. For more information, see Dialog Resource.
菜单资源的名称被指定为AboutDlg。关于这方面的更多信息,请参考“Dialog Resource”。
When the user clicks About from the Help menu, the following code in the window procedure displays the About dialog box:
当用户从Help菜单中单击About菜单项时,窗口过程中的以下代码将会显示About对话框:
HINSTANCE ghInstance;
HWND hWnd;
case WM_COMMAND:
switch (wParam)
{
case IDM_ABOUT:
DialogBox(ghInstance, "AboutDlg", hWnd, AboutDlgProc);
break;
}
break;
The last parameter is a pointer to a dialog box procedure. It has the following prototype.
最后那个参数是指向对话框过程的指针。这个函数的原型如下所示:
INT_PTR WINAPI AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
A dialog box procedure is similar to a window procedure, but usually processes only dialog initialization and user-input messages. The Generic application contains the following message processing code:
一个对话框过程类似于一个窗口过程,但它常常只是处理对话框的初始化和用户的输入消息。Generic应用程序中的对话框过程包含以下消息处理代码:
UINT uMsg;
switch (uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
Source Code
源代码
The Generic application consists of the following files:
Generic应用程序由以下文件组成:
GENERIC.C
GENERIC.H
GENERIC.RC
GENERIC.DLG
GENERIC.C
Generic.c contains code for the Generic application. It includes Generic.h.
Generic.c文件包含了Generic应用程序的源代码。它包含了头文件Generic.h。
/********************************************************************* generic.c: Source code for generic *
* *
* Comments: Generic Application *
* *
* Functions: *
* WinMain - Application entry point *
* MainWndProc - main window procedure *
* AboutDlgProc - dialog procedure for About dialog *
* *
* *
\********************************************************************/
/********************* Header Files *********************/
#include <windows.h>
#include "generic.h"
/********************* Prototypes ***********************/
LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT WINAPI AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
/******************* Global Variables ********************/
HINSTANCE ghInstance;
/********************************************************************* Function: int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int) *
* *
* Purpose: Initializes Application *
* *
* Comments: Register window class, create and display the main *
* window, and enter message loop. *
* *
* *
\********************************************************************/
int PASCAL WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow )
{
WNDCLASS wc;
MSG msg;
HWND hWnd;
BOOL bRet;
if( !hPrevInstance )
{
wc.lpszClassName = "GenericAppClass";
wc.lpfnWndProc = MainWndProc;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 );
wc.lpszMenuName = "GenericAppMenu";
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClass( &wc );
}
ghInstance = hInstance;
hWnd = CreateWindow( "GenericAppClass",
"Generic Application",
WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow( hWnd, nCmdShow );
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 )
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return (int)msg.wParam;
}
/********************************************************************* Function: LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM) *
* *
* Purpose: Processes Application Messages *
* *
* Comments: The following messages are processed *
* *
* WM_PAINT *
* WM_COMMAND *
* WM_DESTROY *
* *
* *
\********************************************************************/
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hDC;
switch( msg ) {
/*************************************************************** WM_PAINT: *
\**************************************************************/
case WM_PAINT:
hDC = BeginPaint( hWnd, &ps );
TextOut( hDC, 10, 10, "Hello, World!", 13 );
EndPaint( hWnd, &ps );
break;
/*************************************************************** WM_COMMAND: *
\**************************************************************/
case WM_COMMAND:
switch( wParam ) {
case IDM_ABOUT:
DialogBox( ghInstance, "AboutDlg", hWnd, (DLGPROC)
AboutDlgProc );
break;
}
break;
/*************************************************************** WM_DESTROY: PostQuitMessage() is called *
\**************************************************************/
case WM_DESTROY:
PostQuitMessage( 0 );
break;
/*************************************************************** Let the default window proc handle all other messages *
\**************************************************************/
default:
return( DefWindowProc( hWnd, msg, wParam, lParam ));
}
return 0;
}
/********************************************************************* Function: LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM)*
* *
* Purpose: Processes "About" Dialog Box Messages *
* *
* Comments: The About dialog box is displayed when the user clicks *
* About from the Help menu. *
* *
\********************************************************************/
LRESULT CALLBACK AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg ) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch( wParam ) {
case IDOK:
EndDialog( hDlg, TRUE );
return TRUE;
}
break;
}
return FALSE;
}
GENERIC.H
Generic.h contains header information for the Generic application. It is included in Generic.c and Generic.rc.
Generic.h文件包含了Generic应用程序的标题信息。它被包含在Generic.c与Generic.rc文件中。
/************************************************************** generic.h: Header file for Generic *
* *
* *
\*************************************************************/
/******* Menu Defines *******/
#define IDM_ABOUT 1000
GENERIC.RC
Generic.rc contains resource information for the Generic application. The dialog resources are included in Generic.dlg.
Generic.rc文件包含了Generic应用程序的资源信息。对话框资源被包含在Generic.dlg文件中。
/************************************************************** generic.rc: Resource script for Generic *
* *
* *
\*************************************************************/
#include <windows.h>
#include "generic.h"
#include "generic.dlg"
GenericAppMenu MENU
{
POPUP "&Help"
{
MENUITEM "&About", IDM_ABOUT
}
}
GENERIC.DLG
Generic.dlg defines the About dialog box for the Generic application. This file is included in Generic.rc.
Generic.dlg文件定义了Generic应用程序中的About对话框。这个文件被包含在Generic.rc文件中。
/************************************************************** generic.dlg: Dialogs for Generic *
* *
* *
\*************************************************************/
1 DLGINCLUDE "generic.h"
AboutDlg DIALOG FIXED 6, 21, 198, 99
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "About Generic"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "&OK", IDOK, 72, 74, 40, 14
LTEXT "Generic Application", 104, 45, 14,
128, 8
LTEXT "Written as a sample", 105, 45, 35, 59, 8
LTEXT "Microsoft Corporation", 106, 45, 45, 98, 8
LTEXT "Copyright (c) 1996", 107, 45,
54, 138, 8
END