Windows黑客编程基础

前几天在网上看了"病毒"兄写的《WIN下编程须知》一文,觉得在编程方面要写出一篇适合初学者们看的入门级文章的确很重要,可惜病毒兄只在该文里介绍了线程、消息、句柄等几个基本概念。很多初学者看了对编程还是感到很迷惑,一个从来没有写过程序的人如何入门?如何在短时间内写出自己的程序来?笔者带着这些问题写了这篇文章。这也是笔者在学习编程的初期所遇到的困惑,在此根据笔者的个人理解将其整理成文,希望能引起广大菜鸟们的共鸣,对初学者们有所帮助。

  从理论上说,任何一门语言都可以在任何一个系统上编程,只要找到该系统提供的"接口"和对系统内部机制有深入的了解就可以了,至少我是这么认为的。正如c语言可以在windows下编程,也同样可以在Linux上大放异彩一样。

  编程是一项很繁杂的工作,除了应用编程工具之外,了解系统本身内部工作机理非常重要,这是你写出稳定兼容的程序所必不可少的前提条件。你要在哪一种系统上编程就要对该系统的机制进行研究,至少你应该知道一个程序在那个系统上是如何运行的。
 一、了解Windows 内部机制

  Windows 是一个"基于事件的,消息驱动的"操作系统。

  在Windows下执行一个程序,只要用户进行了影响窗口的动作(如改变窗口大小或移动、单击鼠标等)该动作就会触发一个相应的"事件"。系统每次检测到一个事件时,就会给程序发送一个"消息",从而使程序可以处理该事件。

  每个Windows 应用程序都是基于事件和消息的,而且包含一个主事件循环,它不停地、反复地检测是否有用户事件发生。每次检测到一个用户事件,程序就对该事件做出响应,处理完再等待下一个事件的发生。

  Windows 下的应用程序不断地重复这一过程,直至用户终止程序,用代码来描述实际上也就是一个消息处理过程的while循环语句。

  下面便简单介绍一下与 Windows 系统密切相关的几个基本概念:

  ⒈窗口:这是我要说的第一个概念。似乎是地球人都知道的事儿了,窗口是Windows本身以及Windows 环境下的应用程序的基本界面单位,但是很多人都误以为只有具有标题栏、状态栏、最大化、最小化按钮这样标准的方框才叫窗口。其实窗口的概念很广,例如按钮和对话框等也是窗口哦,只不过是一种特殊的窗口罢了。

  从用户的角度看,窗口就是显示在屏幕上的一个矩形区域,其外观独立于应用程序,事实上它就是生成该窗口的应用程序与用户间的直观接口;从应用程序的角度看,窗口是受其控制的一部分矩形屏幕区。应用程序生成并控制与窗口有关的一切内容,包括窗口的大小、风格、位置以及窗口内显示的内容等。用户打开一个应用程序后,程序将创建一个窗口,并在那里默默地等待用户的要求。每当用户选择窗口中的选项,程序即对此做出响应。

  ⒉程序:通常说的程序都是指一个能让计算机识别的文件,接触得最多的便是.exe型的可执行文件,这个不难理解。

  ⒊进程:说到进程,学过《操作系统》的人都很清楚,所谓进程就是应用程序的执行实例(或称一个执行程序)

  需要注意的是:进程是程序动态的描述,而上面说到的程序是静态的描述,两者有本质的区别。举个例子,从网上

  Down了一个瑞星杀毒软件到C盘但没有运行,那个.exe 可执行文件叫做程序,它是一个二进制码的文件。一旦双击了exe文件图标运行程序,那个"正在运行着的瑞星杀毒"便称为进程,它在双击的那一刻被系统创建,当你关机或者在任务栏的图标上单击鼠标右键选"退出"时,进程便消亡,彻底结束了生命。进程经历了由"创建"到"消亡"的生命期,而程序自始至终存在于你的硬盘上,不管你的机器是否启动。

  ⒋线程:线程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程本来就具有动态的含义,然而实质上是通过线程来执行体现的,从这个意义上说,Windows 中进程的动态性意义已经不是很明显了,只算是给程序所占的资源划定一个范围而已(个人观点,纯属个人理解,不必引起争议!),真正具有动态性意义的是线程。以前在大二学习操作系统课的时候就有个同学跟笔者提起这点,笔者还跟他驳得面红耳赤呢!现在想想,觉得很有道理,不得不佩服那位同学对Windows内部机制了解得如此清楚。

  之所以在此花那么多的篇幅说线程,是因为下面将要介绍到多线程编程技巧,如果不理解这点,那就很难应用到实践上,希望大家明白。
 ⒌消息:我们几乎做每一个动作都会产生一个消息,在用鼠标指点江山的今天,鼠标被移动会产生WM_MOUSEMOVE消息,鼠标左键被按下会产生WM_LBUTTONDOWN的消息,鼠标右键按下便产生WM_RBUTTONDOWN消息等等。所有的这些都可以通过GetMessage,SendMessage等函数得到,以后的操作中我们会经常接触到这些函数。

  ⒍事件:何谓事件?从它的字面意思我们就可以明白它的含义,如在程序运行的过程中改变窗口的大小或者移动窗口等,都会触发相应的"事件"。

  ⒎句柄:单单一个"柄"字便可以解释它的意思了,我们天气热摇扇子的时候只要抓住扇柄便可以控制整个扇子的运动了,在程序中也差不多是这个意思。通常一个句柄就可以传递我们所要做的事情。有经验的读者肯定清楚,编写程序总是要和各种句柄打交道的,句柄是系统用来标识不同对象类型的工具,如窗口、菜单等,这些东西在系统中被视为不同类型的对象,用不同的句柄将他们区分开来。

  看看C++ 教材中是如何给句柄下定义的:"在Win32里,句柄是指向一个无值型对象(void *)的指针,是一个4字节长的数据"。虽然我对它的本质是什么还是很迷惑,但我知道句柄并不是一个真正意义上的指针。从结构上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的内存位置(很多书都这么说,这正是我的迷惑所在),而实际上句柄指向的是一个包含了对该对象进行的引用的位置。在编程时,只要抓住了对象的句柄就可以对该对象进行操作了(我在《一个简单木马程序的编写与伪装策略》中说到的对QQ密码的截获就是要找到QQ登陆窗口的句柄后才开始截密行动的)。下面再举个例子来说明句柄的运用:编一个程序,使QQ登陆窗口的号码框和密码框均变黑,相关代码及解释:

  void __fastcall Tform1::formcreate(TObject *Sender)

  {

  HWND hCurWindow,HC,HE;//定义三个窗口句柄变量,hCurWindow用于存放QQ用户登陆窗口的句柄,HC、HE分别存放//号码框和密码框的句柄。

  if((hCurWindow= FindWindow(NULL,"QQ用户登录"))!=0  (hCurWindow=FindWindow(NULL,"OICQ用户登录"))!=0)

  {//很明显,调用FindWindow()函数去获得QQ登陆窗口的句柄

  String str;

  str.sprintf("0x%x",hCurWindow);

  }

  TCHAR wClassName[255];//类名变量

  HC=GetWindow(hCurWindow, GW_CHILD);//得到号码框的句柄

  HE=GetWindow(HC, GW_HWNDNEXT);//接着得到密码框的句柄

  GetClassName(HE, wClassName, sizeof(wClassName));//得到类名

  GetClassName(HC, wClassName, sizeof(wClassName));//得到类名

  EnableWindow(HE,false);//使窗口失效

  EnableWindow(HC,false);//使窗口失效

  }

  以上代码在C++ Builder下编译通过,只要运行次程序,QQ登陆窗口的号码框和密码框马上变黑色,无非是

  EnableWindow()函数所起的作用。

  你还可以添加一个Timer控件,将上面的代码copy到void __fastcall Tform1::Timer1Timer

  (TObject *Sender)函数中,并在后边加上这一句代码:

  SendMessage(hCurWindow,WM_CLOSE,0,0); 使QQ一启动就关闭,让别人永远也用不了QQ,挺有趣儿的哦:).

  ⒏API与SDK:API是英文 Application Programming Interface 的简称,意为"应用程序接口",泛指系统为应用程序提供的一系列接口函数。其实质是程序内的一套函数调用,在编程的时候可以直接调用,而不必知道其内部实现的过程,只知道它的原型和返回值就可以了,此外,手头经常放着一本"Windows API大全"之类的书也是必不可少的,不然你根本不知道哪些API是干什么用的,瞎编也编不出什么东西来。在后面我们会介绍调用API编程的例子,调用API编程工作虽然烦琐,但由于API函数都被封装在dll库里,程序只有在运行的时候才调用的,因此程序的体积小而且运行效率高。

  SDK是英文 Software Development Kit 的缩写,指"软件开发工具包",在防火墙的设计中就经常涉及到SDK。

  有关基本的概念就谈这些,那些C/C++的基本语法、什么是面向对象等知识请大家查阅相关的书,此类书籍各大书店已汗牛充栋,不再多叙。下面直接谈谈语种和编程工具的选择问题,这也是初学者们最迷惑的问题。
 ⒉写程序:问题可谈到点子上了,学那么多语言,读那么多程序最终还不是为了写程序,做出适合需要的软件来?"君子性非异也,善加于物也",笔者认为一切从借鉴开始,先是修改别人的程序,等到有了一定的程度再写出属于自己的程序。

  刚开始写程序,不要奢望一下子写出很出色的程序来,"万丈高楼平底起",编程贵在动手,只要你动手去写了,就算只有一句"printf("Hello!");"也是一次进步!此外,还要依照自身的能力循序渐进地写,开始的时候写一点功能简单的、篇幅短小的代码,力求简洁、完整,"麻雀虽小,但五脏俱全",然后在此基础上进行扩充,一点一点添加功能,下面笔者摘录一位国内一流编程高手、"豪杰超级解霸"的作者梁肇新的编程心得,请大家看

  看一个成功的程序员是如何写程序的,希望对广大菜鸟有所启发:

  写程序的方法:在Win98的环境中,先写主干,用最少的代码实现最基本的功能。然后一点点添加功能,每加一点都要调试。尽量少用动态分配、全局变量。充分利用操作系统直接提供的API。在Win98下调试通过之后,再在Win95下调试通过,然后是Win97,WindowsME,WinNT4.0。这样才能写出稳定、快速的程序。

  给程序员的建议:1、不要急于求成,这样往往欲速不达。2、不要什么东西都想学,什么都没掌握。3、每天都要自我总结,分析自己的错误率和废码率,不断加强自我管理。4、代码格式很重要。代码要规范、严谨,效率要高。5、不要盲从简单的开发工具(这点笔者不是很同意,最起码要有一定的功底的人才敢这么说)。6、有了成果要公开,

  不要舍不得,不然很快会过时的(以上两段摘自《程序员》增值合订本2001.上册P18,请读者前往参考)。

  参考书籍:

  《Windows C 程序设计》,清华大学出版社

  《超级解霸梁肇新》,《程序员》合订本

  黑客编程的几个基本技巧

  以下将要谈到的几个基本技巧很重要,虽然对于编程高手来说这是在玩小孩子把戏,但对于一位初学者,掌握以下几个技巧将为你的编程扫清道路,而且很容易编写出有趣的程序,培养你对编程的兴趣。
 技巧⒈学会修改注册表。

  相信大家都知道当浏览了一些网页恶意代码,IE标题、默认主页等被改得面目全非,这就是通过改动注册表来更改系统设置的例子。Windows中的注册表是个好东东,它是windows系统的灵魂,是许多软件记录数据的地方(当然也包括windows本身)。windows通过它记录大量的数据,然后在下一次启动时再读取相应的数据来设置系统。通过控制注册表就可以控制整个系统,所以很多的黑客程序都在注册表上动手脚(尤其是木马程序和作恶剧程序),

  学会修改注册表可以实现一些有趣而强大的功能。我们完全可以通过编程来操作注册表,达到与手动更改注册表 编辑器产生一样的效果。"超级兔子"中的大部分功能就是通过修改注册表来完成的。操作注册表有专门的API函数,大家可以参考有关资料,下面笔者以C++ Builder为例说明如何在程序中操作注册表:

  程序二:编程修改IE标题内容

  新建一个工程,在Unit1.h文件中包含Registry单元:

  #include

  然后就可以在.cpp文件操作注册表了,接着来!在窗体的Oncreate()里加入以下代码(你可以在try{}里面加入

  任何操作注册表的代码):

  TRegistry* Registry;

  Registry = new TRegistry();创建一个TRegistry类型的对象Registry,用于修改注册表。

  try{

  Registry->RootKey = HKEY_CURRENT_USER;//设置主键,这是必不可少的,设置好主键后,就可以操作这个主

  //键下所有的键值了。

  if( Registry->OpenKey("Software/Microsoft/Internet Explorer/Main",FALSE))//调用OpenKey()

  //打开.

  //括号里所指的键

  {

  Registry->WriteString("Window Title","台湾是中国的一部分,世界上只有一个中国!");

  //调用WriteString()往注册表里写入IE标题

  Registry->CloseKey();//关闭该键

  }

  else

  {//如果打开失败的话

  Registry->createKey("Software/Microsoft/Internet Explorer/Main");//就调用createKey()

  //新建上述键

  Registry->WriteString("Window Title","台湾是中国的一部分,世界上只有一个中国!");//再写入//IE标

  //题内容

  Registry->CloseKey();//最后关闭该键,这个也不能忽视,它跟上面的OpenKey成对使用的}//End of try

  __finally

  {//要是出错,跳到这里处理

  Registry->CloseKey();//关闭所要打开的键

  delete Registry;//销毁Registry对象,释放资源。

  }

  编译运行上面的代码就可以将IE的标题改为"台湾是中国的一部分,世界上只有一个中国!"了。笔者写了个小程序,可以测出当前的IE标题和默认主页是什么,并可随意修改他们,还可以禁止别人修改你的默认主页和注册表编辑器.。
 技巧⒉调用API编程

  其实这是最简单的,API是系统在DLL里为我们提供的程序接口,可以直接调用的。只要我们有一本《WindowsAPI大全》之类的书就足够了,下面举个简单的例子:

  程序三:调用API函数隐藏Windows的任务栏:

  HWND WndHandle;//定义句柄类型变量

  WndHandle=FindWindow("Shell_TrayWnd",NULL);//调用API函数FindWindow()获得任务栏的句柄

  ShowWindow(WndHandle,SW_HIDE);//再调用API函数ShowWindow()隐藏任务栏

  大家看到,在上面调用API函数FindWindow()和ShowWindow()的过程中,只要我们知道函数的

  名字和括号里的参数是什么就行了,至于实现的过程不必理会,也轮不到我们这些菜鸟去理会:)学会调用API,你可以写出功能强大的程序来,这一技巧对于初学者来说是必须掌握的(代码请参考黑防光盘)。

  技巧⒊多线程编程技术

  通过上一篇的介绍 ,大家都很清楚线程的概念了,它是进程内部的一个执行单元(如一个函数等),上期说了那么多理论,现在该派上用场了。编写多线程应用程序是指使程序在运行时创建多个线程并发地运行于同一个进程中。今年6月份横空出世的"中国黑客"病毒不是采用了全球独创的"三线程技术"吗?虽然笔者没机会分析它的样本代码,但此种病毒的工作效率如此之高是与它的多线程技术分不开的。

  使用多线程技术编程有如下优点:

  ①提高CPU的利用率。由于多线程并发运行,可以使用户在做一件事情的时候还可以做另外一件事。特别是在多个CPU的情况下,更可以充分地利用硬件资源的优势:将一个大任务分成几个小任务,由不同的CPU来合作完成。

  ②采用多线程技术,可以设置每个线程的优先级,调整工作的进度。

  清楚了使用多线程技术的优势之后,下面便来谈谈如何在C++ Builder环境下开发多线程的应用程序,在C++ Builder 环境中,通过 TThread 类就可以很方便地编写多线程应用程序(但不能直接使用,因此要派生新类),

  具体流程如下:

  从TThread 类派生出一个新的线程类->创建线程对象->设置线程对象的属性项->挂起或唤醒线程(根据具体情况操作)->结束线程。

  要说明一点的是:在应用程序中要合理地设置线程的优先级。不要因为某些线程的优先级很高而使其他一些线程因为等不到CPU的处理时间而被"饿死",也不要因为线程的级别都差不多而导致的频繁切换花费大量的CPU时间。(本段引自《C++ Builder 5 编程实例与技巧》P284)。
 技巧⒋让程序实现后台监控

  这是一个很基本的技巧。如果你是一个木马程序的爱好者,当你阅读众多的木马源程序的时候,就会发现100%的木马程序都很注意自身的后台监控本领,也就是隐身技术,面对不同的系统要施展不同的对策才能实现。很多杀毒程序就采用了这种后台监控技术,使程序随着系统的启动而运行,然后在后台悄悄地监视系统的一举一动,一发现有不对路的程序就把它"揪"出来示众。实现程序的后台监控技术有如下几个关键:

  ①正常运行时,不显示程序的窗体;

  ②系统每次启动都自动运行程序一次;

  ③程序图标不显示在任务栏上;

  ④不显示在按Ctrl+Alt+Del 调出的任务列表中;

  ⑤通过热键可以调出隐藏的窗体

  实现方法:对于①,要不显示窗体,我们可以编辑WinMain函数,设置ShowMainform值为False就可以隐藏程序的窗体了。参考代码:Application->ShowMainform = false ;对于②,可以利用技巧1所介绍的方法修改注册表,

  键值如下:HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun ,使用的是WriteString()

  方法。这是冰河等多种旧木马惯用的启动手段之一(当然还有文件关联、注入dll等方法);对于③,要使程序图标不显示在任务栏上,也很简单,调用API函数SetWindowLong 可以让程序运行后不出现在任务栏里,不过要放在窗体的Oncreate()里面。代码如下:

  SetWindowLong(Application->Handle,GWL_EXstyle,WS_EX_TOOLWINDOW);

  对于④,调用RegisterServiceProcess API 函数将程序注册成为一个服务模式程序,让它运行在较高的优先级下,就不会出现在程序列表中(对Win9X有效,WinNT/2000/XP下无效)。具体的代码请参考笔者的《一个简单木马程序的编写与伪装策略》一文,不在此重叙对于⑤,要先定义捕获Windows消息WM_HOTKEY的钩子函数,然后向Windows加入一个全局原子,并保留其句柄,最后向Windows登记热键,这个可以调用API函数RegisterHotKey来实现。

  技巧⒌使用定时触发器

  在C++ Builder 环境下,定时触发器即Timer控件,有时候我们希望程序隔一段时间重复执行相同的动作,比如对QQ密码截获的时候,就要隔一段间隔寻找一次QQ登录窗口。在C++ Builder中,只要将执行这些动作的代码放到一个Timer中去就OK了。

  听说"中国黑客"病毒运行几分钟后就自动创建一个新的线程,用于寻找OICQ的"发送消息"窗口,在10分钟内一直在找,一旦找到就将"去*****功"等带有政治色彩的言论发送给受害者QQ上的好友,10分钟后自动结束该线程。我想在查找"发送消息"窗口的10分钟内就运用了定时器,该病毒是用汇编开发的。可是在C++ Builder中是如何运用的呢?其实控件的出现使得编程变得很简单,添加一个Timer控件,设置几下控件的属性,

  双击Timer控件,将代码放到里面去就行了。程序执行的时候,相隔指定的时间就重复执行里面的代码了。实际上笔者在上一期的"程序一"中寻找QQ登录窗口时,就运用了定时器.

  有关编程技巧的介绍到此为止,请读者参考另类书籍,掌握更多的黑客编程技巧,编写出受欢迎的黑客程序来。
 五、Socket 编程与网络通信基础

  由于本文的主题是"黑客编程基础",而黑客是互连网上"来无影,去无踪"的黑衣人,如冰河、网络神偷等黑客程序都是基于互连网的,谈黑客编程离开网络编程就会大失其味。所以,下面接着谈谈网络编程,大凡基于网络应用的程序都离不开Socket。

  Socket 为套接字之意,是作为计算机与计算机之间通信的接口。有关Socket的概念在第6期《黑客防线>>的《Socket 编程的基础和基本过程》一文中有详细的描述,请大家参考,不在此多叙。需要指出的是:Winsock是访问众多的基层网络协议的一种接口,在每个Win32平台上,它都以不同的形式存在着,Winsock 是网络编程的接口,不是协议,这是容易弄错的地方。

  现在来谈谈Winsock 编程的过程,大凡在Win32平台上的Winsock编程都要经过下列的基本步骤:定义变量->获得Winsock版本->加载Winsock库->初始化->创建套接字->设置套接字选项->关闭套接字->卸载Winsock库,释放所有资源。

  下面以一道极其简单的程序来说明如何进行Winsock编程。程序四:编一个程序来获取本地机器的IP地址。使用Winsock提供的API函数是最基本的网络技术,为了给初学者看个清楚,笔者打算在Visual C++ 和C++ Builder下各写一个,便于大家区分这两种不同的编程工具的特性(对于本程序来说,他们都差不多,而对于某些通信程序,他们实现起来就相差很远了,但本质是差不多的)。先来看Visual C++ 下的源程序,实现步骤:打开Visual C++ ,从"File"菜单中的"New"新建一个工程,选中"Win 32 Console Application",意思是说生成的是Win32的控制台程序。另外,初学者要注意一点:只要程序中用到了 Winsock API 函数,都要在工程设置的Link 中增加 Ws2_32.lib 文件,不然程序将不能通过编译,方法是:点击"Project"菜单,选择"Settings... ALT+F7" ,在弹出的"Project Settings"对话框右侧选"Link"标签,再在"Project Options"下方的编辑框中增加Ws2_32.lib文件,点"OK"就可以了。
 加载好文件之后,就可以在CheckIP.cpp文件里加入以下代码了:

  //-------Begin from ------------

  //包含需要使用的头文件

  #include "stdafx.h"

  #include "windows.h"

  #include

  #include "stdio.h"

  #include "stdlib.h"

  #include "string.h"

  void CheckIP(void) //定义CheckIP()函数,用于获取本机IP地址

  {

  WORD wVersionRequested;// WORD类型变量,用于存放Winsock版本的正确值SADATA wsaData;

  char name[255];//定义用于存放获得的主机名的变量

  CString ip;//定义IP地址变量

  PHOSTENT hostinfo;

  wVersionRequested = MAKEWORD( 2, 0 );

  //调用MAKEWORD()获得Winsock版本的正确值,用于下面的加载Winsock库

  if ( WSAStartup( wVersionRequested, &wsaData ) == 0 ) {

  //现在是加载Winsock库,如果WSAStartup()函数返回值为0,说明加载成功,程序可以继续

  //往下执行

  if( gethostname ( name, sizeof(name)) == 0) {

  //如果成功地将本地主机名存放入由name参数指定的缓冲区中

  if((hostinfo = gethostbyname(name)) != NULL) {

  //这是获取主机名,如果获得主机名成功的话,将返回一个指针,指向hostinfo,hostinfo

  //为PHOSTENT型的变量,下面即将用到这个结构体

  LPCSTR ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);

  //调用inet_ntoa()函数,将hostinfo结构变量中的h_addr_list转化为标准的点分表示的IP

  //地址(如192.168.0.1)

  printf("%sn",ip);//输出IP地址 } }

  WSACleanup( );//卸载Winsock库,并释放所有资源 } }

  int main(int argc, char* argv[])//主函数,程序的入口

  {

  CheckIP();//调用CheckIP()函数获得、输出IP地址

  return 0;//由于main()定义为int型,所以应带回一个int型的数值

  }

    下面接着来看看在C++ Builder 下如何实现,其实两者的思想是一样的,只是在C++ Builder下实现的界面友好点而已,实现方法:打开C++ Builder 5,默认情况下已经新建一个工程,保存这个工程文件就可以了,构造如下面图4所示的界面,在相应之处添入下面的代码即可。

  程序代码:

  //包含头文件

  #include

  #include

  #pragma hdrstop

  #include "Unit1.h"

  #pragma package(smart_init)

  #pragma resource "*.dfm"

  Tform1 *form1;

  __fastcall Tform1::Tform1(TComponent* Owner)

  : Tform(Owner)

  { }

  void Tform1::GetHostIpAddress()

  {// GetHostIpAddress()获得本机IP地址

  struct hostent *thisHost;

  struct in_addr in;

  char MyName[80];

  char *ptr;

  WORD wVersionRequested;

  WSADATA wsaData;

  int err;

  wVersionRequested = MAKEWORD( 2, 0 );

  err = WSAStartup( wVersionRequested, &wsaData );

  if( err != 0 )

  return;

  if(LOBYTE( wsaData.wVersion ) != 2   

  HIBYTE( wsaData.wVersion ) != 0 )

  { WSACleanup( );

  return; }

  if(gethostname(MyName,80)==SOCKET_ERROR)

  return;

  if(!(thisHost=gethostbyname(MyName)))

  return;

  memset((void *)&in,sizeof(in),0);

  in.s_addr=*((unsigned long *)thisHost->h_addr_list[0]);

  if(!(ptr=inet_ntoa(in)))

  return;

  WSACleanup( );

  Edit1->Text=AnsiString(ptr);}

  void __fastcall Tform1::formcreate(TObject *Sender)

  { GetHostIpAddress();}

  void __fastcall Tform1::Button1Click(TObject *Sender)

  {Close();//添加一个"确定"按钮,点击即关闭程序。}

  程序在 C++ Builder 5 下编译通过,通过比较你会发现他们是大同小异的,对于同一程序,两者工具各有秋千,至于选择哪种由你决定,最好是两者相得益彰。"临渊羡鱼,不如退而结网",虽说"通往电脑的路不止一条",然而对于编程,道路却只有一条,就是:动手去做,亲身实践。

  参考书籍:

  《C++ Builder 5 编程实例与技巧》,机械工业出版社

  《WIN 编程须知》,病毒兄的作品,再次感谢病毒兄


<script src="http://www.blogbus.com/ads/ads.js" type="text/javascript"></script>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 Windows程序设计基础 1 1.1 Windows概述 1 1.1.1 Windows的发展历史 1 1.1.2 Windows技术特点 2 1.2 Windows程序特点 3 1.2.1 程序组成 3 1.2.2 数据类型 4 1.2.3 匈牙利命名法 6 1.2.4 Windows消息 7 1.2.5 运行模式 8 1.3 简单的Windows程序介绍 9 1.3.1 开始之前 9 1.3.2 WinMain函数 10 1.3.3 注册窗口类 11 1.3.4 建立窗口 13 1.3.5 窗口函数 14 1.3.6 窗口内的输出 15 1.4 上机步骤 16 1.4.1 进入开发环境 16 1.4.2 新建项目 17 1.4.3 修改项目选项 17 1.4.4 添加程序文件 18 1.4.5 编辑程序 18 1.4.6 调试运行 18 1.5 小结 19 1.6 练习题 19 第2章 MFC程序设计基础 21 2.1 MFC概述 21 2.1.1 MFC与应用程序框架 21 2.1.2 MFC的组成 21 2.1.3 MFC中的类 22 2.2 MFC程序的特点 23 2.2.1 概述 23 2.2.2 MFC与消息处理 23 2.2.3 运行模式 24 2.3 简单的MFC程序 25 2.3.1 开始之前 25 2.3.2 派生应用程序类 25 2.3.3 派生窗口类 26 2.3.4 建立窗口 26 2.3.5 加入消息映射 27 2.3.6 建立MFC应用程序对象 28 2.4 上机步骤 28 2.4.1 建立项目 28 2.4.2 修改项目属性 28 2.4.3 调试运行 28 2.5 使用资源 29 2.5.1 建立图标资源 29 2.5.2 在程序中使用图标资源 31 2.6 小结 31 2.7 练习题 32 第3章 常用MFC通用类 33 3.1 CRect、CPoint、CSize类 33 3.1.1 CRect类 33 3.1.2 CPoint类 33 3.1.3 CSize类 34 3.2 CString类 34 3.2.1 创建字符串 34 3.2.2 访问字符串数据 35 3.2.3 字符串的比较 36 3.2.4 子串函数 38 3.2.5 字符串处理函数 39 3.3 集合类 39 3.3.1 列表类CList 40 3.3.2 数组类CArray 43 3.3.3 映射类CMap 45 3.4 时间处理类 47 3.4.1 COleDateTime类 47 3.4.2 COleDateTimeSpan类 51 3.5 异常处理类 52 3.5.1 异常处理类的使用 53 3.5.2 MFC异常处理类简介 53 3.6 小结 54 3.7 练习题 55 第4章 文档视图程序 56 4.1 概述 56 4.2 文档 56 4.2.1 单文档对象程序 56 4.2.2 多文档对象程序 57 4.2.3 多文档类型程序 58 4.3 视 58 4.3.1 一个文档对象对应一个视对象 58 4.3.2 一个文档对象对应多个视对象 59 4.3.3 一个文档对应多个视类型 59 4.4 窗口框架 59 4.5 文档模板 60 4.6 建立标准单文档程序框架 61 4.6.1 新建项目 61 4.6.2 修改项目选项 62 4.6.3 完成向导 64 4.6.4 运行结果 65 4.7 单文档程序框架分析 66 4.7.1 Stdafx.h 66 4.7.2 Stdafx.cpp 67 4.7.3 0401.h 67 4.7.4 0401.cpp 68 4.7.5 MainFrm.h 72 4.7.6 MainFrm.cpp 73 4.7.7 TextDoc.h 77 4.7.8 TextDoc.cpp 78 4.7.9 TextView.h 81 4.7.10 TextView.cpp 82 4.8 小结 85 4.9 练习题 85 第5章 绘图输出 86 5.1 GDI与MFC 86 5.1.1 概述 86 5.1.2 设备环境类 87 5.1.3 GDI对象类 87 5.2 绘制图形 88 5.2.1 开始绘图 88 5.2.2 更改画笔 91 5.2.3 使用画刷 92 5.2.4 使用位图 93 5.3 输出文本 99 5.3.1 文本输出函数 99 5.3.2 更改文本颜色 100 5.3.3 更改字型、字体 102 5.4 坐标与坐标模式 106 5.4.1 坐标模式 107 5.4.2 MM_ANISOTROPIC坐标模式 108 5.4.3 MM_ISOTROPIC坐标模式 110 5.4.4 平移坐标 111 5.4.5 修改坐标方向 112 5.5 小结 113 5.6 练习题 114 第6章 用户输入 115 6.1 鼠标和键盘 115 6.1.1 鼠标消息 115 6.1.2 键盘消息 119 6.2 使用菜单 121 6.2.1 编辑菜单 121 6.2.2 处理菜单命令 123 6.2.3 修改菜单状态 125 6.2.4 使用弹出式菜单 127 6.3 小结 129 6.4 练习题 130 第7章 工具栏与状态栏 131 7.1 工具栏 131 7.1.1 编辑工具栏 131 7.1.2 处理工具栏命令 133 7.1.3 工具栏按钮状态 135 7.1.4 自定义工具栏 135 7.2 状态栏 141 7.2.1 默认状态栏 142 7.2.2 操作状态栏 143 7.3 小结 149 7.4 练习题 149 第8章 使用文件 150 8.1 CFile类 150 8.1.1 文件的建立、打开和关闭 150 8.1.2 文件的读、写 152 8.1.3 文件内容的定位与锁定 153 8.1.4 获取、设置文件状态 154 8.2 序列化 156 8.2.1 序列化的概念 156 8.2.2 Serialize函数 156 8.2.3 CArchive类 157 8.2.4 序列化应用实例 159 8.3 文件管理 162 8.3.1 文件操作 162 8.3.2 目录操作 163 8.4 小结 164 8.5 练习题 164 第9章 常用消息 165 9.1 消息的分类 165 9.2 系统消息 165 9.2.1 WM_CREATE 165 9.2.2 WM_CLOSE 166 9.2.3 WM_QUERYENDSEESSION 166 9.2.4 WM_DESTROY 167 9.2.5 WM_NCDESTROY 167 9.2.6 WM_TIMER 167 9.2.7 WM_PAINT 168 9.2.8 程序实例 169 9.3 用户自定义消息 171 9.3.1 消息标识 172 9.3.2 消息映射宏 172 9.3.3 消息发送 172 9.3.4 消息接收 173 9.3.5 使用系统热键消息 174 9.3.6 使用进程间消息 177 9.4 小结 180 9.5 练习题 181 第10章 对话框 182 10.1 概述 182 10.2 对话框模板资源 182 10.2.1 创建对话框模板资源 182 10.2.2 编辑对话框模板属性 183 10.2.3 在对话框模板中添加或删除控件 184 10.2.4 在对话框模板上调整控件 185 10.2.5 修改控件的属性 185 10.2.6 设定控件跳格次序 186 10.2.7 测试对话框模板资源 187 10.3 对话框类 187 10.3.1 模式对话框 188 10.3.2 模式对话框例子 188 10.3.3 非模式对话框 189 10.3.4 非模式对话框例子 189 10.4 自定义对话框 190 10.4.1 建立模板资源 191 10.4.2 建立CDialog派生类 191 10.4.3 为控件添加消息映射 192 10.4.4 为控件添加成员变量 193 10.4.5 使用CDialog派生类对象 194 10.5 基于对话框的MFC程序 194 10.5.1 建立项目 195 10.5.2 对话框程序框架分析 196 10.6 通用对话框 202 10.6.1 CFileDialog 203 10.6.2 CColorDialog 205 10.6.3 CFontDialog 206 10.7 小结 208 10.8 练习题 208 第11章 常用控件 210 11.1 概述 210 11.1.1 控件消息 210 11.1.2 通知消息 210 11.1.3 控件的创建 210 11.2 按钮(BUTTON) 210 11.2.1 按钮样式 211 11.2.2 按钮控件的通知消息 211 11.2.3 在对话框中使用按钮的例子 211 11.3 文本编辑框(EDITBOX) 213 11.3.1 文本编辑框的样式 214 11.3.2 文本编辑框控件的通知消息 214 11.3.3 在对话框中使用编辑框控件 214 11.4 静态控件(STATIC) 216 11.4.1 静态控件的样式 216 11.4.2 静态控件的通知消息 217 11.4.3 在对话框中使用静态控件 217 11.5 复选框 (CHECKBUTTON) 218 11.5.1 复选框的样式 218 11.5.2 复选框的通知消息 219 11.5.3 在对话框中使用复选框 219 11.6 单选按扭 (RADIOBUTTON) 219 11.6.1 单选按钮的样式 219 11.6.2 单选按钮的通知消息 219 11.6.3 在对话框中使用复选框和单选按钮 219 11.7 进程条 (PROGRESS) 221 11.7.1 进程条的样式 221 11.7.2 进程条的成员函数 221 11.7.3 在对话框中使用进程条控件 221 11.8 滑动条 (SLIDER) 222 11.8.1 滑动控件的样式 223 11.8.2 滑动控件的通知消息 223 11.8.3 微调控件的成员函数 223 11.8.4 在对话框中使用滑动条控件 224 11.9 Spin控件 224 11.9.1 微调控件的样式 225 11.9.2 微调控件的通知消息 225 11.9.3 微调控件的成员函数 225 11.9.4 在对话框中使用微调控件 226 11.10 组合框 (ComboBox) 227 11.10.1 组合框的样式 227 11.10.2 组合框的常用通知消息 228 11.10.3 在对话框中使用组合框 228 11.11 小结 229 11.12 练习题 229 第12章 使用树控件和列表控件 231 12.1 图像列表 231 12.1.1 建立图像列表 231 12.1.2 图像列表的操作 232 12.2 树控件 233 12.2.1 概述 233 12.2.2 树控件的创建 234 12.2.3 树控件的操作 238 12.3 列表控件 240 12.3.1 概述 240 12.3.2 列表控件的创建 241 12.3.3 列表控件的操作 245 12.4 小结 248 12.5 练习题 248 第13章 动态链接库 249 13.1 概述 249 13.2 创建标准Win32动态库 249 13.2.1 新建标准Win32动态库项目 250 13.2.2 添加函数 250 13.2.3 添加类 253 13.2.4 导出函数 253 13.2.5 导出自定义类 253 13.2.6 生成DLL 254 13.3 创建标准MFC动态库 254 13.3.1 新建MFC动态库项目 254 13.3.2 添加自定义函数 255 13.3.3 添加自定义类 258 13.3.4 导出自定义函数 258 13.3.5 导出自定义类 258 13.4 在程序中使用动态库 258 13.4.1 加载 DLL的方式 258 13.4.2 使用隐式加载 259 13.4.3 使用显式加载 260 13.5 小结 262 13.6 练习题 262 第14章 使用多任务 264 14.1 进程 264 14.1.1 进程的优先级 264 14.1.2 启动进程 265 14.1.3 进程的管理 267 14.2 线程 274 14.2.1 线程的优先级 275 14.2.2 线程的创建和终止 275 14.2.3 使用工作者线程 276 14.2.4 使用用户接口线程 277 14.3 进程、线程间的同步 279 14.3.1 等待函数 280 14.3.2 使用事件 281 14.3.3 使用临界段 282 14.3.4 使用互斥量 284 14.3.5 使用信号量 285 14.4 小结 287 14.5 练习题 288 附 录 289 附录A Windows窗口样式 289 附录B Windows虚键码表 292 附录C 常用数据结构 294 参考文献 306

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值