您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > (全)windows+sdk编程系列文章
windowssdk编程系列文章----消息框在本课中,我们将用C语言写一个Windows程序,程序运行时将弹出一个消息框并显示helloworld。理论:Windows为编写应用程序提供了大量的资源。其中最重要的是WindowsAPI(ApplicationProgrammingInterface)。WindowsAPI是一大组功能强大的函数,它们本身驻扎在Windows中供人们随时调用。这些函数的大部分被包含在几个动态链接库(DLL)中,譬如:kernel32.dll、user32.dll和gdi32.dll。Kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。除了上面主要的三个动态链接库,您还可以调用包含在其他动态链接库中的函数,当然您必须要有关于这些函数的足够的资料。动态链接库,顾名思义,这些API的代码本身并不包含在Windows可执行文件中,而是当要使用时才被加载。为了让应用程序在运行时能找到这些函数,就必须事先把有关的重定位信息嵌入到应用程序的可执行文件中。这些信息存在于引入库中,由链接器把相关信息从引入库中找出插入到可执行文件中。您必须指定正确的引入库,因为只有正确的引入库才会有正确的重定位信息。当应用程序被加载时Windows会检查这些信息,这些信息包括动态链接库的名字和其中被调用的函数的名字。若检查到这样的信息,Windows就会加载相应的动态链接库,并且重定位调用的函数语句的入口地址,以便在调用函数时控制权能转移到函数内部。如果从和字符集的相关性来分,API共有两类:一类是处理ANSI字符集的,另一类是处理UNICODE字符集的。前一类函数名字的尾部带一个A字符,处理UNICODE的则带一个W字符(我想W也许是代表宽字符的意思吧)。我们比较熟悉的ANSI字符串是以NULL结尾的一串字符数组,每一个ANSI字符是一个BYTE宽。对于欧洲语言体系,ANSI字符集已足够了,但对于有成千上万个唯一字符的几种东方语言体系来说就只有用UNICODE字符集了。每一个UNICODE字符占有两个BYTE宽,这样一来就可以在一个字符串中使用65336个不同字符了。几乎每一个API都有处理这两种字符集的形式,例如:MessageBoxA和MessageBoxW,其中MessageBoxA是适用于处理ANSI字符集的API。MessageBoxW是适用于UNICODE字符集的API。在c中为了调用方便,对这两个API进行了宏定义。统一使用MessageBox。编译的时候会根据编译设置决定是使用MessageBoxA还是使用MessageBoxW。下面摘自WINUSER.H中关于MessageBox的定义。WINUSERAPIintWINAPIMessageBoxA(HWNDhWnd,LPCSTRlpText,LPCSTRlpCaption,UINTuType);WINUSERAPIintWINAPIMessageBoxW(HWNDhWnd,LPCWSTRlpText,LPCWSTRlpCaption,UINTuType);#ifdefUNICODE#defineMessageBoxMessageBoxW#else#defineMessageBoxMessageBoxA#endif其中WINUSERAPI是一个宏,该宏定义了其修饰的函数是从其他库中导入的,还是自身定义的。#if!defined(_USER32_)#defineWINUSERAPIDECLSPEC_IMPORT#else#defineWINUSERAPI#endif为了两种字符集都可以支持,在处理字符时,我们使用_T()宏。该宏会根据你的设置,将你的字符串转变为相应的字符集。例子:(见光盘Helloword)#includewindows.h#includetchar.hint_stdcallWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnShowCmd){MessageBox(NULL,_T(helloworld),_T(MyFirstWindowsProgram),MB_OK);return1;}分析:当我们在工程中Settings里面设置如下图所示的UNICODE,_UNICODE时,代码中的_T(helloworld)和_T(MyFirstWindowsProgram)编译时都转化为unicode字符。MessageBox也会使用MessageBoxW函数。如果按照下图的设置,使用_MBCS.代码中的_T(helloworld)和_T(MyFirstWindowsProgram)编译时都转化为ANSI字符。MessageBox也会使用MessageBoxA函数。windowssdk编程系列文章----简单窗口程序理论:Windows程序中,在写图形用户界面时需要调用大量的标准WindowsGui函数。其实这对用户和程序员来说都有好处,对于用户,面对的是同一套标准的窗口,对这些窗口的操作都是一样的,所以使用不同的应用程序时无须重新学习操作。对程序员来说,这些Gui源代码都是经过了微软的严格测试,随时拿来就可以用的。当然至于具体地写程序对于程序员来说还是有难度的。为了创建基于窗口的应用程序,必须严格遵守规范。作到这一点并不难,只要用模块化或面向对象的编程方法即可。下面我就列出在桌面显示一个窗口的几个步骤:1.得到您应用程序的句柄(对于C程序,可选);2.得到命令行参数(如果您想从命令行得到参数,可选);3.注册窗口类(必需,除非您使用Windows预定义的窗口类,如MessageBox或dialogbox;4.产生窗口(必需);5.在桌面显示窗口(必需,除非您不想立即显示它);6.刷新窗口客户区;7.进入无限的获取窗口消息的循环;8.如果有消息到达,由负责该窗口的窗口回调函数处理;9.如果用户关闭窗口,进行退出处理。相对于单用户的DOS下的编程来说,Windows下的程序框架结构是相当复杂的。但是Windows和DOS在系统架构上是截然不同的。Windows是一个多任务的操作系统,故系统中同时有多个应用程序彼此协同运行。这就要求Windows程序员必须严格遵守编程规范,并养成良好的编程风格。例子:(见光盘FirstWindow)#includeWindows.h#includetchar.hHWNDhWinMain;TCHARszClassName[]=_T(MyClass);TCHARszCaptionMain[]=_T(MyFirstWindow!);TCHARszText[]=_T(Win32program,Simpleandpowerful!);WNDCLASSEXstdWndClass;//如果有消息到达,由负责该窗口的窗口回调函数处理LRESULTCALLBACKProcWinMain(HWNDhWnd,UINTMsg,WPARAMwParam,LPARAMlParam){switch(Msg){//如果用户关闭窗口,进行退出处理caseWM_CLOSE:{DestroyWindow(hWinMain);PostQuitMessage(NULL);}break;default:returnDefWindowProc(hWnd,Msg,wParam,lParam);}return0;}intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow){MSGstMsg;WNDCLASSEXstdWndClass;RtlZeroMemory(&stdWndClass,sizeof(stdWndClass));stdWndClass.hCursor=LoadCursor(0,IDC_ARROW);stdWndClass.cbSize=sizeof(stdWndClass);stdWndClass.style=CS_HREDRAW|CS_VREDRAW;stdWndClass.lpfnWndProc=ProcWinMain;stdWndClass.hbrBackground=(HBRUSH)COLOR_WINDOW;stdWndClass.lpszClassName=szClassName;stdWndClass.hInstance=hInstance;//注册窗口RegisterClassEx(&stdWndClass);//产生窗口hWinMain=CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,szCaptionMain,\WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);if(!hWinMain)return0;//在桌面显示窗口ShowWindow(hWinMain,SW_SHOWNORMAL);//刷新窗口客户区UpdateWindow(hWinMain);//进入无限的获取窗口消息的循环while(GetMessage(&stMsg,NULL,0,0)){TranslateMessage(&stMsg);DispatchMessage(&stMsg);}returnstMsg.wParam;}分析:看到一个简单的Windows程序有这么多行,您是不是有点想撤?但是您必须要知道的是上面的大多数代码都是模板而已,模板的意思即是指这些代码对差不多所有标准Windows程序来说都是相同的。在写Windows程序时您可以把这些代码拷来拷去,当然把这些重复的代码写到一个库中也挺好。其实真正要写的代码集中在WinMain中。这和一些C编译器一样,无须要关心其它杂务,集中精力于WinMain函数。唯一不同的是C编译器要求您的源代码有必须有一个函数叫WinMain。否则C无法知道将哪个函数和有关的前后代码链接。相对C,汇编语言提供了较大的灵活性,它不强行要求一个叫WinMain的函数。下面我们开始分析,您可得做好思想准备,这可不是一件太轻松的活。头文件:windows.h是编写windows程序必须要包含的,因为其中包含大量要用到的常量和结构的定义,windowd.h还没有包含windows所有的常量和结构定义,对于程序中我们用到的在windows.h定义之外的,我们可以通过察看msdn,找到该结构和函数所在的头文件和库文件,包含进来就行。tchar.h定义了我们用得宏_T(x).我们的程序调用的API在user32.dll(譬如:CreateWindowEx,RegisterWindowClassEx)和kernel32.dll(ExitProcess)中的函数,所以必须链接这两个库。接下来我如果问:您需要把什么库链入您的程序呢?答案是:先查到您要调用的函数在什么库中,然后包含进来。在VC6的settings中已经包含了常用的lib.如图所示。因此,我们在代码中就无需显式的加载用到的库。显式加载的方法是在代码中加入一句,例如:#pragmacomment(lib,kernel32.lib“)我们在前面曾经讲过,windows提供的API函数封装在几个DLL中,调用DLL中的这些API函数,有两种方法,我们现在用的就是其中一种,即静态加载办法。还有一种是动态加载,我们将在后面讲DLL的时候,再给大家介绍。windows应用程序中必须要有WinMain函数,这个函数是由C编译器需要的,代码编译后,在程序运行时,该函数由C运行库调用,传入4个参数。用户可以把它看作是程序的入口。该函数共有4个参数:应用程序的实例句柄,该应用程序的前一实例句柄,命令行参数串指针和窗口如何显示。Win32没有前一实例句柄的概念,所以第二个参数总为0。之所以保留它是为
本文标题:(全)windows+sdk编程系列文章
链接地址:https://www.777doc.com/doc-3723992 .html