读博士期间自己总结的VC笔记

2024-06-30

读博士期间自己总结的VC笔记

读博士期间自己总结的VC笔记 篇1

第一课

1.MFC生成的C++源文件中都有StdAfx.h,此文件包含了常用的AFX函数的声明,其中有afxwin.h,此文件包含了CRECT,CPoint,CWnd等许多类及其方法的声明。2.Project->Setting->Debug可以加入命令行参数。

3.在SDK中要加入“windows.h”和stdio.h。因为LoadCursor,MessageBox等函数的声明在这个文件中。

4.创建一个完整的窗口的四个步骤SDK,1设计窗口类,2注册窗口类,3创建窗口,4显示窗口

5.函数名可以代表函数代码的首地址,即可作为函数指针。

6.要查看VC数据类型,可以在MSDN中输入“BOOL”然后选择“DATA TYPE”。7.atof将字符串转化为float,atoi将字符串转化为int型。8.所有从CWnd类派生的类都有m_hWnd句柄。

9.变量的生命周期:可以认为出了包含它的大括号,这个变量的生命周期结束。所以全局变量的声明位于所有大括号之外。但是用new声明的变量和用static声明的变量除外。

10.SDK示范程序,见下面。

11.sprintf格式化字符,其头文件为stdio.h,在MFC中格式化字符用CString.Format 12.GetDC()与ReleaseDC()要成对使用,否则会内存泄漏。同样,BeginPaint()与EndPaint()。

13.GetStockObject()得到画笔、画刷、字体、调色板的句柄,使用时必须用类型转换。

14.什么时候用NULL,什么时候用0.答,对指针赋值时用NULL,对变量赋值时用0.15.什么是野指针?答:将指针指向的变量的内存释放后,此指针即变成野指针!如何避免野指针?答:将此指针指向NULL即可。p=NULL;16.SDK代码流程:

#include “windows.h”//包含头文件LoadCursor,TextOut等函数 #include “stdio.h”//包含sprintf,printf等函数 LRESULT CALLBACK MyProc(...);//声明回调函数 int WINAPI WinMain(){ WNDCLASS wndcls;//设计窗口类

wndcls.hcursor=LoadCursor();//初始化....RegisterClass(&wndcls);//注册窗口类 hwnd=CreateWindow(...);//创建窗口 ShowWindow(..);//显示窗口 UpdateWindow(..);MSG msg;//定义消息结构体

while(GetMessage(...))//消息循环 {...} return 0;}

LRESULT CALLBACK MyProc(...)//实现回调函数 { switch(uMsg){ case WM_CHAR: break;...} }

第2课

1.定义结构体和类时别忘记在最后加入“;”号!例如Class Point{int x;int y;};2.#include 与#include “xxx.h”的区别:<>不查找运行时目录,“"查找运行时目录!

3.类的定义中,如果未指明成员类型,则缺省为private.而结构体中则缺省为public.4.引用:引用经常用在函数的传参上。另外数值交换函数也经常用引用。例 change(int &x,int &y){int temp;temp=x;x=y;y=x}调用时即可以用 int a=3;int b=4;change(a,b);一般不用指针来作为参数进行数值交换。因为会引起歧义。

5.通常将类的定义放.h文件,而将其实现放在cpp文件中,别忘记了在cpp文件中#include ”xxx.h“ 6.如何防止类的重复定义? 用#inndef Point_H_H #define Point_H_H class Point{};#endif来防止

7.源文件cpp文件单独编译成obj文件。最后由链接器将与将要使用到的C++标准库类链接成exe文件,头文件不参加编译。所以在cpp文件中别忘记了加入#include ”xxx.h“ 8.函数的覆盖,在子类中重写父类的函数,此时采用早期绑定的方法。如果加入了virtual,则将采用迟绑定的技术,在运行时根据对象的类型确定调用哪一个函数。此迟绑定技术是MFC的类的继承的精髓。

9.强制类型转换。如果CFish从CAnimal派生而来。则可以将鱼的对象转换为CAnimal的对象,而反之则不行。从现实中理解也是正常的,鱼可以是动物,而动物却不是鱼。再如int可以强制转换成char型。而反之则出错。

