打开VS2010,File->New->win32Project->input "HelloWorld"->ok->Finish。此时已经创建了带一定头文件的WIN32PROJECT。

此时VS2010自动帮我们生成了文档结构:

  • External Dependencies:外部资源头文件集合
  • Header Files:项目内头文件集合
  • Resources Files:资源集合
  • Source Files:项目内CPP文件集合

对于External Dependencies中得文件,因为是外部文件,此处不作深究,有兴趣可以抛开相关代码查阅。Head Files为项目内部头文件集合,对于项目来说也最为重要。下面详细介绍此中的各个文件:

  • targetver.h,不存在与其对应.cpp文件。 该文件中代码就一行:

#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and

// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.

#include <SDKDDKVer.h>

通过注释可以看明白,此处仅仅是定义the highest available Windows platform。一般无需管理,除非待建工程需要支持之前版本的windows系统,此处需要设置_WIN32_WINNT

如:

#ifndef WINVER // 指定¡§°a¨®Ì?Á?̨ª?¬¡§º? Windows Vista¡ê

#define WINVER 0x0600 // ?ä?¦Ì¨¹?a¨¤®|Ì?¦Ìê?°?º¨º®?®¨² Windows Ì???ã?À?¡ê

#endif

 

#ifndef _WIN32_WINNT // ?¡§°a¨®Ì?Á?̨ª?¬¡§º? Windows Vista¡ê

#define _WIN32_WINNT 0x0600 // ?ä?¦Ì¨¹?a¨¤®|Ì?¦Ìê?°?º¨º®?®¨² Windows Ì???ã?À?¡ê

其中_WIN32_WINNT值域为:

#define _WIN32_WINNT 0x0500 : Windows 2000

#define _WIN32_WINNT 0x0501 : Windows XP

#define _WIN32_WINNT 0x0502 : Windows Server 2003

#define _WIN32_WINNT 0x0600 : Windows Vista

  • stdafx.h包含标准系统常用头文件和项目特别指定包含的外部头文件。其余每个.cpp文件均需包含该头文件以减少代码的编写并加快编译速度。对应stdafx.cpp

.h

// stdafx.h : include file for standard system include files, or project specific include files that are used frequently, but are changed infrequently

#pragma once

#include "targetver.h"

 

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

// Windows Header Files:

#include <windows.h>

 

// C RunTime Header Files

#include <stdlib.h>

#include <malloc.h>

#include <memory.h>

#include <tchar.h>

// TODO: reference additional headers your program requires here

.cpp

// stdafx.cpp : source file that includes just the standard includes win32Hellworld.pch will be the pre compiled header

// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H and not in this file

  • Resource.h:定义项目中所有资源相关ID,供win32Helloworld.rc和win32Hellworld.h使用。

//{{NO_DEPENDENCIES}} Microsoft Visual C++ generated include file. Used by win32Hellworld.rc

 

#define IDS_APP_TITLE            103

 

#define IDR_MAINFRAME            128

#define IDD_WIN32HELLWORLD_DIALOG    102

#define IDD_ABOUTBOX            103

#define IDM_ABOUT                104

#define IDM_EXIT                105

#define IDI_WIN32HELLOWORLD            107

#define IDI_SMALL                108

#define IDC_WIN32HELLOWORLD            109

#define IDC_MYICON                2

#ifndef IDC_STATIC

#define IDC_STATIC                -1

#endif

// Next default values for new objects

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

 

#define _APS_NO_MFC                    130

#define _APS_NEXT_RESOURCE_VALUE    129

#define _APS_NEXT_COMMAND_VALUE        32771

#define _APS_NEXT_CONTROL_VALUE        1000

#define _APS_NEXT_SYMED_VALUE        110

#endif

#endif

其中宏定义前缀含义如下:

  • IDCID COMMON一般控件
  • IDMID MESSAGE 消息标志,用于消息映射
  • IDIID ICON 图标
  • IDRID MENU 菜单
  • IDD ID DIALOG 对话框

其中ID可以重复,但在同一个父项下不可重复。

  • win32Hellworld.h:主程序.h。默认代码如下:

#pragma once

#include "resource.h"

在此处可以添加主函数所需成员变量或成员方法。对应.cpp文件为win32Hellworld.cpp。其中代码如下:

// win32Hellworld.cpp : Defines the entry point for the application.

#include "stdafx.h"

#include "win32Hellworld.h"

 

#define MAX_LOADSTRING 100

 

// Global Variables:

HINSTANCE hInst;                                 // current instance

TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text

TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

 

// Forward declarations of functions included in this code module:

ATOM                MyRegisterClass(HINSTANCE hInstance);

BOOL                InitInstance(HINSTANCE, int);

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

 

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

// 使得未使用参数不会引起编译器警告

