以下程序使用vc6.0 自动生成的
主要步骤:
1、一般是先调用RegisterClassEx()函数用当前窗口句柄去向操作系统申请(或称登录)将要创建一个什么样的窗口,申请成功后;
2、再调用CreateWindowEx()函数创建一个窗口对象,这仅仅是一个外观;
3、还要调用ShowWindow()函数设置初期表示,即最大或最小或普通等;
4、最后还要调用UpdateWindow()函数向窗口传送WM_PAINT消息来画出窗口里面的内容;
5、窗口创建完后,这是一个“静止”的窗口,因此还要在WinMain()函数的最后添加消息循环,最后才return;
6、WinMain()函数完了之后,还要再编写一个“窗口消息处理”函数。
主要API:
1、ATOM RegisterClassEx ( CONST WNDCLASSEX *lpwcx ); 注册窗口
ATOM 即WORD,也就是unsigned short
2、CreateWindow()函数创建一个窗口,这儿说的窗口是广义的窗口,事实上按钮也是窗口,也是由这个函数创建的。其中最关键的是第三个参数,先看一下函数原型。
HWND CreateWindow(
LPCTSTR lpClassName, //窗口名
LPCTSTR lpWindowName, //窗口标题
DWORD dwStyle, //窗口式样
int x, //窗口左上角的x坐标
int y, //窗口左上角的y坐标
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //菜单句柄
HINSTANCE hInstance, //实例句柄
LPVOID lpParam //创建参数
);
窗口式样有以下几种
WS_OVERLAPPEDWINDOW
层叠式窗口,有边框、标题栏、系统菜单、最大最小化按钮,是以下几种风格的集合:WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX
WS_POPUPWINDOW
弹出式窗口,是以下几种风格的集合: WS_BORDER,WS_POPUP,WS_SYSMENU。WS_CAPTION与WS_POPUPWINDOW风格一起使用时窗口菜单才能可见
WS_OVERLAPPED 层叠式窗口,有标题栏和边框,与WS_TILED风格类似
WS_POPUP 弹出式窗口,与WS_CHILD不能同时使用
WS_BORDER 窗口有单线边框
WS_CAPTION 窗口有标题栏
WS_CHILD 子窗口,不能与WS_POPUP同时使用
WS_DISABLED 为无效窗口
WS_HSCROLL 水平滚动条
WS_ICONIC 初始化为最小化
WS_MAXIMIZE 初始化为最大化
WS_MAXIMIZEBOX 有最大化按钮
WS_MINIMIZE 与WS_MAXIMIZE一样
WS_MINIMIZEBOX 窗口有最小化按钮
WS_SIZEBOX 边框可进行大小控制的窗口
WS_SYSMENU 创建一个有系统菜单的窗口,必须与WS_CAPTION风格同时使用
WS_THICKFRAME 创建一个大小可控制的窗口,与WS_SIZEBOX风格一样.
WS_TILED 创建一个层叠式窗口,有标题栏
WS_VISIBLE 窗口为可见
WS_VSCROLL 窗口有垂直滚动条
3、消息循环
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) //GetMessage()的返回值一直不为0,直到接受WM_QUIT时才为0(也就是false)
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);//DispatchMessage()是将消息传给窗口消息处理函数
}
}
消息的结构体:
typedef struct {
HWND hwnd; //接受消息的窗口的句柄
UINT message; //消息(应用程序只能用低字节,高字节留给系统用)
WPARAM wParam; //消息的第一附加信息
LPARAM lParam; //消息的第二附加信息
DWORD time; //Specifies the time at which the message was posted.
POINT pt; //Specifies the cursor position, in screen coordinates, when the message was posted.
} MSG , *PMSG ;
4、消息处理函数
Windows中消息的种类大致有2种,即系统消息和应用程序消息,消息的前缀也多种多样。不过日常用到的消息大都以“WM_”开头,而且许多消息的wParam和lParam都为0(也就是不使用),一般只有“WM_COMMAND”菜单命令或键盘鼠标的消息才使用wParam和lParam。
Windows中消息虽然很多,但并不是每一消息都要编程处理,我们一般把不需要特别处理的消息交给缺省消息处理函数DefWindowProc(),例子中的default部分便是。另外,有一函数必须处理,也就是关闭窗口消息WM_DESTROY,这时必须调用PostQuitMessage(0)来向操作系统发送一条终止程序的消息。
用的最多的消息可能是WM_PAINT,当窗口改变大小、或有别的窗口从这个窗口面前经过,这个窗口中的文字或图案被冲掉,这就必须重新描画。因此,窗
口中要显示的文字或图像一般都是在WM_PAINT中实现的。下面我们以在窗口上显示一行字作例子,不过,这时要稍微知道一点GDI(Graphic Device Interface)
的知识。
case WM_PAINT: //重画窗口消息
hdc = BeginPaint(hWnd, &ps);//开始描画
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);//取窗口有效区域
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);//显示文字
EndPaint(hWnd, &ps);//结束描画
break;
//
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, //当前窗口实例句柄 这里的APIENTRY 即__stdcall
HINSTANCE hPrevInstance, //前一个实例句柄,Win32下为NULL
LPSTR lpCmdLine, //命令行参数字符
int nCmdShow) //窗口的显示方式
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32HELLO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); //注册窗口类
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) //初始化窗口
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WIN32HELLO);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) //消息循环
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);//消息解释
DispatchMessage(&msg);//消息发送
}
}
return msg.wParam; //注意:不能用“return 0;”,因为有非正常退出的可能性
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is 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) //AUTO 即WORD 也就是unsigned short
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX); //这个结构体的长度,一般用sizeof(WNDCLASSEX)设置
wcex.style = CS_HREDRAW | CS_VREDRAW; //窗口式样
wcex.lpfnWndProc = (WNDPROC)WndProc; //窗口消息处理的函数名
wcex.cbClsExtra = 0; //分配给窗口类结构之后的额外字节数,一般为0
wcex.cbWndExtra = 0; //分配给窗口实例之后的额外字节数,一般为0
wcex.hInstance = hInstance; //想要申请的窗口实例句柄
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_WIN32HELLO); //运行时的图标,NULL时取系统缺省图标
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //光标
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//背景
wcex.lpszMenuName = (LPCSTR)IDC_WIN32HELLO; //菜单
wcex.lpszClassName = szWindowClass; //窗口名
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); //缩小时的图标,NULL时取系统缺省图标
return RegisterClassEx(&wcex); //原型:ATOM RegisterClassEx ( CONST WNDCLASSEX *lpwcx );
}
//
// FUNCTION: InitInstance(HANDLE, 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.
//
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// 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
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)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...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY: //必须处理的消息 关闭窗口消息
PostQuitMessage(0); //必须调用PostQuitMessage(0)来向操作系统发送一条终止程序的消息(WM_QUIT)
break; //WM_QUIT消息只能用PostMessage ,因为该消息将导致应用程序释放消息环,也就无法返回结果。
default:
return DefWindowProc(hWnd, message, wParam, lParam); //不需要特别处理的消息
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
1. 实例(instance): 这是C++的内容,“类”相当于结构体的数据类型,用“类”这种类型去定义一个变量(如果是指针,则假定已经得到了空间),这个变量就是那个“类”的“实例”。它和C语言中的变量是一回事,不过只有用“类”定义的变量才称为“实例”。
2. 句柄(handle):这是C语言的内容,和文件句柄一样,它实际上是一个整数,用来标识是哪一个实例,也就是实例的标识符。通过句柄可以操作这个实例。
3. 回调(CALLBACK):这其实是C语言中的函数指针,函数指针一般在大项目搭框架时常常使用。也就是你设计好要得到什么,把接口定义好,具体怎么实现完全交给别人,别人只要把函数名传给你就OK。这个函数名就是地址,不过取这种地址的指针在定义上与普通指针有些不同。