第3课

1.在main或WinMain之前,全局变量已经被分配内存并初始化了。2.在MFC中在WinMain之前有个theApp全局变量先被构造并被初始化,而由于子类构造函数执行前,其父类的构造函数先被执行,所以CTestApp的父类CWinAPP的构造函数先执行。产生了theApp对象后,在WinMain()中的指针*pThread和*pApp就有了内容。3.MFC大致流程:

CTestApp theApp;//构造全局对象 WinMain(){ AfxWinMain();//调用下面的函数 } AfxWinMain(){ pThread->Initinstance();//初始化工作和注册窗口类,窗口显示和更新 pThread->Run();//消息循环 } 而在BOOL CTestApp::InitInstance()中的代码 CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CTestDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CTestView));AddDocTemplate(pDocTemplate);完成了将这三个类关联起来的工作。

4.如何在单文档文件中显示一个CButton的对象?

在CMainFrame::OnCreate()中定义一个CButton的对象btn;然后调用btn.Create(”维新“,WS_DISABLED |WS_CHILD | WS_VISIBLE | BS_AUTO3STATE, CRect(0,0,300,100),/*GetParent(),*/this,123);注意点:

(1).此处btn不能是局部变量,否则它的生命周期太短,将不能显示。(2).在create函数的第二个参数中加入WS_VISIBLE 参数才行。否则必须调用ShowWindow 也可以在view的OnCreate消息响应函数中加入(3).CButton类的定义头文件在afxwin.h中,而stdafx.h包含了afxwin.h,所以可以直接使用。因为MFC中的每一个类中都有#include ”stdafx.h“的声明。

第4课

1.在单文档中view挡在MainFrame的前面。此时如果编写针对MainFrame的mouseClick事件,将不会有反应。

