VC开发以及外挂制作总结.docx

上传人:b****5 文档编号:12542318 上传时间:2023-04-20 格式:DOCX 页数:24 大小:25.49KB
下载 相关 举报
VC开发以及外挂制作总结.docx_第1页
第1页 / 共24页
VC开发以及外挂制作总结.docx_第2页
第2页 / 共24页
VC开发以及外挂制作总结.docx_第3页
第3页 / 共24页
VC开发以及外挂制作总结.docx_第4页
第4页 / 共24页
VC开发以及外挂制作总结.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

VC开发以及外挂制作总结.docx

《VC开发以及外挂制作总结.docx》由会员分享,可在线阅读,更多相关《VC开发以及外挂制作总结.docx(24页珍藏版)》请在冰豆网上搜索。

VC开发以及外挂制作总结.docx

VC开发以及外挂制作总结

1.注册dll

regsvr32JpgShowCtl.ocx

2.如果调用了AfxInitOle,那么就不用调用CoInitialize

因为AfxInitOle已经调用过了

而调用CoInitialize需要最后时候调用CoUnInitialize

与AfxOleInit()对应的是,AfxOleTerm()。

AfxOleInit()和AfxOleTerm()其实也是需要成对的,但是,在你的程序中,AfxOleTerm()可以不出现,这是因为,MFC已经帮你做好了(有兴趣的话,你可以仔细研究一下CWinThread:

:

m_lpfnOleTermOrFreeLib,而CWinApp是从CWinThread继承的)。

3.HWNDoldHWnd=NULL;

EnumWindows(EnumWndProc,(LPARAM)&oldHWnd);//枚举所有运行的窗口

if(oldHWnd!

=NULL)

{

:

:

ShowWindow(oldHWnd,SW_SHOWMAXIMIZED);//激活找到的前一个程序

:

:

SetForegroundWindow(oldHWnd);//把它设为前景窗口

returnFALSE;//退出本次运行

}

CStringg_szPropName="GPSWEBVER";

HANDLEg_hValue=(HANDLE)1;

4.添加一个枚举窗口的函数

BOOLCALLBACKEnumWndProc(HWNDhwnd,LPARAMlParam)

{

HANDLEh=GetProp(hwnd,g_szPropName);

if(h==g_hValue)

{

*(HWND*)lParam=hwnd;

returnfalse;

}

returntrue;

}

GetVersionEx

在一个OSVERSIONINFO结构中载入与平台和操作系统有关的版本信息

 

5.关于htmlView使用心得

首先定义一个子类例如CHtmlCtrl继承CHtmlView

然后实现虚函数Create

这个Create需要实现以下代码

m_pCreateContext=pContext;

if(!

CView:

:

Create(lpszClassName,lpszWindowName,

dwStyle,rect,pParentWnd,nID,pContext))

{

returnFALSE;

}

RECTrectClient;

GetClientRect(&rectClient);

//createthecontrolwindow

//AFX_IDW_PANE_FIRSTisasafebutarbitraryID

if(!

m_wndBrowser.CreateControl(CLSID_WebBrowser,lpszWindowName,

WS_VISIBLE|WS_CHILD,rectClient,this,AFX_IDW_PANE_FIRST))

{

DestroyWindow();

returnFALSE;

}

LPUNKNOWNlpUnk=m_wndBrowser.GetControlUnknown();

HRESULThr=lpUnk->QueryInterface(IID_IWebBrowser2,(void**)&m_pBrowserApp);

if(!

SUCCEEDED(hr))

{

m_pBrowserApp=NULL;

m_wndBrowser.DestroyWindow();

DestroyWindow();

returnFALSE;

}

returnTRUE;

这样就可以通过IDispatch接口响应到网页的一些事件,包括点击移动以及js事件。

6.

用CreateDC,getDC等建立了DC后,在不再使用时应该用

ReleaseDC释放他们所建立的DC,而用CreateCompatibleDC建立的DC应该用DeleteDC释放

7.CBitmapHBITMAP相互转化

CBitmap*pBitmap=newCBitmap

这个时候只有CBitmap的空间,但是没有图像

需要pBitmap->Attach(hBitmap)

来获得图像

而CDC获取图像的方式是CDC.SelectObject(hNewBitmap)

同时返回里面的hOldBitmap

pBitmap使用完以后需要DeleteObject

这样就释放掉与其相关的资源,而且可以Attach新的资源。

