博文

第20课 钩子与数据库编程(2007-05-01 15:40:00)

摘要:1.Hook简介:作用是拦截某些消息,关键函数是SetWindowsHookEX()2.示例程序:  1.新建一基于对话框工程,InnerHook,此过程的钩子是只拦截本进程的。  2.在OnInitDialog()中添加代码:   g_hWnd=m_hWnd;g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());设置了鼠标钩子g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,GetCurrentThreadId());设置了键盘钩子  3.完成钩子函数的编写:HHOOK g_hKeyboard=NULL;HHOOK g_hMouse;HWND g_hWnd=NULL;LRESULT CALLBACK MouseProc(   int nCode,      // hook code   WPARAM wParam,  // message identifier   LPARAM lParam   // mouse coordinates){  return 1;}LRESULT CALLBACK KeyboardProc(   int code,       // hook code   WPARAM wParam,  // virtual-key code   LPARAM lParam   // keystroke-message information){  //if(VK_SPACE==wParam || VK_RETURN==wParam)如果是空格键  /*if(VK_F4==wParam && (1==(lParam>&g......

阅读全文(2486) | 评论:0

第19课 DLL编程(2007-05-01 15:40:00)

摘要:1.DLL简介,动态库,静态库。动态库节约磁盘空间,静态库体积大。可以用多种语言编写DLL文件。动态库有两种加载方式:隐式调用和动态加裁!2.新建一个DLL1的dll工程,加入一源文件名为dll1.cpp,加入add和subtract两个函数,注意此时须在函数名前加_declspec(dllexport),并且编译。用dumpbi -exports dll1.dll查看其导出的函数,发现函数名字已经被改成了 ?add@@YAHHH@Z,这种现象叫做名字粉碎,是为了支持函数重载而做的。3.编写一个程序测试DLL,工程名为DllTest,基于对话框的,放置两个按纽add和subtract,响应按纽消息,调用这个Dll的add和subtract函数。使用这两个函数前要先声明函数,//extern int add(int a,int b);//extern int subtract(int a,int b);还需要将Dll1.lib和Dll1.dll拷贝到当前目录下!另外还需要在Project->Setting->Link->Object/Library中加入Dll1.lib,此种方式为隐式调用!OK!用Dumpbin -imports DllTest.exe查看它的输入信息,可以看到它加亓薲ll1.dll。同时也可以用depends程序查看程序需要哪些dll文件!除了用extern外,还可以用//_declspec(dllimport) int add(int a,int b);//_declspec(dllimport) int subtract(int a,int b);告诉编译器,此函数是动态链接库中的函数,这样可以提高效率。4.通常写Dll时在dll1.h中声明函数,然后在DllTest.h中包含这个头文件,另外会用一组宏来取代_declspec(dllimport)Dll1.h#ifdef DLL1_API#else#define DLL1_API extern "C" _declspec(dllimport)#endif DLL1_API int _stdcall add(int a,int b);DLL1_API int _stdcall subtract(int a,int b);Dll1.cpp的代码:#define DLL1_API......

阅读全文(2721) | 评论:0

第18课 ActiveX编程(下面X均为ActiveX简称)(2007-05-01 15:40:00)

摘要:1.在VB中调用X控件,添加方法 project->Add components。另外可以用Object Browser来查看控件2.在VC中创建X控件  1.新建一个X工程名为Clock,注意一个文件中可以包含多个控件。  2.保持缺省设置,完成。注意它生成的三个类,以及相关的接口。  3.运行它。选择TSTCON32.exe作为容器。  4.选择Insert Control,此时我们可以看到,它画了一个椭圆。也可以在VB中测试。  5.删除注册信息。用regsvr32 /u +文件名。也可以在菜单选择反注册命令。  6.重写代码。在CClockCtrl::OnDraw()中画了一个椭圆,此时我们在其中得到系统时间,并显示它。为此我们在OnCreate()设置了一个定时器,每隔一定时间发出一个Invalidate()消息,使窗口重绘。  7.如何改变控件的背景色和前景色?ClassWizard->AutoMation->Add Property->BackColor,还需要在OnDraw()中加上相应的代码   CBrush brush(TranslateColor(GetBackColor()));pdc->FillRect(rcBounds, &brush);pdc->SetBkMode(TRANSPARENT);pdc->SetTextColor(TranslateColor(GetForeColor()));  8.增加属性页。在  BEGIN_PROPPAGEIDS(CClockCtrl, 2)此时数目也得改成相应的数目PROPPAGEID(CClockPropPage::guid)PROPPAGEID(CLSID_CColorPropPage)  END_PROPPAGEIDS(CClockCtrl)  OK~  9.增加自定义属性:ClassWizard->AutoMation->Add Property加上一个变量m_interva......

阅读全文(2694) | 评论:0

第17课 进程间通信(2007-05-01 15:39:00)

摘要:有四种方法1.剪贴板  a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。  b.具体代码:    发送端代码:if(OpenClipboard()){  CString str;  HANDLE hClip;  char *pBuf;  EmptyClipboard();  GetDlgItemText(IDC_EDIT_SEND,str);  hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);  pBuf=(char*)GlobalLock(hClip);将句柄转换为指针!  strcpy(pBuf,str);  GlobalUnlock(hClip);  SetClipboardData(CF_TEXT,hClip);  CloseClipboard();}     接收端代码:if(OpenClipboard()){  if(IsClipboardFormatAvailable(CF_TEXT))  {   HANDLE hClip;   char *pBuf;   hClip=GetClipboardData(CF_TEXT);   pBuf=(char*)GlobalLock(hClip);   GlobalUnlock(hClip);   SetDlgItemText(IDC_EDIT_RECV,pBuf);   CloseClipboard();  }}2.匿名管道:只能在父子进程之间进行通信  a.先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单  ......