2.消息响应会在3处修改代码,1处是在头文件中,//{{AFX_MSG(CDrawView)afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);//}}AFX_MSG DECLARE_MESSAGE_MAP()另一处是cpp文件的begin MessageMap和End MessageMap之间,BEGIN_MESSAGE_MAP(CDrawView, CView)//{{AFX_MSG_MAP(CDrawView)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()//}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()最后是要有函数实现的代码。

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point){ // TOD Add your message handler code here and/or call default m_ptOrigin=m_ptOld=point;m_bDraw=TRUE;CView::OnLButtonDown(nFlags, point);} 3.画线:定义一个成员变量保存mouseDown的点m_Point 1)API函数方法画线用HDC 2)用CDC类成员函数画线。此时别忘记ReleaseDC 3)用CClientDC 4)用CWindowDC,用它甚至可以整个屏幕区域画线。下面是上面4种方法的代码 /*HDC hdc;hdc=::GetDC(m_hWnd);MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);LineTo(hdc,point.x,point.y);::ReleaseDC(m_hWnd,hdc);必须成对使用。*/ /*CDC *pDC=GetDC();pDC->MoveTo(m_ptOrigin);pDC->LineTo(point);ReleaseDC(pDC);必须成对使用。*/

//CClientDC dc(this);/*CClientDC dc(GetParent());dc.MoveTo(m_ptOrigin);dc.LineTo(point);此处不需要ReleaseDC,因为CClientDC会自动释放DC*/

//CWindowDC dc(this);//CWindowDC dc(GetParent());/*CWindowDC dc(GetDesktopWindow());//此时可以在整个屏幕上画线。dc.MoveTo(m_ptOrigin);dc.LineTo(point);*/ /*CPen pen(PS_DOT,1,RGB(0,255,0));CClientDC dc(this);CPen *pOldPen=dc.SelectObject(&pen);dc.MoveTo(m_ptOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);*/ 5)用Bitmap填充所画的矩形。CBitmap bitmap;bitmap.LoadBitmap(IDB_BITMAP1);CBrush brush(&bitmap);CClientDC dc(this);dc.FillRect(CRect(m_ptOrigin,point),&brush);//CBRUSH::FromHandle是静态成员函数,所以可以用下面的方法调用。CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));CBrush *pOldBrush=dc.SelectObject(pBrush);dc.Rectangle(CRect(m_ptOrigin,point));dc.SelectObject(pOldBrush);m_bDraw=FALSE;6)用其它颜色画线 CClientDC dc(this);CPen pen(PS_SOLID,1,RGB(255,0,0));CPen *pOldPen=dc.SelectObject(&pen);//选中红色画笔 if(m_bDraw==TRUE){ dc.SetROP2(R2_BLACK);//设置绘画模式 dc.MoveTo(m_ptOrigin);//dc.LineTo(point);dc.LineTo(m_ptOld);//dc.MoveTo(m_ptOrigin);dc.MoveTo(m_ptOld);dc.LineTo(point);//m_ptOrigin=point;m_ptOld=point;} dc.SelectObject(pOldPen);4.MFC中隐式的包含了windows.h。为什么? 因为在AFXV_W32.h文件中:

// This is a part of the Microsoft Foundation Classes C++ library.// Copyright(C)1992-1998 Microsoft Corporation // All rights reserved.在AFXWIN.h中

// Note: WINDOWS.H already included from AFXV_W32.H 5.如何从句柄获得对象的指针? 答FromHandle 6.类的静态成员函数可以由类名直接调用,也可以由对象调用。可以认为静态成员函数并不属于某个对象,它属于类本身。程序运行伊始,即使没有实例化类的对象,静态成员函数和静态成员变量已然有其内存空间。静态成员函数不能访问非静态成员变量!静态成员变量必须在类的外部初始化。当然如果并不打算用到静态成员变量,此时你可以不初始它。7.理解代码区,数据区,堆,栈!请见下面的简介:

http://amedPipeSrvView::OnPipeCreate(){ // TOD Add your command handler code here hPipe=CreateNamedPipe(”.pipeMyPipe“, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,1,1024,1024,0,NULL);if(INVALID_HANDLE_VALUE==hPipe){ MessageBox(”创建命名管道失败!“);hPipe=NULL;return;} HANDLE hEvent;hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(!hEvent){ MessageBox(”创建事件对象失败!“);CloseHandle(hPipe);hPipe=NULL;return;} OVERLAPPED ovlap;ZeroMemory(&ovlap,sizeof(OVERLAPPED));ovlap.hEvent=hEvent;if(!ConnectNamedPipe(hPipe,&ovlap)){ if(ERROR_IO_PENDING!=GetLastError()){ MessageBox(”等待客户端连接失败!“);CloseHandle(hPipe);CloseHandle(hEvent);hPipe=NULL;return;} } if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE)){ MessageBox(”等待对象失败!“);CloseHandle(hPipe);CloseHandle(hEvent);hPipe=NULL;return;} CloseHandle(hEvent);} void CNamedPipeSrvView::OnPipeRead(){ // TOD Add your command handler code here char buf[100];DWORD dwRead;if(!ReadFile(hPipe,buf,100,&dwRead,NULL)){ MessageBox(”读取数据失败!“);return;} MessageBox(buf);} void CNamedPipeSrvView::OnPipeWrite(){ // TOD Add your command handler code here char buf[]=”http://amedPipeCltView::OnPipeConnect()连接管道 { // TOD Add your command handler code here if(!WaitNamedPipe(“.pipeMyPipe”,NMPWAIT_WAIT_FOREVER)){ MessageBox(“当前没有可利用的命名管道实例!”);return;} hPipe=CreateFile(“.pipeMyPipe”,GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(INVALID_HANDLE_VALUE==hPipe){ MessageBox(“打开命名管道失败!”);hPipe=NULL;return;} } void CNamedPipeCltView::OnPipeRead()读取数据 { // TOD Add your command handler code here char buf[100];DWORD dwRead;if(!ReadFile(hPipe,buf,100,&dwRead,NULL)){ MessageBox(“读取数据失败!”);return;} MessageBox(buf);} void CNamedPipeCltView::OnPipeWrite()写入数据 { // TOD Add your command handler code here char buf[]=“命名管道测试程序”;DWORD dwWrite;if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL)){ MessageBox(“写入数据失败!”);return;} } 4.邮槽,使用时应将消息长度限制在424字节以下,关键函数CreateMailSlot()a.先建一个MailSlotSRV工程,加菜单“接收数据” b.消息响应代码:

void CMailslotSrvView::OnMailslotRecv()菜单“接收数据”的代码 { // TOD Add your command handler code here HANDLE hMailslot;hMailslot=CreateMailslot(“.mailslotMyMailslot”,0, MAILSLOT_WAIT_FOREVER,NULL);if(INVALID_HANDLE_VALUE==hMailslot){ MessageBox(“创建油槽失败!”);return;} char buf[100];DWORD dwRead;if(!ReadFile(hMailslot,buf,100,&dwRead,NULL)){ MessageBox(“读取数据失败!”);CloseHandle(hMailslot);return;} MessageBox(buf);CloseHandle(hMailslot);} c.加工程MailSlotCLT,加菜单“发送数据” d.加消息响应,添加代码,客户端也比较简单。

void CMailslotCltView::OnMailslotSend()菜单“发送数据”的代码 { // TOD Add your command handler code here HANDLE hMailslot;hMailslot=CreateFile(“.mailslotMyMailslot”,GENERIC_WRITE, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(INVALID_HANDLE_VALUE==hMailslot){ MessageBox(“打开油槽失败!”);return;} char buf[]=“http://”;DWORD dwWrite;if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL)){ MessageBox(“写入数据失败!”);CloseHandle(hMailslot);return;} CloseHandle(hMailslot);} 5.以上4种方法各有优缺点:剪贴板比较简单。邮槽是基于广播的,可以一对多发送。但只能一个发送,一个接收,要想同时发送接收,须写两次代码。命名管道和邮槽可以进行网络通信。

第18课 ActiveX编程(下面X均为ActiveX简称)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_interval,类型为short,对应外部变量为Interval。在CClockCtrl中增加OnIntervalChanged方法。添加如下代码: if(m_interval<0 || m_interval>6000){ m_interval=1000;} else { m_interval=m_interval/1000*1000;KillTimer(1);SetTimer(1,m_interval,NULL);BoundPropertyChanged(0x1);} 10.测试:Control->Invoke Methods 11.将时间间隔加到属性页中,在资源视图中加入一文本框和编辑框。为EditBox关联成员变量,加入属性interval。12.增加方法:ClassWizard->AutoMation->Add Method->Hello加入代码 OK!在VB中可以调用此方法!

void CClockCtrl::Hello(){ // TOD Add your dispatch handler code here MessageBox(“Hello world!”);} 13.增加事件:ClassWizard->AutoMation->Add Events->Click 14.增加自定义事件:ClassWizard->AutoMation->Add Events->NewMinute 在新的一分钟到达时发出这个通知,在OnDraw()中写代码: CTime time=CTime::GetCurrentTime();if(0==time.GetSecond()){ FireNewMinute();} 15.让Interval属性具有持久性。在CClockCtrl::DoPropExchange()中调用PX_short()方法,OK!

PX_Short(pPX,“Interval”,m_interval,1000);16.让Property Page和Property属性中的interval保持一致的方法:在OnIntervalChanged()中调用BoundPropertyChanged(0x1);17.希望控件在设计时间内不走动的方法:在OnTimer()中,if(AmbientUserMode())InvalidateControl();巧妙!3.在VC中调用X控件

1.新建ClockTest对话框应用程序 2.点击右键->插入X控件->时钟控件

3.Project->Add Component会生成CClock类。

4.在CCLockTestDlg中增加CClock类的成员变量m_clock,然后可以动态创建一个这样的东东!

5.试验Click(),NewMinute(),SetBkColor(),SetForeColor()方法和属性 6.如何为动态创建的控件做事件响应呢?首先你得知道它的ID号,然后参考非动态的控件事件代码,呵。第19课 DLL编程

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查看它的输入信息,可以看到它加载了dll1.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 extern “C” _declspec(dllexport)#include “Dll1.h” #include #include int _stdcall add(int a,int b){ return a+b;} int _stdcall subtract(int a,int b){ return a-b;} 5.在Dll1中加入类Point它有一个函数output(int a,intb),它的功能是在屏幕上输出x,y值。须包含头文件windows.h和stdio.h.然后在DllTest中加入一个按纽来测试这个函数!此时我们可以dumpbin来查看dll1.dll和dllTest.exe的导出导入情况。注意,也可以只导出类的某个函数。

6.我们希望导出的函数名不被改变,加extern “C”大写的C!即可,#define DLL1_API extern “C” _declspec(dllexport),但它只能导出全局函数,不能导出类的成员函数,并且如果调用约定被改成了别的方式,此时函数名也被改变。所以这种方式不太好。

7.解决之道是用模块定义文件。1.新建dll2.dll工程;

2.加dll2.cpp中写两个函数add和subtract 3.在目录中新建dll2.def文件,增加到工程。4.在dll2.def中加入如下代码: LIBRARY Dll2 EXPORTS add subtract 5.编译后用dumpbin查看函数名是否被改变?

6.测试,我们这次用动态加载的方法来调用dll文件。以前是用隐式链接的方法,嘿嘿。动态加载的好处是需要时再加载,可以提高执行的效率。代码如下: HINSTANCE hInst;hInst=LoadLibrary(“Dll3.dll”);typedef int(/*_stdcall*/ *ADDPROC)(int a,int b);//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,“?add@@YAHHH@Z”);ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));if(!Add){ MessageBox(“获取函数地址失败!”);return;} CString str;str.Format(“5+3=%d”,Add(5,3));MessageBox(str);FreeLibrary(hInst);7.此时你改变调用约定,函数名不会被改变,但如果你加上_stdcall定义函数,调用时也需要加入_stdcall,否则会出错!

8.DllMain()是Dll的入口点,不过不是必须的。但在DllMain中不要做复杂的调用。为什么?因为DllMain加载时,某些核心Dll文件不一定已经被加载。9.创建一个基于MFC的DLL工程,简介。

10.当不使用DLL时,调用FreeLibrary减少DLL的使用计数,释放DLL资源,减少系统负担。明白?

11.上面总结:1.*.def使函数名不改变;

2.定义时为_stdcall,调用时也必须用_stdcall.第20课 钩子与数据库编程

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>>29 & 1)))拦截ALT+F4按键!return 1;else return CallNextHookEx(g_hKeyboard,code,wParam,lParam);*/ if(VK_F2==wParam)按F2时程序可以退出,这是留的后门。否则程序无法关闭,只能用任务管理器来关闭它了。{ ::SendMessage(g_hWnd,WM_CLOSE,0,0);UnhookWindowsHookEx(g_hKeyboard);当程序退出时最好将钩子移除。UnhookWindowsHookEx(g_hMouse);} return 1;} 3.编写一个屏屏蔽所有进程和所有线程的钩子程序。此时这个钩子必须安装在DLL中,然后被某个程序调用才行。1.新建一个DLL工程名为Hook 2.增加Hook.cpp 3.代码如下:

#include 包含头文件

HHOOK g_hMouse=NULL;HHOOK g_hKeyboard=NULL;

#pragma data_seg(“MySec”)新建了一个节,用于将下 面的这个变量设为全局共享。

HWND g_hWnd=NULL;这个变量是全局共享的。#pragma data_seg()

//#pragma comment(linker,“/section:MySec,RWS”)/*HINSTANCE g_hInst;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to the DLL module DWORD fdwReason, // reason for calling function LPVOID lpvReserved // reserved){ g_hInst=hinstDLL;}*/

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_F2==wParam)如果是F2键,则退出。{ SendMessage(g_hWnd,WM_CLOSE,0,0);UnhookWindowsHookEx(g_hMouse);当退出时将钩子卸掉。UnhookWindowsHookEx(g_hKeyboard);} return 1;}

void SetHook(HWND hwnd)此函数设置了钩子。{ g_hWnd=hwnd;注意这种传递调用它的进程的句柄的方法,比较巧妙!

g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle(“Hook”),0);

g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle(“Hook”),0);} Hook.DEF的代码如下: LIBRARY Hook EXPORTS SetHook @2 SEGMENTS MySec READ WRITE SHARED 也可以设置节的属性。

4.新建一个工程调用此钩子函数。工程名为HookTest,基于对话框的。在OnInitDialog()中调用SetHook(),要事先声明_declspec(dllimport)void SetHook(HWND hwnd);然后在Project->Setting->Link->加入..HookDebugHook.lib,并将Hook.Dll拷贝到当前目录。int cxScreen,cyScreen;cxScreen=GetSystemMetrics(SM_CXSCREEN);cyScreen=GetSystemMetrics(SM_CYSCREEN);SetWindowPos(&wndTopMost,0,0,cxScreen,cyScreen,SWP_SHOWWINDOW);将窗口保持在最前面。SetHook(m_hWnd);5.DLL的调试方法,设置断点,然后运行时断点时,step into即可。4.数据库编程