而deletepBitmap则不会释放资源,只会讲自己CBitmap对象释放掉。

8.回调函数的使用

一般来说回调函数的应用的一种情况

voidfun1()

{

许多代码1

logic1();

许多代码2

}

voidfun2()

{

许多代码1

logic2()

许多代码2

}

fun1和fun2功能上基本一致,但是有很少部分逻辑有点区别。

而许多代码2和许多代码1不大容易变成函数。

这个时候就需要根据外面的调用把logic1和logic2当做参数传进来,在适当的时候调用

fun(logicfun&logic)

{

许多代码1

logic

许多代码2

}

这样就把函数内部的逻辑变到了参数上面去。

9.Invalidate()--RedrawWindow()--UpdateWindow()三个函数有什么异同?

Invalidate()是强制系统进行重画,但是不一定就马上进行重画。

因为Invalidate()只是通知系统,此时的窗口已经变为无效。

强制系统调用WM_PAINT,而这个消息只是Post就是将该消息放入消息队列。

当执行到WM_PAINT消息时才会对敞口进行重绘。

UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。

RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。

声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。

 

//

CArray

10.

在使用一个数组之前,先用SetSize函数建立数组的大小,并为数组分配内存。

如果应用程序没有使用SetSize函数,则向数组中增加元素会使它被频繁地再分配和拷贝。

频繁再分配和拷贝的效率很低,并且可能使内存变得很零碎。

指针数组不能被串行化。

当一个指针数组被删除时,或当其元素被删掉时,只删掉指针,而这些指针所引用的实体不被删除。

 

11.下载文件时候的动画

HWNDm_hAnimationCtrl;

HINSTANCEm_hInstance,m_avi;

//TODO:

Addextrainitializationhere

if((m_avi=LoadLibrary("Shell32.dll"))==NULL)

{

MessageBox("Unabletoloadlibrary.","ANI",0);

}

else