UNREFERENCED_PARAMETER(hPrevInstance);

UNREFERENCED_PARAMETER(lpCmdLine);

 

    // TODO: Place code here.

// 消息结构体

    // TODO: Place code here.

// typedef struct tagMSG {

// HWND hwnd;

// UINT message;

// WPARAM wParam;

// LPARAM lParam;

// DWORD time;

// POINT pt;

//#ifdef _MAC

// DWORD lPrivate;

//#endif

// } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

    MSG msg;

// 热键表

    HACCEL hAccelTable;

 

    // Initialize global strings

// 从资源文件中加载字符串

// hInstance是应用程序实例句柄

// uID是资源中的字符串编号

// lpBuffer是接收从资源里拷贝字符串出来的缓冲区

// nBufferMax是指明缓冲的大小

    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

    LoadString(hInstance, IDC_WIN32HELLOWORLD, szWindowClass, MAX_LOADSTRING);

// 注册窗体

    MyRegisterClass(hInstance);

 

    // Perform application initialization:

// InitInstance初始化实例。返回值:如果初始化成功则返回非零值,否则返回零值。备注:windows系统允许在同一时刻运行程序的几份拷贝。在概念上,程序的初始化被分为两部分:一次性的程序初始化工作,这些在应用程序第一次运行时完成。实例的初始化工作,每次运行程序的一个拷贝时都会执行这些操作,包括第一次运行。框架中的WinMain函数实现对这个函数的调用。重载这个函数以初始化在WINDOWS系统下运行的应用程序的每个新实例。通常重载该函数以构造主窗口对象并设置CWinThread::m_pThread数据成员,使其指向这个窗口。

    if (!InitInstance (hInstance, nCmdShow))

    {

        return FALSE;

    }

 

// 调入快捷键表。参数:HINSTANCE hInstance:模块的一个实例句柄,该模块的可执行文件中包含将要调入的快捷键表;LPCSTR lpTableName指向一个以空结尾的字符串的指针,该指针包含了即将调入的快捷键表的名字。返回值:若函数调用成功,则返回非零值,否则返回零值。备注:若快捷键表尚未载入,则可从指定的可执行文件将其装入。从资源中装载的快捷键列表在程序结束时可自动释放。

    hAccelTable = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDC_WIN32HELLOWORLD));

 

    // Main message loop:

// GetMessage从调用线程的消息队列里获取一个消息并将其放于指定结构中。该函数可取的与指定窗口联系的消息和由PostThreadMessage寄送的线程消息。此函数接受一定范围内的消息值。不接收其他线程或应用程序的消息。获取消息后,线程将从消息队列中删除该消息。函数一直等待直到有消息才会有返回值。其中参数:LPMSGMSG指针,用于从消息队列中获取消息;HWND取得其消息的窗口,当为NULL的时候该方法为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程;UNIT wMsgFilterMin指定被检索的最小消息的整数。UNIT wMSGFilterMax指定被检索的最大消息的整数。

    while (GetMessage(&msg, NULL, 0, 0))

    {

// 翻译快捷键表。该函数处理菜单命令中的快捷键。该函数将一个VM_KEYDOWMVM_SYSKEYDOWM翻译成VM_COMMANDVM_SYSCOMMAND消息,然后翻译结果发送到相应窗口的处理过程。该方法直到窗口处理消息完成后才返回。其参数:HWND hWnd:窗口句柄,该窗口消息将被翻译。HACCEL hAccTable快捷键表句柄,快捷键表必须由LoadAccelerators函数调用装入或者CreateAccd_eratorTable函数调用创建。LPMSG MSG结构指针,MSG结构中包含从GETMESSAGEPeekMessage函数调用线程消息队列得到的消息内容。返回值:如果函数成功则返回非零值,若失败则返回值为零。为了将该函数发送的消息与窗口菜单或控制发送的消息区别开来,使VM_COMMANDVM_SYSCOMMAD消息的vParam高位置1。用于从窗口菜单中选择菜单项的快捷键组合被翻译成VM_SYSCOMMAND,所有其他组合被翻译成VM_COMMAND。如果TranslateAccelerator返回非零值且消息已经被翻译,则应用程序不能调用TranslateMessage函数对消息再做处理。每一个快捷键不一定对应于菜单命令。如果快捷键对应菜单项,则VM_INIMENUVM_INITMENYPOPUP消息将被发送到应用程序,就好像用户正在操作。但如果以下条件成立其一,则这些消息不再发送:窗口被禁止、菜单项被禁止。

        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

        {

// 将虚拟键信息转换为字符信息。字符信息被寄送到调用线程消息队列中。当下一次线程调用GetMessage或者PeekMessage时被读出。参数:CONST MSG* lpMsg:指向含有消息的MSG结构的指针。该结构中包含调用GetMessage或者PeekMessage从消息队列中读取到的信息。返回值:如果消息被转换则返回非零值,如果消息是VM_KEYDOWNVM_KEYUPVM_SYSKEYDOWNVM_SYSKEYUP返回非零值,不考虑转换。否则返回零。注意:此函数不修改参数lpMsg指向的消息。

            TranslateMessage(&msg);

// 分发消息给窗口程序。消息通常是从GetMessage中获得。消息被分发到回调函数,作用是将消息传递给操作系统,之后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。参数:CONST MSG* lpMsg指向含有消息的结构指针。返回值:窗口程序的返回值。尽管返回值的信息依赖于被调度的消息,但返回值通常被忽略。备注:MSG结构必须包含有效信息。如果参数lpMsg是一个指向VM_TIMER消息,并且VM_TIMER的参数IPrama不为NULL,则调用IParam指向的函数,而不调用窗口程序。

            DispatchMessage(&msg);

        }

    }