1.ODBC,ADO简介:ADO可以认为是建立在ODBC上的。ADO的三个核心对象 Connection对象

Connection对象表示了到数据库的连接,它管理应用程序和数据库之间的通信。Recordset和Command对象都有一个ActiveConnection属性,该属性用来引用Connection对象。Command对象

Command对象被用来处理重复执行的查询,或处理需要检查在存储过程调用中的输出或返回参数的值的查询。Recordset对象

Recordset对象被用来获取数据。Recordset对象存放查询的结果,这些结果由数据的行(称为记录)和列(称为字段)组成。每一列都存放在Recordset的Fields集合中的一个Field对象中。

2.演示在VB中使用ADO的方法,方法比较简单,使用方便。另外在VB中演示了Connection和Command和Recordset的方法,用这三种方法都可以执行SQL语句。

3.在VC中利用ADO访问数据库。

1.新建一个基于对话框的工程,名为ADO。

2.在对话框中放一ListBox和一个Button控件。

3.在使用时须导入MSADO15.dll,方法是在StdAfx.h中#import “D:Program FilesCommon FilesSystemadomsado15.dll” no_namespace rename(“EOF”,“rsEOF”)至少于将EOF改名为rsEOF,是为了避免与文件中的EOF重名。然后编译程序,将产生的debug目录下的两个文件MSADO15.tlh和MSADO15.tli加到工程中,其目的只是方便我们查看而已。并不是编译需要它。

