深入浅出MFC-Win32程序
1、Windows程序运行本质:以事件为驱动、消息为基础!
2、Windows程序事件驱动特性包括消息的产生、获得、分派、判断、处理。
3、Win32 SDK程序开发流程
Windows程序由程序代码+UI资源两大部分组成,2个部分最后以RC编译器整合为一个完整的EXE文件。
UI资源:本质上也是二进制文件,需要借助各种工具产生,以不同的扩展名存在如.ico .bmp .cur等。程序员需要在资源描述文件(.rc)中描述它们,RC编译器读取RC文件的描述后将所有UI资源文件集中生成一个.RES文件,再与程序代码结合生成EXE可执行文件。
4、Windows程序依赖的函数库(.LIB)
Windows程序调用的函数分为C Runtime以及Windows API两部分:
- LIBC.LIB 是C Runtime函数库的静态链接版本。
- MSVCRT.LIB 是C Runtime的动态链接版本(MSVCRT40.DLL)的Import库,链接此函数库程序执行时必须有MSVCRT40.DLL。
- Windows API部分由Windows操作系统本身提供,主要是Windows的三大模块GDI32.DLL、USER32.DLL、KERNEL32.DLL。虽然它们都是在运行时链接,但是链接器在程序链接过程中必须知道函数的一些信息,才能够帮助程序在运行时顺利跳转到DLL执行。而这些函数相关的信息就存放在所谓的import库中,即GDI32.LIB USER32.LIB KERNEL32.LIB。(自己编写或第三方的动态库,通过隐式加载的方式时,都需要其对应的导入库即.lib文件和头文件;通过显式加载即LoadLibrary的方式则不需要)
5、需要的头文件
所有Windows程序都必须包含Windows.h,但是它一般只包含三大模块里面的API函数,如果需要使用其他系统DLL,则还需要包含其对应头文件。
6、消息为基础、事件为驱动
7、makefile
8、一个Win32程序
# filename : generic.mak # make file for generic.exe (Generic Windows Application) # usage : nmake generic.mak (Microsoft C/C++ 9.00) (Visual C++ 2.0) # usage : nmake generic.mak (Microsoft C/C++ 10.00) (Visual C++ 4.0) all: generic.exe generic.res : generic.rc generic.h rc generic.rc generic.obj : generic.c generic.h cl -c -W3 -Gz -D_X86_ -DWIN32 generic.c generic.exe : generic.obj generic.res link /MACHINE:I386 -subsystem:windows generic.res generic.obj \ libc.lib kernel32.lib user32.lib gdi32.lib
//--------------------------------------------------------------------- // 檔名 : generic.h //--------------------------------------------------------------------- BOOL InitApplication(HANDLE); BOOL InitInstance(HANDLE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------------- // Generic - 示範 Win32 程式的基礎寫法 // Top Studio * J.J.Hou // 檔名 : generic.c // 作者 : 侯俊傑 // 編譯聯結 : 請參考 generic.mak //--------------------------------------------------------------------- #include <windows.h> // Windows程序依赖的头文件 #include "resource.h" // 内部包含各个资源的资源ID #include "generic.h" // 本程式头文件 HINSTANCE _hInst; // Instance handle HWND _hWnd; char _szAppName[] = "Generic"; // 程序名称 char _szTitle[] = "Generic Sample Application"; // 窗口标题 //--------------------------------------------------------------------- // WinMain - Windows程式入口函数 //--------------------------------------------------------------------- int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; UNREFERENCED_PARAMETER(lpCmdLine); // 避免编译器警告 if (!hPrevInstance) if (!InitApplication(hInstance)) return (FALSE); if (!InitInstance(hInstance, nCmdShow)) return (FALSE); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); // 返回 PostQuitMessage 的参数 } //--------------------------------------------------------------------- // InitApplication - 注册窗口类 //--------------------------------------------------------------------- BOOL InitApplication(HINSTANCE hInstance) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; // 注册窗口过程函数 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "jjhouricon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); // 窗口背景颜色 wc.lpszMenuName = "GenericMenu"; // .RC中定义的菜单 wc.lpszClassName = _szAppName; return (RegisterClass(&wc)); } //--------------------------------------------------------------------- // InitInstance - 产生窗口 //--------------------------------------------------------------------- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { _hInst = hInstance; _hWnd = CreateWindow( _szAppName, _szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if (!_hWnd) return (FALSE); ShowWindow(_hWnd, nCmdShow); // 显式窗口 UpdateWindow(_hWnd); // 发送 WM_PAINT 消息 return (TRUE); } //--------------------------------------------------------------------- // WndProc - 窗口过程函数定义 //--------------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case IDM_ABOUT: DialogBox(_hInst, // WinMain的第一个参数,当前运用程序实例句柄 "AboutBox", // 对话框资源名称 hWnd, // 父窗口句柄 (DLGPROC)About // 对话框的窗口函数 ); break; case IDM_EXIT: // 使用者想结束程序,处理方式与 WM_CLOSE 相同。 DestroyWindow (hWnd); break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } break; case WM_DESTROY: // 窗口已经被销毁,程序即将结束 PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); } //--------------------------------------------------------------------- // About - 关于对话框的窗口过程函数 //--------------------------------------------------------------------- LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (TRUE); // 返回 TRUE 表示已经处理该消息,不需要再处理 case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, TRUE); return (TRUE); // 返回 TRUE 表示已经处理该消息 } break; } return (FALSE); // FALSE 表示我没有处理这个消息 } //------------------------ end of file ------------------------------
//--------------------------------------------------------------------- // 文件名: resource.h //--------------------------------------------------------------------- #define IDM_NEW 40001 #define IDM_OPEN 40002 #define IDM_SAVE 40003 #define IDM_SAVEAS 40004 #define IDM_PRINT 40005 #define IDM_PRINTSETUP 40006 #define IDM_EXIT 40007 #define IDM_UNDO 40008 #define IDM_CUT 40009 #define IDM_COPY 40010 #define IDM_PASTE 40011 #define IDM_LINK 40012 #define IDM_LINKS 40013 #define IDM_HELPCONTENTS 40014 #define IDM_HELPSEARCH 40015 #define IDM_HELPHELP 40016 #define IDM_ABOUT 40017
//--------------------------------------------------------------------- // 文件名: generic.rc //--------------------------------------------------------------------- #include "windows.h" #include "resource.h" jjhouricon ICON DISCARDABLE "jjhour.ico" GenericMenu MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "&New", IDM_NEW, GRAYED MENUITEM "&Open...", IDM_OPEN, GRAYED MENUITEM "&Save", IDM_SAVE, GRAYED MENUITEM "Save &As...", IDM_SAVEAS, GRAYED MENUITEM SEPARATOR MENUITEM "&Print...", IDM_PRINT, GRAYED MENUITEM "P&rint Setup...", IDM_PRINTSETUP, GRAYED MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT END POPUP "&Edit" BEGIN MENUITEM "&Undo\tCtrl+Z", IDM_UNDO, GRAYED MENUITEM SEPARATOR MENUITEM "Cu&t\tCtrl+X", IDM_CUT, GRAYED MENUITEM "&Copy\tCtrl+C", IDM_COPY, GRAYED MENUITEM "&Paste\tCtrl+V", IDM_PASTE, GRAYED MENUITEM "Paste &Link", IDM_LINK, GRAYED MENUITEM SEPARATOR MENUITEM "Lin&ks...", IDM_LINKS, GRAYED END POPUP "&Help" BEGIN MENUITEM "&Contents", IDM_HELPCONTENTS, GRAYED MENUITEM "&Search for Help On...", IDM_HELPSEARCH, GRAYED MENUITEM "&How to Use Help", IDM_HELPHELP, GRAYED MENUITEM SEPARATOR MENUITEM "&About Generic...", IDM_ABOUT END END AboutBox DIALOG DISCARDABLE 22, 17, 144, 75 STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU CAPTION "About Generic" BEGIN CTEXT "Windows 95", -1,0, 5,144,8 CTEXT "Generic Application",-1,0,14,144,8 CTEXT "Version 1.0", -1,0,34,144,8 DEFPUSHBUTTON "OK", IDOK,53,59,32,14,WS_GROUP END
WinMain函数是Windows程序的入口点,当使用者执行一个Windows程序时,Windows的Shell进程会调用加载器把该程序加载到进程地址空间,然后调用C Startup Code,C启动代码将调用WinMain函数开始执行程序,WinMain函数的四个参数由操作系统传递。
9、窗口类的注册与窗口的产生
未完,待更新。。。