概述
现在市场上出现了很多应用程序框架,比如窗体程序,如MFC,.net framwork , VB , delphi,举不胜数。其实,这些并不是开发win32应用程序必需的东西,windows在底层是为我们开放了一套API函数库,使用这套函数库,其实我们也能构建出一套功能强健的win32应用程序。
Win32的窗口应用程序,其实,win32窗口程序的核心就是窗口,一个win32窗口应用程序是由无数的窗口构成。
win32程序框架
一个Win32程序是由程序代码和UI(User Interface)两大部分组成,当我们编辑好这两部分后,再由RC(resource compiler)编译器将这两部分整合成一个EXE文件。程序代码不用说了,UI资源指的是一些如菜单、对话框、位图、鼠标指针、图标等,我们必须在一个.rc文件中描述它们。
另外,程序要想成功编译运行,还需要加入一些函数库和头文件。Windows程序调用的函数可以分为C Runtimes和Windows API两种,LIBC.LIB是C Runtimes的静态连接版,MSVCRT.LIB是C Runtimes的动态连接版。GDI32.DLL、USER32.DLL和KERNEL32.DLL是32位Windows API的三大函数库。所有的windows程序都要包含windows.h,但windows.h只包含GDI32.DLL、USER32.DLL和KERNEL32.DLL中的函数,如果你还想加入别的dll,就需要加入相应的头文件。
Win32编程一般遵循以下几个步骤:注册窗口(主要是声明调用主窗体处理消息的函数),创建窗口(创建实例主窗口和子窗口,控件),显示窗口,更新窗口,消息循环。我们常常只需要做的是,创建子窗体与控件,和定义消息体函数和在相应的条件下发送消息。
实例源码
#include "stdafx.h" #include "myWin32Window.h" #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); /* _tWinMain()是win32应用程序的入口函数。其win32的固定步骤:注册窗口类,创建窗口,显示窗口,更新窗口,消息循环。 */ int APIENTRY _tWinMain(HINSTANCE hInstance,//当前实例句柄,是本进程的句柄,它主要用来为以后做参数传递给需要调用的函数 HINSTANCE hPrevInstance,//前一个实例句柄 LPTSTR lpCmdLine,//命令行字符 int nCmdShow)//窗口显示方式,最大(3),最小(7),正常(1),隐藏等 { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_MYWIN32WINDOW, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MYWIN32WINDOW)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // 目的: 注册窗口类。 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; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYWIN32WINDOW)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+11); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MYWIN32WINDOW); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // 目的: 保存实例句柄并创建和显示主窗口 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, //窗口类名称 szTitle, //窗口标题 WS_OVERLAPPEDWINDOW,//窗口风格,定义为普通型 CW_USEDEFAULT,//窗口位置的x坐标 0,//窗口位置的y坐标 CW_USEDEFAULT, //窗口的宽度 0, //窗口的高度 NULL, //父窗口句柄,若不为空,则表示为某一个父窗口创建一个子窗口 NULL, //菜单句柄 hInstance, //应用程序实例句柄 NULL);//窗口创建数据指针 if (!hWnd)//hWin保存好创建主窗口的句柄,为以后调用(如创造子窗口或此窗口的控件时要需要此参数) { return FALSE; } //-----------在此可以创建子窗口或控件 //显示并更新窗口 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // 目的: 处理主窗口的消息。 // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 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); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);//弹出关于窗口,About是回调函数,用来处理其窗口的消息 break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 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; }