ADO也是COM组件,须初始化COM库方法是CoInitialize(NULL);使用完后须CoUninitialize();代码如下:

void CAdoDlg::OnBtnQuery(){ // TOD Add your control notification handler code here CoInitialize(NULL);初始化

_ConnectionPtr pConn(__uuidof(Connection));产生connection智能指针 _RecordsetPtr pRst(__uuidof(Recordset));产生recordset智能指针 _CommandPtr pCmd(__uuidof(Command));产生command智能指针

pConn->ConnectionString=“Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=pubs”;数据库信息 pConn->Open(“",”“,”“,adConnectUnspecified);打开数据库 //pRst=pConn->Execute(”select * from authors“,NULL,adCmdText);用记录集查询数据

//pRst->Open(”select * from authors“,_variant_t((IDispatch*)pConn), // adOpenDynamic,adLockOptimistic,adCmdText);pCmd->put_ActiveConnection(_variant_t((IDispatch*)pConn));pCmd->CommandText=”select * from authors“;用这种方法也可以查询数据 pRst=pCmd->Execute(NULL,NULL,adCmdText);while(!pRst->rsEOF)将查询到的数据加到列表框咯。{((CListBox*)GetDlgItem(IDC_LIST1))->AddString((_bstr_t)pRst->GetCollect(”au_lname"));pRst->MoveNext();}

pRst->Close();pConn->Close();pCmd.Release();pRst.Release();pConn.Release();CoUninitialize();} 至此20课笔记全部记完,关于数据库的比较简单些。

上一篇:我的新年愿望班会下一篇:酒店餐厅服务员工作流程