阅读全文(2138) | 评论:0

第16课 (2007-05-01 15:39:00)

摘要: 1.事件对象:来实现线程的同步。与互斥对象一样均属于内核对象。            当人工重置有信号时,所有线程均得到信号,所以不能设为人工重置。代码就不贴了。            通过创建匿名的事件对象,也可以让一个程序只能运行一个实例。  2.关键代码段实现线程的同步:类似公用电话亭,只有当电话亭里面没人了,其它人才可以再进去打电话。用了4个函数,这种方法比较简单!但缺点是如果使用了多少关键代码码,容易赞成线程的死锁3.线程死锁,用关键代码示例,用了两个临界区对象,实战中要注意避免这种错误!4.使用异步套接字编写网络聊天室  1)加载套接字库,进行版本协商,包含头文件,链接库文件,这次请示的是2.2版本!  2)在类CChatDlg中增加一个成员变量m_socket,在析构函数中释放这个变量  3)利用WSASocket()创建套接字(数据报类型的UDP型的)  4)然后调用WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ)为网络事件定义消息!此时如果发生FD_READ消息,系统会发送UM_SOCK消息给应用程序!程序并不会阻塞在这儿了!  以上是在BOOL CChatDlg::OnInitDialog()完成  5)然后完成消息响应!  头文件中:#define UM_SOCK  WM_USER+1afx_msg void OnSock(WPARAM,LPARAM);   源文件中:    ON_MESSAGE(UM_SOCK,OnSock)    实现消息响应函数:void CChatDlg::OnSock(WPARAM wParam,LPARAM lParam){switch(LOWORD(lP......

阅读全文(2150) | 评论:0

第15课多线程与网络编程(2007-05-01 15:39:00)

摘要:1.多线程介绍,略2.一个简单的多线程程序MSND中参数[in]和[out]的含义要注意#include <windows.h>#include <iostream.h> DWORD WINAPI Fun1Proc(  LPVOID lpParameter   // thread data); DWORD WINAPI Fun2Proc(  LPVOID lpParameter   // thread data);int index=0;int tickets=100;HANDLE hMutex;互斥对象的句柄void main(){HANDLE hThread1;HANDLE hThread2;hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);创建线程1hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);创建线程2CloseHandle(hThread1);关闭线程的句柄,为什么要关闭?它将线程的使用计数减1CloseHandle(hThread2);这样当线程结束时,线程内核对象被释放,否则只有当进程结束,才释放线程的内核对象/*while(index++<1000)  cout<<"main thread is running"<<endl;*///hMutex=CreateMutex(NULL,TRUE,NULL);将第二个参数设为true后,互斥对象的计数加1hMutex=CreateMutex(NULL,TRUE,"tickets");此段代码可以让系统只一份实例在运行!if(hMutex){  if(ERROR_ALREADY_EXISTS==GetLastError())  {   cout<<"only instance can run!"<<endl;   return;  }}WaitForSingleObject(hMutex,INFINITE);此代码也将互斥对象......

阅读全文(2254) | 评论:0

第14课 网络编程(2007-05-01 15:38:00)

摘要:1.TCP流式套接字的编程步骤在使用之前须链接库函数:工程->设置->Link->输入ws2_32.lib,OK!服务器端程序:1、加载套接字库2、创建套接字(socket)。 3、将套接字绑定到一个本地地址和端口上(bind)。4、将套接字设为监听模式,准备接收客户请求(listen)。5、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。6、用返回的套接字和客户端进行通信(send/recv)。7、返回,等待另一客户请求。8、关闭套接字。客户端程序:1、加载套接字库2、创建套接字(socket)。 3、向服务器发出连接请求(connect)。4、和服务器端进行通信(send/recv)。5、关闭套接字。服务器端代码如下:#include <Winsock2.h>//加裁头文件#include <stdio.h>//加载标准输入输出头文件 void main(){WORD wVersionRequested;//版本号WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );//1.1版本的套接字err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {  return;}//加载套接字库,加裁失败则返回 if ( LOBYTE( wsaData.wVersion ) != 1 ||        HIBYTE( wsaData.wVersion ) != 1 ) {  WSACleanup( );  return; }//如果不是1.1的则退出SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//创建套接字(socket)。 SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//转换Unsigned short为网络字节序的格式addrSrv.sin_family=A......