// 该结果将传递给void PostQuitMessage(int nExitCode)当作其中nExitCode参数。

    return (int) msg.wParam;

}

 

//

// FUNCTION: MyRegisterClass()

//

// PURPOSE: Registers the window class.

//

// COMMENTS:

// This function and its usage are only necessary if you want this code to be compatible with Win32 systems prior to the 'RegisterClassEx' function that was added to Windows 95. It is important to call this function so that the application will get 'well formed' small icons associated with it.

ATOM MyRegisterClass(HINSTANCE hInstance)

{

    WNDCLASSEX wcex;

 

    wcex.cbSize = sizeof(WNDCLASSEX); // 大小

 

    wcex.style            = CS_HREDRAW | CS_VREDRAW; // 风格

    wcex.lpfnWndProc    = WndProc; // 窗口处理函数的指针

    wcex.cbClsExtra        = 0; // 指定紧跟在窗口类结构后的附加字节数

    wcex.cbWndExtra        = 0; // 指定紧跟在窗口实例后的附加字节数

    wcex.hInstance        = hInstance; // 本模块的实例句柄

// 图标的句柄。

// LoadIcon从指定模块的可执行文件中装入指定图标资源。仅当图标资源还没有被装入时该函数才执行装入操作,否则只是获取装入资源的句柄。参数:HINSTANCE hInstance指定的模块;LIPCSTR lpIconName指向空字符结尾的字符串的指针,他包含图标名。如果要使用windows预定义的图标,此处hInstance必须为NULL

// MAKEINTRESOURCE 原型:((LPWSTR)((ULONG_PTR)((WORD)(i))))将数字类型转换为指针类型的宏。不存在释放问题。用这个宏的主要原因是有的资源是用序号定义的,而不是字符串。所以要把数字类型转换为指针然后再传递给LoadResource之类的函数才能加载资源。

    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32HELLOWORLD));

// 光标句柄。

// LoadCursor从指定模块的可执行文件中装入指定光标资源。仅当图标资源还没有被装入时该函数才执行装入操作,否则只是获取装入资源的句柄。参数:HINSTANCE hInstance指定的模块;LIPCSTR lpCursorName指向空字符结尾的字符串的指针,他包含光标资源名

    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);

    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1); // 背景画刷的句柄

    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_WIN32HELLOWORLD); // 指向菜单的指针

    wcex.lpszClassName    = szWindowClass// 指向类名称的指针

    wcex.hIconSm    = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); // 和窗口类关联的小图标

 

// 为随后在调用CreateWindow函数和CreateWindowEx函数中使用的窗口注册一个窗口类。参数:CONST WNDCLASSEX* lpwcx指向一个WNDCLASSEX结构的指针。在传递给这个函数之前,必须在结构体内填充适当的类的属性返回值。如果这个函数成功则返回这个窗口类型的标识号,否则返回零。备注:如果使用RegisterClassEx来注册窗口类。应用程序通知系统被注册类的窗口的消息使用ANSI字符集的文本和字符参数。如果使用RegisterClassExw来注册,则应用程序使用Unicode来传递消息文本参数。

    return RegisterClassEx(&wcex);

}

 

//

// FUNCTION: InitInstance(HINSTANCE, int)

//

// PURPOSE: Saves instance handle and creates main window

//

// COMMENTS:

//

// In this function, we save the instance handle in a global variable and

// create and display the main program window.

//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

HWND hWnd;

 

hInst = hInstance; // Store instance handle in our global variable

 