{

//Libraryloadednowcreatetheanimationcontrol

m_hAnimationCtrl=CreateWindowEx(0,//Style

ANIMATE_CLASS,//ClassName

NULL,//Windowname

WS_CHILD|WS_VISIBLE|//WindowStyle

ACS_TRANSPARENT|ACS_CENTER,

0,//Left

0,//Top

360,//Right

60,//Bottom

m_hWnd,//Handleofparent

NULL,//Menu

m_avi,//hInstance

NULL);//Userdefinedstyle

//ControlcreatedNowopentheaviresource

if(:

:

SendMessage(m_hAnimationCtrl,ACM_OPEN,(WPARAM)m_avi,(LPARAM)161)==NULL)

MessageBox("CannotLoadtheaviresource","ANI",0);

//play

:

:

SendMessage(m_hAnimationCtrl,ACM_PLAY,(WPARAM)-1,MAKELONG(0,-1));

//STOP

:

:

SendMessage(m_hAnimationCtrl,ACM_STOP,(WPARAM)-1,MAKELONG(0,-1));

 

//获取按钮,给按钮发送消息

CWnd*pButton1=GetDlgItem(IDC_BUTTON1);

if(pButton1)

{

:

:

SendMessage(pButton1->m_hWnd,BM_CLICK,0,0);

}

给菜单项发送消息

:

:

SendMessage(AfxGetMains");GetSafeHwnd(),WM_COMMAND,ID_TEST1,NULL);

设置状态栏第一个地方的文字

m_wndStatusBar.SetPaneText(0,"helloworld");

 

12.在MainFrame框架下有个消息循环,底层的实现是这样的。

Becausethereturnvaluecanbenonzero,zero,or-1,avoidcodelikethis:

while(GetMessage(lpMsg,hWnd,0,0))...

Thepossibilityofa-1returnvaluemeansthatsuchcodecanleadtofatalapplicationerrors.Instead,usecodelikethis:

BOOLbRet;

while((bRet=GetMessage(&msg,hWnd,0,0))!

=0)

{

if(bRet==-1)

{

//handletheerrorandpossiblyexit

}

else

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

Anapplicationtypicallyusesthereturnvaluetodeterminewhethertoendthemainmessageloopandexittheprogram.

如果点击菜单或者按钮就会有消息进入这个消息循环,从而被DispatchMessage分发到相应的处理过程去处理。

如果发送WM_QUIT消息,就会返回-1,从而整个驱动的核心被停止。

但是如果你在一个消息处理的事件中加入循环,那么系统就不会再响应其他消息,直到你的循环结束。

如果你想让系统响应其他消息,那么你的循环事件必须做成多线程程序。

多线程MFC下有两种方式一个是工作者线程一个是用户界面线程。

工作者线程不会响应消息,一般是做后台工作。

用户界面线程可以响应消息。

13.如何等待线程退出,然后主线程再退出

比如主线程有10个子线程,

当主线程退出前要等待子线程退出。

但是这个时候子线程可能在完成一些工作,比如写文件等,如果强行中止会影响结果。

一个方式是

循环等待所有线程退出

WaitForSingleObject(Thread[i]->m_hThread,TIMEOUT);//这里可以考虑使用

INFINITE

GetExitCodeThread(Thread[i]->m_hThread,&dwExitCode);

if(dwExitCode==STILL_ACTIVE)

{

TerminateThread(Thread[i]->m_hThread,dwExitCode);

}

如果退出码不对,那么需要强制退出。

也可以把句柄放到数组里面,同时等待退出

WaitForMultipleObjects(10,handle,TRUE,10000);

14.比如带界面的程序最小化,能够把堆中分配的内存释放掉。

15.Warning:

constructingCOleException,scode=DISP_E_MEMBERNOTFOUND($80020003).

发现这个错误一般都是继承htmlView的时候OnSize没有处理好

voidCGpsSCView:

:

OnSize(UINTnType,intcx,intcy)

{

CHtmlView:

:

OnSize(nType,cx,cy);

if(:

:

IsWindow(m_hWnd))

{

CRectrect;GetClientRect(rect);//就这一句与CHtmlView的不同

:

:

AdjustWindowRectEx(rect,GetStyle(),FALSE,WS_EX_CLIENTEDGE);

SetWindowPos(NULL,rect.left,rect.top,rect.Width(),rect.Height(),SWP_NOACTIVATE|SWP_NOZORDER);

}

}

 

16.如果使用MFC扩展库来做dll,如果在dll中需要使用dll的资源,那么如果就需要使用

GetModuleHandle("**.dll")来获取dll句柄。

如果需要使用主程序的资源,**.dll就替换为空

注意代码中,如果都使用IDB_BITMAP1,需要将主程序的IDB_BITMAP1定义为和dll一样的值。

否则就会载入失败。

17.使用CreateFile来追加文件内容。

m_file=CreateFile("c:

\\test.txt",

GENERIC_WRITE|SYNCHRONIZE,

FILE_SHARE_WRITE|FILE_SHARE_READ,

NULL,

OPEN_ALWAYS,

FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,

NULL);

SetFilePointer(m_file,0,NULL,FILE_END);

DWORDnCOunt=0;

WriteFile(m_file,"helloworld",strlen("helloworld"),&nCOunt,NULL);

CloseHandle(m_file);

18.

VC6.0设置动态链接库工程生成的lib文件的位置

2011-06-2211:

37

在"Projet"->"Settings..."的"Link"选项卡中

"Outputfilename"中设置dll的输出路径

Projectoptions:

中可以看到刚刚设置生成的DLL路径,

紧跟着就是LIB文件的路径,默认应该是DEBUG或者release的目录下,

这里需要手动修改LIB路径到你所需要的设置生成相应lib文件的所在路径,下面一句设置是Release模式下路径:

/out:

"../UltrasoundWorkStation/PatientDBManage.dll"

/implib:

"../UltrasoundWorkStation/PatientDBManage.lib"

下面是DEBUG模式下默认路径,这里未作修改。

/out:

"Debug/PatientDBManage.dll"

/implib:

"Debug/PatientDBManage.lib"/pdbtype:

sept(多了一个这个)

根据需要修改之即可。

注意:

这里/implib:

"../UltrasoundWorkStation/PatientDBManage.lib"表示LIB生成路径为:

当前DLL工程的上一级目录下的UltrasoundWorkStation文件夹位置下

 

19.

加载DLL的方法主要有两种:

一种是隐式链接,另外一种是动态加载。

隐式链接会把DLL中所有标志为_declspec(dllexport)的函数都加载,如果有多个DLL加载时,可能会影响到程序执行的效率。

而用动态加载DLL的方式则可以根据需要去加载用到的函数。

动态加载DLL的方法:

1.生成dll过程:

把生成的.DLL文件复制到测试工程DLLTest目录下。

这里假设该.DLL文件为add.dll,主要代码是:

_declspec(dllexport)intadd(intx,inty)

{

returnx+y;

}

2.使用1生成的dll:

在DLLTest工程中添加DllTest.cpp文件.

首先使用LoadLibrary("add.dll")加载add.dll文件:

HMODULEhmod=LoadLibrary("add.dll");

然后定义一个函数指针的类型:

typedefint(*AddAddr)(intx,inty);

注意,这里的参数与返回类型务必与add.dll文件中函数add的声明一样。

接着:

AddAddrAdd=(AddAddr)GetProcAddress(hmod,"add");

如果Add值为空,则获取函数的地址失败!

if(!

Add)

{

printf("获取函数地址失败!

");

return;

}

最后,可以测试一下:

printf("testadd():

1+2=%d",add(1,2));

运行结果一看,会出现“获取函数地址失败!

”。

为什么会这样?

打开命令行,用cd命令到add.dll工程目录的debug目录下,然后使用命令:

dumpbin-exportsadd.dll

则会看到add.dll文件中的add函数的名称为“?

add@@YAHHH@Z”,而不是函数名add,这是C++编译器的命名改编机制。

修改原来的代码:

AddAddrAdd=(AddAddr)GetProcAddress(hmod,"?

add@@YAHHH@Z");

这时运行就成功了。

但如果按这样去动态加载DLL,那每次获取函数地址都要使用dumpbin命令去获取,则会很麻烦。

那怎样可以直接使用add而不是?

add@@YAHHH@Z这个长长的字符串呢,修改add.dll的add函数,在函数前加上extern"C",再编译add.dll文件所在的工程,复制新生成的add.dll覆盖DLLTest工程目录下的add.dll,原来的代码获取函数地址时使用add,结果运行就成功了。

而再使用dumpbin-exportsadd.dll命令,显示add.dll的中的add函数的名称变成了add.

20

一个函数将CPtrList里所有记录读出来:

POSITIONpos=apStr.GetHeadPosition();

while(pos!

=NULL)

{

str=apStr.GetNext(pos);

//这里,你就可以使用str了

}

21.

OpenCV

cvReleaseImage属于cxcore.lib

#pragmacomment(lib,"cxcore.lib")

cvWaitKey

cvShowImage

cvMoveWindow

cvNameWindow

cvLoadImage

都在highgui.lib

22.让console程序不显示控制台

在默认情况下链接器看到/subsystem下是windows选项的时候,它会自动寻找winmain或者wwinmain

但我们强制指定入口地址,这样运行程序的时候默认的console窗口就会隐藏!

上面是在代码中使用#pragma指令来设置,还有一种就是直接在开发环境的

project->setting->link->projectoption中手工改动!

写了这么多,自己都有点感觉乱,没有办法,以前没写过什么文章,所以措辞可能不太好,希望大家见谅。

1:

如果console程序已经写好了,不能改了,也可以。

写一个API程序,不要画窗口,然后用CreateProcess调用写好的console程序,把属性设成SW_HIDE即可。

2:

不能用控制台来写(CONSLOE),要用WINMAIN做入口就可以了,不画窗口,别人就都看不见了.你只用想想办法把你的进程在任务栏里面隐藏住就可以.

3:

如果是console程序,用API函数GetStdHandle()获得控制台程序的窗口句柄,然后在隐藏窗口

4:

//这一句隐藏控制台

#pragmacomment(linker,"/subsystem:

\"windows\"/entry:

\"mainCRTStartup\"")

23.console接收输入,即使console在后台

while

(1){

intkey=cvWaitKey(10);

if(key==27)break;

if(key==-1)continue;

printf("%c",key);

}

 

24.创建弹出菜单并响应消息

CMenumenu;

menu.CreatePopupMenu();

ClientToScreen(&point);

menu.AppendMenu(MF_STRING,WM_DESTROY,"Exit");

menu.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);

menu.DestroyMenu();

需要使用ON_COMMAND来响应消息

命令可以在resource.h中定义例如#defineID_ALERTWM_USER+1000

25.通过发消息在Notepad中写字

HWNDm_LocalWnd=:

:

FindWindow("Notepad",NULL);

HWNDm_ChildWnd=:

:

FindWindowEx(m_LocalWnd,NULL,"Edit","");

:

:

PostMessage(m_ChildWnd,WM_CHAR,'A',0);

:

:

PostMessage(m_ChildWnd,W

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 幼儿读物

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1