阅读全文(4851) | 评论:0

第13课 文档与串行化(2007-05-01 15:38:00)

摘要:1.CArchive在菜单打开保存时的代码CFile file("1.txt",CFile::modeCreate | CFile::modeWrite);CArchive ar(&file,CArchive::store);int i=4;char ch='a';float f=1.3f;CString str("http://www.sunxin.org");ar<<i<<ch<<f<<str;以上是保存,打开略2.文档-视类结构简介   OnNewDocument在程序启动时被调用,此时可设置文档标题,也可以在String Table的IDR_MAINFRAME的第二个"\"后改变文档的标题。须了解的7个字符串的用途,见PPT。   在WinAPP的InitInstance()中完成DOC,View,MainFrame的归一。   当点击系统的打开和新建菜单时,有一系列的步骤,孙鑫老师给我们跟踪了代码的调用过程,此段跟踪我们略过。但我们要牢记住:CWinAPP负责管理文档管理器,文档管理器有一个指针链表,且来保存文档模板的指针,文档模板指针管理三个类DOC,VIEW,MAINFRAME,使其为某文件对象服务。3.利用CArchive来保存一个类的对象,此类必须支持串行化,需要5个步骤。  a.让类从CObject派生;  b.覆盖Serialize()函数,在其中完成保存和读取功能;  c.在.h中加入 DECLARE_SERIAL(CGraph);  d.在。cpp中加入IMPLEMENT_SERIAL(CGraph, CObject, 1 );  e.定义一个不带参数的构造函数。保存绘画数据到文件的简单过程  a.在CGraph中增加一个画图的成员函数,其实不增加也行。可以在View中完成相应功能。  b.增加四个画图菜单,菜单可以从11课的代码中拷贝。  c.在View中增加LButtonDown和UP的响应,在UP中画图,在DOWN中保存点  d.利用CObAr......

阅读全文(2267) | 评论:0

第12课 文件操作(2007-05-01 15:38:00)

摘要:1.常量指针与指针常量的区分  char ch[5]="lisi";  const char *pStr=ch;//const在*之前,表明指针指向的内容为常量,即为常量指针  char * const pStr=ch;//const在*之后,表明指针的地址不能改变,即为指针常量  明白?2.对文件读写的三种方法  1.C中    FILE *pFile=fopen("1.txt","w");fwrite("http://www.sunxin.org",1,strlen("http://www.sunxin.org"),pFile);//fseek(pFile,0,SEEK_SET);//fwrite("ftp:",1,strlen("ftp:"),pFile);//fwrite("http://www.sunxin.org",1,strlen("http://www.sunxin.org"),pFile);fclose(pFile);*///fflush(pFile);  2.C++中/* ofstream ofs("4.txt");ofs.write("http://www.sunxin.org",strlen("http://www.sunxin.org"));ofs.close();*/         要包括头文件 "fstream.h"  3.MFC中 用CFile类,哈哈!简单好用CFileDialog fileDlg(FALSE);fileDlg.m_ofn.lpstrTitle="我的文件保存对话框";fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0All Files(*.*)\0*.*\0\0";fileDlg.m_ofn.lpstrDefExt="txt";if(IDOK==fileDlg.DoModal()){  CFile file(fileDlg.GetFileName(),CFile::modeCreat......

阅读全文(2300) | 评论:0

第11课(2007-05-01 15:37:00)

摘要:1.创建4个菜单,为其添加消息响应,用成员变量保存绘画类型。添加LButtonDown和Up消息。2.当窗口重绘时,如果想再显示原先画的数据,则需要保存数据。为此创建一个新类来记录绘画类型和两个点。class CGraph  {public:CPoint m_ptOrigin;//起点CPoint m_ptEnd;//终点UINT m_nDrawType;//绘画类型CGraph();CGraph(UINT m_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd);//此为构造函数。virtual ~CGraph(); };   然后在void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)中加入如下代码//CGraph graph(m_nDrawType,m_ptOrigin,point);//不能用局部变量//m_ptrArray.Add(&graph);//加入这种指针数组中/* OnPrepareDC(&dc);//这个函数中可以重新设置窗口原点,对于滚动条中,保存数据前要调用此函数dc.DPtoLP(&m_ptOrigin);//将设备坐标转换为逻辑坐标dc.DPtoLP(&point);//CGraph *pGraph=new CGraph(m_nDrawType,m_ptOrigin,point);//在堆中创建新的对象m_ptrArray.Add(pGraph);*///加入到指针数组中在GraphicView.h中有如下代码CPtrArray m_ptrArray;   在OnDraw中重画时调出数据for(int i=0;i<m_ptrArray.GetSize();i++)3.在CView::OnPaint()调用了OnDraw(),但在void CGraphicView::OnPaint()中MFC的Wizard没有调用OnDraw(),要注意这个区别。如果你此时想调用,必须手动添加代码。 OnDraw(&dc);4.让窗口具有滚动条的功能。   第1.将CGraphicView的头文件中的CView全部替换成CSrollVi......

阅读全文(2331) | 评论:0