// 创建个重叠式、弹出式或者子窗口。他指定窗口类、窗口标题、窗口风格、以及窗口初始位置和大小。如果要使用除CreateWindow支持的风格之外的扩展风格,需要使用CreateWindowEx函数。参数:LPCSTR lpClassName指定一个空结束的字符串或者整形数ATOM,如果该参数是整型数,则他是由之前的调用theGlobalAddAtom函数产生的全局量。这个小于0xC00016位数必须是lpClassName的低16位,该参数最高位必须是0.如果是一个字符串,则他制定了窗口的类名。这个类名可以是任何用RegisterClassEx注册的类名或者任何预定义的控制类名。LPCSTR lpWindowName窗口名。DWORD dwStyle指定窗体风格。接下来四个为起始点(左上角)以及大小,HWND hWndParent指向被创建的窗口的父窗口或所有者句柄。HMENU hMenu菜单句柄或者根据窗口风格指定一个子窗口标识,对于层叠式或者弹出式窗口hMenu指定了窗口使用的菜单,如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。HWND hInstance与窗口有关的模块实例句柄,lpParam指向一个指针,该值在IParam参数中得CREATESTRUCT结构传递。如果应用程序调用CreatWindow创建一个MDI子窗体,则lpParam必须指向一个CLIENTCREATESTRUCT结构。返回值:如果成功,则返回新窗口的句柄,否则返回零。

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 

if (!hWnd)

{

return FALSE;

}

// 设定指定窗口的显示状态。参数hWnd窗口句柄,nCmdShow窗口显示样式。返回值:如果窗口当前可见则返回非零,否则返回零

ShowWindow(hWnd, nCmdShow);

// 发送一个VM_PAINT来更新指定窗口的客户区

UpdateWindow(hWnd);

 

return TRUE;

}

 

//

// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)

//

// PURPOSE: Processes messages for the main window.

//

// WM_COMMAND    - process the application menu

// WM_PAINT    - Paint the main window

// WM_DESTROY    - post a quit message and return

//

// 窗口过程的回调函数。处理消息。参数:hWnd窗口句柄,message 消息ID以及两个消息参数

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    int wmId, wmEvent;

    PAINTSTRUCT ps;

    HDC hdc;

 

    switch (message)

    {

    case WM_COMMAND:

        wmId = LOWORD(wParam);

        wmEvent = HIWORD(wParam);

        // Parse the menu selections:

        switch (wmId)

        {

        case IDM_ABOUT:

            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

            break;

        case IDM_EXIT:

            DestroyWindow(hWnd);

            break;

        default:

            return DefWindowProc(hWnd, message, wParam, lParam);

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hWnd, &ps);

        // TODO: Add any drawing code here...

        EndPaint(hWnd, &ps);

        break;

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

 

// Message handler for about box.

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

    UNREFERENCED_PARAMETER(lParam);

    switch (message)

    {

    case WM_INITDIALOG:

        return (INT_PTR)TRUE;

 

    case WM_COMMAND:

        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

        {

            EndDialog(hDlg, LOWORD(wParam));

            return (INT_PTR)TRUE;

        }

        break;

    }

    return (INT_PTR)FALSE;

}

上面即为对于编辑器自动为我们生成的代码。运行结果如下:

为了更加生动一点,我们在这个窗体的中间增加一个按钮,并且赋给该按钮一个事件,当点击时弹出一个对话框。

Resource.h中增加

#define IDC_BUTTON1 1278

此处IDC_BUTTON为即将添加的BUTTON唯一性标识。(此处标识只要在父窗体内不重复即可,无需全局唯一)。然后在我们的主函数页面win32Hellworld.h中增加btn的创建以及事件响应。具体代码如下:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    int wmId, wmEvent;

    PAINTSTRUCT ps;

    HDC hdc;

    HWND hButton1;

 

    switch (message)

    {

 

case WM_CREATE:

// BUTTON的创建实现

hButton1 = CreateWindow(_T("button"), _T("点我"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 100, 100, 100, 30, hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);

break;

case WM_COMMAND:

        wmId = LOWORD(wParam);

        wmEvent = HIWORD(wParam);

        // Parse the menu selections:

        switch (wmId)

        {

        case IDM_ABOUT:

            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

            break;

case ID_FILE_EXIT:

case IDM_EXIT:

DestroyWindow(hWnd);

            break;

case IDC_BUTTON1:

MessageBox(NULL,_T("Hello World"),_T("Hello World"), MB_OK);

break;

        default:

            return DefWindowProc(hWnd, message, wParam, lParam);

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hWnd, &ps);

        // TODO: Add any drawing code here...

RECT rt;

GetClientRect(hWnd, &rt);

DrawText(hdc, _T("Hello world"), strlen("Hello world"), &rt, DT_CENTER);

 

        EndPaint(hWnd, &ps);

        break;

    case WM_DESTROY:

        PostQuitMessage(0);

        break;

    default:

        return DefWindowProc(hWnd, message, wParam, lParam);

    }

    return 0;

}

posted on 2011-10-13 19:00  BLoodMaster  阅读(3967)  评论(0编辑  收藏  举报