首页 用C语言写聊天工具,类似于QQ

用C语言写聊天工具,类似于QQ

举报
开通vip

用C语言写聊天工具,类似于QQC 语言究竟能干什么 序言 鉴于现在已经大三了,很多同学很迷茫,自己学的东西到底能做什么,将来自己到底能干什么?我不想看着同学迷茫的面孔, 特别是几个好兄弟,有几个想学习编程,但又苦苦找不到门路的兄弟,所以想写点东西,希望对大家又点略微的帮助,以尽兄弟我的微薄之力。 很多同学学了C语言之后,可能难免会有所感叹:这就是C语言!总是感觉C语言竟然能写出Windows、Linux?为了解除同学们 的疑惑,也愿为同学们指点编程之道吧。我写的这些东西采用C语言,计划通过编程实例来讲解C编程的一些知识,让大家对C 能又更深一层...

用C语言写聊天工具,类似于QQ
C 语言究竟能干什么 序言 鉴于现在已经大三了,很多同学很迷茫,自己学的东西到底能做什么,将来自己到底能干什么?我不想看着同学迷茫的面孔, 特别是几个好兄弟,有几个想学习编程,但又苦苦找不到门路的兄弟,所以想写点东西,希望对大家又点略微的帮助,以尽兄弟我的微薄之力。 很多同学学了C语言之后,可能难免会有所感叹:这就是C语言!总是感觉C语言竟然能写出Windows、Linux?为了解除同学们 的疑惑,也愿为同学们指点编程之道吧。我写的这些东西采用C语言, 计划 项目进度计划表范例计划下载计划下载计划下载课程教学计划下载 通过编程实例来讲解C编程的一些知识,让大家对C 能又更深一层的理解和认识。当然,大家不要指望看了这些之后会写出一个操作系统来,但是我想,如果你认真看了的话,写 一个类似与QQ的聊天程序应该不难。 本来书是假期里照顾妈妈时写的,原想是1、不让自己的水平停滞不前,温故知新(两个月的假期是很长的) 2. 帮助一些同学,解决编程上的困惑 3.希望妈妈快点康复 4.让母亲和家里人知道自己一直都很努力,我是好样的 但现在母亲已经能够不在了,所以第三点,就改为原母亲在天之灵得到慰藉,早日放下烦恼,不用惦记我们。 C语言的基本语法我是不打算再提了,很多C语言编程的书,就是将一些基本的数据类型、数据结构、语法,然后就是一些数值 计算的实例,大多数都是雷同的,难免有抄袭之嫌,而且页没有多少实用价值。 本书以实用实例作为编程指导,指引大家编写真正实用的程序。了解到大家对黑客程序、病毒、窗口类程序比较感兴趣,因此我就拿这些实例进行讲解。基于大家基本都用Windows XP SP3,我也就在这个系统上把程序调试成功后再给大家讲解。编程环境,我还是喜欢Visual C++ 6.0 本书计划从四个大的方面来讲,这四个方面是:窗口类、文件操作类、网络类、数据库类。 都是时下流行的编程必备技术,也是软件开发者,必须掌握的技术。中间以实例讲解,逐步学习,相信大家看完后会有很大的提高的。 第一章 窗口类程序的编写 这一章就先来讲解下窗口类程序的编写。因为现在程序没有界面,就像人没有脸面一样,而且好的界面更能吸引人。从基本的界面开始,相信能给大家指明出一条路的,使大家很容易地掌握窗口序的编写。其实界面 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 利用VC 6.0 的MFC,很容易地制作出来。这里从底层开始写代码来写界面程序,使大家知道一些底层的东西,为以后学习打下好的基础,相信您学了这些,再用VC 的MFC会得心应手的。 1.1 用 C 写的第一个一个窗口程序 作为编程的开始,我们还是以一个Hello World来开始我们的学习之旅。代码如下: #include void main() { printf("Hello World!"); } 这是一个再简单不过的C程序了,只要有点C语言的知识就能够懂的,不过这里估计还有些人,到现在还不知道#include 中的头文件stdio.h到底是什么东西,我就来说下了,stdio.h是一个文本文件,存在于磁盘上的,已VC为例它的位置如下图: 也许你听说过printf()函数是在stdio.h中预定义的,但是你见过其定义的形式没有,没有且看下图 其定义形式,就如图中所示,也许你并不懂前面那些东西是什么,不用担心,以后我会慢慢解释给大家的。函数是先定义才能使用的,所以stdio.h中定义printf函数,我我们在引用了stdio.h头文件后就可以在程序中调用printf函数了。 上面是在命令行中显示一个“Hello World!”,没什么意思,下面我写一个窗口程序,显示个Hello World! #include void main() { MessageBox(NULL," Hello World!","我的第一个窗口程序",MB_OK); } 编译运行后如下图: 弹出的是一个对话框,上面有Hello World,还有一个标题和一个“确定”按钮。 当然你会说这对话框也算个窗口吗?这里肯定的告诉你:是的,对话框是窗口程序的一个子集。你可能还会这样问,这样一个简单的窗口有啥用呢,其实这样的窗口非常有用,我们在操作计算机的时候,会出现一些警告或提示的对话框,都是基本是这种方法写出来的。就算是这个很简单,学习本来不就是有易向难,有浅显深奥去的过程吗。 整个效果几乎就是靠一个函数MessageBox的功劳。这里也先不介绍这个函数了,说些其他的。 其实用C编写一些恶程序,就是把编程环境中所提供的一些函数熟悉了基本就可以了。用VC来写成序,其中的头文件有很多,定义了很多Windows API 函数 、数据结构、宏,可以让我们大家运用,通过它们,我们可以快速开发出使用的程序。这些Windows API在微软的MSDN上查,上面有很多说明,部分还有代码示例。不会是可以输入函数名,查找相关信息,建议大家用英文版的Library,因为其内容比中文版的全面,英语不好的同学呢,就先看中文了 中文MSDN:http://msdn.microsoft.com/library/zh-cn/ 英文MSDN:http://msen.micorsoft.com/library/en-us/ 到这里,我们就完成第一个有界面程序的编写,你感觉写有界面的程序难吗?显然不难。 下面看一个向锋和波波感兴趣的程序:九九乘法 采用命令行形式 #include “stdio.h” int i=0,j=0; for(i=1;i<10;i++) for(j=1;j 目录 工贸企业有限空间作业目录特种设备作业人员作业种类与目录特种设备作业人员目录1类医疗器械目录高值医用耗材参考目录 资源的名字一样。如果使用整型id 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示菜单,可以用MAKEINTRESOURCE定义一个宏。如果它的值为NULL,那么该类创建的窗口将都没有默认的菜单。 lpszClassName 窗口类的名字,字符串类型。 hIconSm 小图标的句柄,在任务栏显示的图标,可以和上面的那个一样。 定义一个WNDCLASSEX类型变量后,在给变量成员初始化后,我们就可以用 RegisterWindowEx(&wndclassex)来注册这个窗口类了。 这个注册过程,就和我们平常创建一个项目一样,都要先注册才能创建 。 2.​ 创建窗口 这一步很简单,就是利用CreateWindowEx()函数来创建就是了。 CreateWindowEx函数的原型如下: HWND CreateWindowEx(           DWORD dwExStyle,     LPCTSTR lpClassName,     LPCTSTR lpWindowName,     DWORD dwStyle,     int x,     int y,     int nWidth,     int nHeight,     HWND hWndParent,     HMENU hMenu,     HINSTANCE hInstance,     LPVOID lpParam ); 参数说明 dwExStyle:指定窗口的扩展风格。该参数可以是下列值: WS_EX_ACCEPTFILES:指定以该风格创建的窗口接受一个拖拽文件。    WS_EX_APPWINDOW:当窗口可见时,将一个顶层窗口放置到任务条上。    WS_EX_CLIENTEDGE:指定窗口有一个带阴影的边界。    WS_EX_CONTEXTHELP:在窗口的标题条包含一个问号标志。 WS_EX_CONTROLPARENT:允许用户使用Tab键在窗口的子窗口间搜索。    WS_EX_DLGMODALFRAME:创建一个带双边的窗口;该窗口可以在dwStyle中指定WS_CAPTION风格来创建一个标题栏。    WS_EX_LEFT:窗口具有左对齐属性,这是缺省设置的。    WS_EX_LEFTSCROLLBAR:如果外壳语言是如Hebrew,Arabic,或其他支持reading order alignment的语言,则标题条(如果存在)则在客户区的左部分。若是其他语言,在该风格被忽略并且不作为错误处理。    WS_EX_LTRREADING:窗口文本以LEFT到RIGHT(自左向右)属性的顺序显示。这是缺省设置的。    WS_EX_MDICHILD:创建一个MD子窗口。   WS_EX_NOPATARENTNOTIFY:指明以这个风格创建的窗口在被创建和销毁时不向父窗口发送WM_PARENTNOTFY消息。 WS_EX_OVERLAPPED:WS_EX_CLIENTEDGEWS_EX_WINDOWEDGE的组合。 WS_EX_PALETTEWINDOW:WS_EX_WINDOWEDGE, WS_EX_TOOLWINDOW和WS_WX_TOPMOST风格的组合WS_EX_RIGHT:窗口具有普通的右对齐属性,这依赖于窗口类。 WS_EX_RIGHTSCROLLBAR:垂直滚动条在窗口的右边界。这是缺省设置的。    WS_EX_RTLREADING:如果外壳语言是如Hebrew,Arabic,或其他支持读顺序对齐(reading order alignment)的语言,则窗口文本是一自左向右)RIGHT到LEFT顺序的读出顺序。 WS_EX_STATICEDGE:为不接受用户输入的项创建一个3一维边界风格   WS_EX_TOOLWIDOW:创建工具窗口,即窗口是一个游动的工具条。 WS_EX_TOPMOST:指明以该风格创建的窗口应放置在所有非最高层窗口的上面并且停留在其L,即使窗口未被激活。使用函数SetWindowPos来设置和移去这个风格。    WS_EX_TRANSPARENT:指定以这个风格创建的窗口在窗口下的同属窗口已重画时,该窗口才可以重画。   由于其下的同属富日已被重画,该窗口是透明的。 IpClassName: 窗口类的名字。 lpWindowName:指向一个指定窗口名的空结束的字符串指针。其实就是窗口的名字。 dwStyle:指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格。 x:窗口的横坐标。 y:窗口的竖坐标。 nWidth:窗口的宽度。 nHeight:窗口的高度。 hMenu:菜单句柄,或依据窗口风格指明一个子窗口标识。 hlnstance:与窗口相关联的模块事例的句柄。 lpParam:指向一个值的指针,该值传递给窗口 WM_CREATE消息 返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。 3.​ 显示窗口 显示窗口就是更简单的事情了。 连个函数轻松搞定,第一个函数就是ShowWindow(),原型如下: BOOL ShowWindow(            HWND hWnd,//当前的窗口句柄      int nCmdShow //可见状态 ); 因为CreateWindowEx函数创建的窗口是在内存中的,并没有显示到显示器上,用ShowWindow()函数,设定窗口的可见状态,并把数据从内存中移动到显卡上,以便显示。 第二个函数就是UpdateWindow(); 函数原型:   BOOL UpdateWindow(HWND hWnd);   描述:   这个 UpdateWindow 函数通过发送重绘消息 WM_PAINT 给目标窗体来更新目标窗体客户区的无效区域。如果那个窗体的无效区域没有,就不发送重绘消息 WM_PAINT 了 。注意了,这个 API 函数是直接发送消息 WM_PAINT 给目标窗体的,没有进入过消息队列。   函数参数:   hWnd 一个要更新的窗体的句柄   函数返回值:   如果函数调用成功,返回值为非零值。 如果函数调用不成功,返回值为零。 经过这三步后,一个窗口就实现了,就创建了出来,难不,也真够难的,Windows想的正周到,把创建过程的每一个细节都给想到了,每毫秒可能发生的事情都想到了,难怪Windows那么贵,还不开源。也算是人间的产品嘛,费的心血可真不少呀。说难其实也不难,创建一个窗口程序也就三步:一注册,二创建,三显示。很容易就ok了。这T他妈容易了吧。 原来就是这些的,我想我已经说的挺明白的了,如果你有什么疑惑,可以给我发邮件(cangsanbujin@126.com) 下面我们就按照上面所说的来编程实现一个窗口: #include //回调函数 LRESULT WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) { switch(Msg)//处理消息过程,什么是消息,下节再讲 { case WM_DESTROY://响应鼠标单击关闭按钮事件 PostQuitMessage(0);//退出消息队列,至于什么是消息队列,下节说 return 0;//退出函数 } return DefWindowProc(hWnd,Msg,wParam,lParam); } //主函数 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { char *cName = "myWindow"; WNDCLASSEX wc; HWND hWnd; MSG Msg; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.cbSize = sizeof(WNDCLASSEX); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//通过函数来设置一个白色的背景,这里大家设置为NULL看看,会很有趣的 wc.hCursor = NULL;//不设置 wc.hIcon = NULL;//不设置 wc.hIconSm = NULL;//不设置 wc.hInstance = hInstance;//当前程序的句柄,hInstance是有系统给传递的 wc.lpfnWndProc = WinProc;//窗口处理过程的回调函数。 wc.lpszClassName =(LPSTR)cName;//窗口类的名字。 wc.lpszMenuName = NULL;//目录名,不设置 wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wc);//在系统中注册 hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,cName,"我的窗口我喜欢",WS_OVERLAPPEDWINDOW, 200,100,600,400,NULL,NULL,hInstance,NULL);//创建窗口,窗口标题为"我的窗口我喜欢" if(hWnd == NULL) {//容错处理 MessageBox(NULL,"There's an Error","Error Title",MB_ICONEXCLAMATION|MB_OK); return 0; } ShowWindow(hWnd,nShowCmd);//显示窗口 UpdateWindow(hWnd); //下面是对消息的循环处理,大家先不必管这些,下节课我会细说的 while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg);//翻译消息 DispatchMessage(&Msg);//分派消息 } return Msg.message; } 编译运行后,可以看到一个白色背景的窗口出来了。如下图 哎,这一节,篇幅可是真有点长的,看完估计得换几口气吧,但是只要你看到了这些,你的水平就立马上了一个档次。想你看完后也许会头昏脑胀的,没有再看下去的信心的,但是估计当你把我的代码复制到VC中编译运行后,看到一个可爱的窗口时,肯定又会重新点燃你心中学习的热情吧,因为你已经看到了成功,看到了成就,一种成就感犹然自心中生,自信也提起来了,这比什么都好,人嘛就得对自己充满信心的。所以大家要发扬持之以恒的精神,坚持和我一起把这段苦闷的入门过程给走完,那么编程就不再是痛苦,而是一种乐趣。其实写这些程序很多东西都不用去记的想WNDCLASSEX结构的成员及成员作用,这些都不用去死记,只要知道有这么个东西,到时时再查就可以了,编程用到的函数、结构体那么多,谁想记呀。这一节已经留下了些问题,在下节介绍的,大家如果有余力的话,可以先查下资料的。 1.4 鼠标指针特效 大家在都玩过网络游戏吧,里面的界面都是很吸引人的,好的界面的确能给人以美的感受。而里面的鼠标并不是我们平常见到的箭头了,而是独具匠心的。网游我就只玩过魔域,所以就以魔域为例,魔域中的鼠标是这样的 。今天我们就来实现让鼠标到程序窗口上就变为我们想要的图案。 在写代码之前,我们还是先来看下先驱知识,这里要说的就是上节说资源了,当时大家看了可能并不知道什么是资源,这里就详细说一下。 大家知道Windows程序都有图标,鼠标有光标,窗口上有图片、按钮、文字等等,这些都是程序的部分,这样就是程序的资源。程序没有进入内存运行的时候,我们就叫它可执行文件吧,在磁盘保存的时候,并不只是保存了程序运行的代码部分(即cpu指令部分),还有一些图片、字符、按钮、图标并不是在代码段的。可执行文件的大致机构如下图 一个可执行文件是很复杂的,这里就简单的画这么一个难看的图,知道资源所在的大概位置,能理解程序的执行部分和知道程序的图标是从哪来的就可以了。 今天我们只是修改鼠标的指针,所以用到的资源,只有鼠标的光标资源而已。资源的源文件是以rc为扩展名的脚本文件(仍然是C语言格式的,很简单),有资源编译器Rc.exe编译成以res为扩展名的二进制资源文件,最后用连接器,把res文件和obj文件连接到一起就成了我们的程序exe文件了,现在知道了程序编译后要连接了吧。光标的图片格式有两中cur和ani的。这个文件我在魔域的图片库里面找到了就复制到,当前项目目录下。下面来定义下资源文件myOwnCursor.rc //myOwnCursor.rc written by xhk 2009.3.1 #include //资源文件要用到的图文件 #define CUR 0x1000 //定义资源的ID,为整型id CUR CURSOR "myOwnCursor.ani" //用到的光标图案 写完后,在命令提示符下进入目录,然后用rc.exe编译,输入rc myOwnCursor.rc命令,回车 我们查看下项目目录下多了个myOwnCursor.RES的文件,就是编译生成的二进制资源件。 接下来就该编写代码了,来应用这个资源文件,建立myOwnCursor.c文件,其实代码和上节所写代码很相似的,只是稍微加以修改而已。 #include #define CUR 0x1000 //预定义光标的id //回调函数 LRESULT WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) { switch(Msg)//处理消息过程,什么是消息,下节再讲 { case WM_DESTROY://响应鼠标单击关闭按钮事件 PostQuitMessage(0);//退出消息队列,至于什么是消息队列,下节说 return 0;//退出函数 } return DefWindowProc(hWnd,Msg,wParam,lParam); } //主函数 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { char *cName = "myWindow"; WNDCLASSEX wc; HWND hWnd; MSG Msg; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.cbSize = sizeof(WNDCLASSEX); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//通过函数来设置一个白色的背景,这里大家设置为NULL看看,会很有趣的 wc.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(CUR));//这里改了,来载入光标资源 wc.hIcon = NULL;//不设置 wc.hIconSm = NULL;//不设置 wc.hInstance = hInstance;//当前程序的句柄,hInstance是有系统给传递的 wc.lpfnWndProc = WinProc;//窗口处理过程的回调函数。 wc.lpszClassName =(LPSTR)cName;//窗口类的名字。 wc.lpszMenuName = NULL;//目录名,不设置 wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wc);//在系统中注册 hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,cName,"我的窗口我喜欢",WS_OVERLAPPEDWINDOW, 200,100,600,400,NULL,NULL,hInstance,NULL);//创建窗口,窗口标题为"我的窗口我喜欢" if(hWnd == NULL) {//容错处理 MessageBox(NULL,"There's an Error","Error Title",MB_ICONEXCLAMATION|MB_OK); return 0; } ShowWindow(hWnd,nShowCmd);//显示窗口 UpdateWindow(hWnd); //下面是对消息的循环处理,大家先不必管这些,下节课我会细说的 while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg);//翻译消息 DispatchMessage(&Msg);//分派消息 } return Msg.message; } 用vc编译生成myOwnCursor.obj,把myOwnCursor.obj和myOwnCursor.res放到同一个文件夹下,然后在命令行下进入它们所在的目录 ,输入命令:linke kernel32.lib user32.lib gdi32.lib /subsystem:windows myOwnCursor.obj myOwnCursor.res把两个文件连接成myOwnCursor.exe.运行后界面如下; 看到了吧,当鼠标移入窗口的时候,光标就变成了那个手型图案了, 这和魔域的是一样的。到现在想想一个特效又咋地,不还是一句一句代码写出来的,而特效和普通程序往往只有数据代码不同而已。网络游戏的界面很好看,也只不过是资源文件用的比较多而已,而且计算量很大,所以网游总是很占内存的,因为图片、声音文件都很大,而且变换比较多、快,就比较占用资源了。 其实再好的程序,只要有了思路,就能写出来,而且写出来也难的,是不是,今天大家应该会有点收获了,都会设计个性的鼠标光标了,比起以前学习C的东西,应该有一种层次感了吧。这些东西都比较接近系统了,所以学了之后,你对Windows系统也会有很深的了解的。如果各位看官看到本节还有兴趣继续看下去,那么这对小人就是一种支持,小人在此谢过了;如果看官觉得看这些没有半点收获,那么请看官不要再勉强自己看下去了,免得浪费看官大人的宝贵时间,那是小人所承担不起的。 总之了,要想写好程序,就得多练,编译连接过程中很容易发现错误的所在,那么这时你解决一个错误你就提高一次,解决的错误越多越快,你就学的越多越快。终于后来你会发现,你太难找到错误了,那么恭喜你,你已经升级为大虾了,已经完全脱离了菜菜级了。希望大家继续努力! 1.5 在窗口上写上“Hello World” 这一节我们乘胜追击,来继续深入学习下,学习窗口处理时间的东东。 也许你以前听说过,windows系统是消息驱动的,可是可能根本就不知道什么消息,更不知道什么消息驱动了。其实什么是消息呢,说白了就是我们点鼠标击键盘而程序发生反应,消息是一种数据,就是我们点鼠标击键盘后,系统把我们的操作封装到数据中,然后发送给程序,让程序对我们点鼠标击键盘的动作做出反应,当然程序也可以置之不理。Windows可是一个多任务的系统,而且同时可能产生很多的击键动作,那么同时可能能会有很多消息,windows系统为了更好的管理维护这些消息,就把这些消息加入消息队列中,消息队列其实就是消息的集合。 学过VB的人知道,VB中的程序是事件驱动的,因为一般都是发生时,调用相应的事件处理函数,所以整个处理过程都好像是事件引发的一样。这里的事件就是指我们击键的动作等。 学过JAVA的人知道,JAVA中有事件适配器,来捕获相应的事件,并交给相应的处理方法进行处理。 其实三种语言的处理过程也都是大同小异,只不过JAVA和VB把这些处理过程给封装了,VB尤其封装的更厉害,所以编程者不必考虑和知道这中间的细节问题,仍然可以编写出实用的程序,但正是由于细节的原因,用VB的开发的程序并不能高效地处理问题。 而C语言本身就是面向过程的语言,所以这一过程可以用C语言更好地表现出来,这也是我用C而不用C++的原因之一。 通过前几节的学习,我们知道了,在窗口程序中都有一个处理窗口的函数,其实所有的消息将会得到怎样的处理,都是此函数安排的。现在大家再回去看看那个程序代码和注释,相信应该能明白些了吧。 系统产生的消息是不断的,但是中间是有间隔的,程序要想知道有没有自己的消息,得不停地去问系统,问系统当前有没有属于自己的消息,这就需要一个循环来实现了。 下面先看下前两节种用到的消息循环代码: while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg);//翻译消息 DispatchMessage(&Msg);//分派消息 } Windows为消息定义一种新的数据类型MSG,用于保存消息的相关信息。在windows中GetMessage函数从消息队列种取得消息,填写好MSG结构并返回,如果获取的消息是WM_QUIT消息,则退出循环。 TranslateMessage将MSG结构传给Windows进行一些键盘消息的转换,当有键盘按下或者放开时,Windows产生WM_KEYDOWN和WM_KEYUP或WM_SYSKEYDOWN和WM_SYSKEYUP消息(像WM_KEYDOWN这些都是微软定义的一些宏,是什么意思,看字面意思就可以知道了),但是这些消息的参数种包含的是按键的扫描码(暂时不用理会),转换成常用的ASCII码要经过查表,很不方便,TranslatMessage遇到键盘消息则将扫描码转换成ASCII码并在消息队列种插入WM_CHAR或WM_SYSCHAR消息,参数就是转换好的ASCII码,如此一来,要处理键盘消息的话只要是处理WM_CHAR消息就好了。菊与刀非键盘消息TranslateMessage则不做处理。 最后,由DispatchMessage将消息发送到窗口对应的窗口过程去处理。窗口过程返回后DispatchMessage函数才返回,然后开始新一轮的消息循环。 想想我们这节的目的是为了在洁白的窗口种写下“Hello World”,那么我们怎么来留下我们的笔迹呢?窗口我们是能做出来了,那么怎么在上面写东西呢,等等,在上面写东西的前提是不是窗口做出来之后,当初我是这么想的,后来看到别人的代码才知道原来可以在窗口绘制的过程就绘制“Hello world”了。Windows有时真是个细心的家伙,把窗口创建到显示的一瞬间又给划分了很多小的过程。在绘制窗口时,Windows会产生WM_PAINT消息,那么我们在得到这个个消息的时候,来留下我们的笔迹,岂不就是下手最早的时刻。其实Windows在屏幕上输出文字和图像是一样的,都是在屏幕上画,和我们在纸上画图和写字是一样的,都是用笔来画的,只不过用的笔不一样而已,如果牵强用一支笔去做所有的工作,效果并不会理想的。Windows的笔也是这样的,不过这些笔是函数而已,画图和画文字的函数不一样而已。 下面就接着上节修改的代码继续修改,必要的注释和改变的地方我会标明的 #include #define CUR 0x1000 //预定义光标的id HDC hDC;//HDC是指设备上下文(暂时不用管,只要能这样用就可以了)的句柄 //PAINTSTRUCT要绘制的信息,详情请登陆http://msdn.microsoft.com/en-us/library/dd162768(VS.85).aspx //了解下就可以了,没什么重要的东西 PAINTSTRUCT paint; RECT rect;//RECT用来存储窗口信息的结构,只要是窗口的坐标、宽度和高度。 //回调函数 LRESULT WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) { switch(Msg)//处理消息过程,什么是消息,下节再讲 { case WM_PAINT: //BginPaint做些绘画的开始工作,填充PAINSTURCT结构,返回设备上下文(暂时不用理解)句柄 hDC=BeginPaint(hWnd,&paint); //GetClientRect用来获取窗口所在客户区的位置大小信息 GetClientRect(hWnd,&rect); //DrawText就是Windows用来“画字”的笔了,DT_*之类是指文字的样式,看字面意思也能看懂的 //有多少样式呢,可以查看这里http://msdn.microsoft.com/en-us/library/ms901121.aspx //本例中是单线、水平居中和竖直居中。 DrawText(hDC,"Hello World!",-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); //EndPaint就是做些收尾的工作了。 EndPaint(hWnd,&paint); break; case WM_DESTROY://响应鼠标单击关闭按钮事件 PostQuitMessage(0);//退出消息队列,至于什么是消息队列,下节说 return 0;//退出函数 } return DefWindowProc(hWnd,Msg,wParam,lParam); } //主函数 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { char *cName = "myWindow"; WNDCLASSEX wc; HWND hWnd; MSG Msg; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.cbSize = sizeof(WNDCLASSEX); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//通过函数来设置一个白色的背景,这里大家设置为NULL看看,会很有趣的 wc.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(CUR));//这里改了,来载入光标资源 wc.hIcon = NULL;//不设置 wc.hIconSm = NULL;//不设置 wc.hInstance = hInstance;//当前程序的句柄,hInstance是有系统给传递的 wc.lpfnWndProc = WinProc;//窗口处理过程的回调函数。 wc.lpszClassName =(LPSTR)cName;//窗口类的名字。 wc.lpszMenuName = NULL;//目录名,不设置 wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wc);//在系统中注册 hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,cName,"我的窗口我喜欢",WS_OVERLAPPEDWINDOW, 200,100,600,400,NULL,NULL,hInstance,NULL);//创建窗口,窗口标题为"我的窗口我喜欢" if(hWnd == NULL) {//容错处理 MessageBox(NULL,"There's an Error","Error Title",MB_ICONEXCLAMATION|MB_OK); return 0; } ShowWindow(hWnd,nShowCmd);//显示窗口 UpdateWindow(hWnd); //下面是对消息的循环处理,大家先不必管这些,下节课我会细说的 while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg);//翻译消息 DispatchMessage(&Msg);//分派消息 } return Msg.message; } 最终运行结果: 其实就是比原来的多了三个变量和几句代码,多的我也标出来了,而且都说明,那些简单的函数,大家可以自己查下,很简单的,我就不再为一些简单的函数来打字了,这样也可以锻炼大家的动手能力。 编译连接后,大家看看预期的结果出现了吧,洁白的窗口上留下了我们的字迹。建议学过VB或JAVA的读者,可以联系起来想一想,把C的处理消息过程给理解下,理解下消息的结构和概念,熟悉西Windows的消息机制,这样就可以为以后编写优质的软件打下坚实的基础。此言不虚的,像金山词霸的屏幕取词功能就是对Windows消息巧妙的运用;键盘记录器(木马)也是利用了截获Windows消息,而记录我们的按键行为,从而盗取信息的。大家好好理解下本节内容,自己动手写点东西,查些其他的事件信息,改进下程序,多熟练下,为后面的学习做一点铺垫。 1.6 让窗口响应鼠标的事件 为了让大家能够多熟悉下事件和消息的概念,本节再以一个小的例子看下鼠标事件的应用。鼠标的事件有单击、右击、双击和滚动轮的,我们这里先让鼠标响应两种事件:单击和右击。我们在实现在窗口上单击时弹出一个上面 有“你击了左键”的对话框,右击时弹出一个上面有“你击了右键”的对话框。代码仍用上节的,只在窗口处理过程的,消息处理语句(switch)中加入一下代码: case WM_LBUTTONUP://鼠标左键松开时 MessageBox(hWnd,"你击了左键","提示",MB_OK); break; case WM_RBUTTONUP://鼠标右键松开时 MessageBox(hWnd,"你击了右键","提示",MB_OK); break; 编译运行,单击左键如下图 当然,至于是弹出对话框还是干别的什么,你可以自己添加代码的。不管怎样,我想通过这个例子,你应该理解了程序是怎么处理鼠标的单击和右击了吧,应该对消息驱动有了更好一点理解吧。自己多写写代码,多查查资料成就很快的。就在写这个实例的时候,因为VC 6.0的MFC中定义的消息和API中的不太一样,一时忘了API中鼠标事件的宏是怎么写的,我查了MSDN、百度和谷歌,竟然没有查出来(真是岂有此理),最后,我就只有自己解决了,硬是在winuser.h的头文件中找到鼠标事件消息的宏定义的。真个过程中有一种山穷水尽疑无路,柳暗花明又一村的感觉,就在我快要放弃的时候,想起来了用基本的方法,直接查看头文件的定义,真可谓天才,然是最笨的方法了。不过这样也好,一下子看了很多消息的宏定义。大家学习一定要自己多查多练习,相信聪明的你一定会轻松解决遇到的问题的。想我这么笨的人,都学会了用C写Windows程序,又何况聪明的你呢。 1.7 单击鼠标来改变窗口的位置 目的还是为了大家进一步熟悉Windows的窗口实现消息的机制,也使大家了解多一点的Windows API 函数,从而利于日后的实际编程。平常我们都是用鼠标拖着窗口来改变窗口的,今天我们来点新鲜的,通过单击鼠标来使窗口改变位置。 从前面的知识中,我们知道,窗口的初始位置是在CreateWindow函数中设定的,Windows既然可以让用户通过鼠标拖来改变窗口位置,那么肯定就有函数是专门用来改变窗口位置的。是的,的确有这样的函数,常用的有两个,它们是SetWindowPos和MoveWindow。两个函数的详细情况如下: SetWindowPos   函数功能:该函数改变一个子窗口,弹出式窗口式顶层窗口的 尺寸 手机海报尺寸公章尺寸朋友圈海报尺寸停车场尺寸印章尺寸 ,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被
本文档为【用C语言写聊天工具,类似于QQ】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_315285
暂无简介~
格式:doc
大小:944KB
软件:Word
页数:74
分类:互联网
上传时间:2011-08-12
浏览量:57