
补充一下另一种方法。
1,在头文件中添加shellapih,或者直接添加如下代码:
#ifndef _INC_SHELLAPI#define _INC_SHELLAPI
//
// Define API decoration for direct importing of DLL references
//
#ifndef WINSHELLAPI
#if !defined(_SHELL32_)
#define WINSHELLAPI DECLSPEC_IMPORT
#else
#define WINSHELLAPI
#endif
#endif // WINSHELLAPI
#ifndef SHSTDAPI
#if !defined(_SHELL32_)
#define SHSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHSTDAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHSTDAPI STDAPI
#define SHSTDAPI_(type) STDAPI_(type)
#endif
#endif // SHSTDAPI
#ifndef SHDOCAPI
#if !defined(_SHDOCVW_)
#define SHDOCAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHDOCAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHDOCAPI STDAPI
#define SHDOCAPI_(type) STDAPI_(type)
#endif
#endif // SHDOCAPI
#if ! (defined(lint) || defined(_lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 ) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push)
#endif
#pragma pack(1)
#else
#pragma pack(1)
#endif
#endif // ! (defined(lint) || defined(_lint) || defined(RC_INVOKED))
#ifdef __cplusplus
extern "C" { / Assume C declarations for C++ /
#endif / __cplusplus /
DECLARE_HANDLE(HDROP);
WINSHELLAPI UINT APIENTRY DragQueryFileA(HDROP,UINT,LPSTR,UINT);
WINSHELLAPI UINT APIENTRY DragQueryFileW(HDROP,UINT,LPWSTR,UINT);
#ifdef UNICODE
#define DragQueryFile DragQueryFileW
#else
#define DragQueryFile DragQueryFileA
#endif // !UNICODE
WINSHELLAPI BOOL APIENTRY DragQueryPoint(HDROP,LPPOINT);
WINSHELLAPI VOID APIENTRY DragFinish(HDROP);
WINSHELLAPI VOID APIENTRY DragAcceptFiles(HWND,BOOL);
#ifdef __cplusplus
}
#endif / __cplusplus /
#if ! (defined(lint) || defined(_lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 ) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(pop)
#else
#pragma pack()
#endif
#else
#pragma pack()
#endif
#endif // ! (defined(lint) || defined(_lint) || defined(RC_INVOKED))
#endif / _INC_SHELLAPI /
2,对话框属性中勾选 接收文件(Accept files)
3,添加消息处理:
case WM_DROPFILES:HDROP hDropInfo = (HDROP) wParam; //从WM_DROPFILES消息中获取所拖放文件的数据结构的指针
DragQueryFile(hDropInfo,0,szFilePath,_MAX_PATH); //获取文件路径
DragFinish(hDropInfo); //拖放结束后,释放内存
SendDlgItemMessage(hWnd,IDC_FILEPATH_EDIT,WM_SETTEXT,MAX_PATH,(LPARAM)szFilePath);
下面是完整代码:
#include <windowsh>#include <shellapih>
#include <commdlgh>
#include "resourceh"
LRESULT CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL OpenFileDlg(HWND);
char szFilePath[MAX_PATH];
HINSTANCE hInst;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
hInst = hInstance;
DialogBox(hInstance, (LPCTSTR)IDD_MAIN_DLG, NULL, (DLGPROC)MainDlgProc);
return 0;
}
LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDC_OPEN_BTN:
if(!OpenFileDlg(hWnd))
return FALSE;
SendDlgItemMessage(hWnd,IDC_FILEPATH_EDIT,WM_SETTEXT,MAX_PATH,(LPARAM)szFilePath);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hWnd, 0);
break;
case WM_DROPFILES:
HDROP hDropInfo = (HDROP) wParam; //从WM_DROPFILES消息中获取所拖放文件的数据结构的指针
DragQueryFile(hDropInfo,0,szFilePath,MAX_PATH); //获取文件路径
DragFinish(hDropInfo); //拖放结束后,释放内存
SendDlgItemMessage(hWnd,IDC_FILEPATH_EDIT,WM_SETTEXT,MAX_PATH,(LPARAM)szFilePath);
return TRUE;
break;
}
return 0;
}
BOOL OpenFileDlg(HWND hwnd)
{
OPENFILENAME ofn;
memset(szFilePath,0,MAX_PATH);
memset(&ofn, 0, sizeof(ofn));
ofnlStructSize =sizeof(ofn);
ofnhwndOwner =hwnd;
ofnhInstance =GetModuleHandle(NULL);
ofnnMaxFile =MAX_PATH;
ofnlpstrInitialDir ="";
ofnlpstrFile =szFilePath;
ofnlpstrTitle ="Open";
ofnFlags =OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofnlpstrFilter ="\0\0";
if(!GetOpenFileName(&ofn))
{
ZeroMemory(&ofn,sizeof(OPENFILENAME)); //释放内存
return FALSE;
}
ZeroMemory(&ofn,sizeof(OPENFILENAME)); //释放内存
return TRUE;
}
首先纠正一下,不是IE浏览器不见了,而是它的快捷方式没有显示在桌面和开始菜单处。
右击桌面空白处,选择“属性”命令,切换到“桌面”选项卡,单击“自定义桌面”按钮,勾选“Internet Explorer”项,然后单击“确定”,IE的图标即可在桌面上显示出来。
当然,也可找到“iexploreexe”程序(在“C:\Program Files\Internet Explorer”目录下),然后创建该程序的桌面快捷方式(右击该程序图标,选择“发送到-桌面快捷方式”),同样可以让IE图标显示在桌面上。
右击任务栏空白处,选择“属性”命令,选择“开始菜单”选项卡,点选“开始菜单”,单击“自定义”,选择“常规”选项卡,在该页面的下方有“在开始菜单上显示”一栏,勾选“Internet”,单击“确定”,IE图标即可在开始菜单上显示出来。
IE实例遍历实现
---- 首先我们来看系统是如何知道当前有多少个IE的实例在运行。
----
我们知道在Windows体系结构下,一个应用程序可以通过 *** 作系统的运行对象表来和这些应用的实例进行交互。但是IE当前的实现机制是不在运行对象表中进行注册,所以需要采用其他的方法。我们知道可以通过ShellWindows集合来代表属于shell的当前打开的窗口的集合,而IE就是属于shell的一个应用程序。
---- 下面我们描述一下用VC实现对当前
IE实例的进行遍历的方法。IShellWindows是关于系统shell的一个接口,我们可以定义一个如下的接口变量:
SHDocVw::IShellWindowsPtr m_spSHWinds;
然后创建变量的实例:
m_spSHWindsCreateInstance
(__uuidof(SHDocVw::ShellWindows));
通过IShellWindows接口的方法GetCount
可以得到当前实例的数目:
long
nCount = m_spSHWinds- >GetCount();
通过IShellWindows接口的方法Item
可以得到每一个实例对象
IDispatchPtr
spDisp;
_variant_t
va(i, VT_I4);
spDisp
= m_spSHWinds->Item(va);
然后我们可以判断实例对象是不是
属于IE浏览器对象,通过下面的语句实现:
SHDocVw::IWebBrowser2Ptr
spBrowser(spDisp);
assert(spBrowser
!= NULL)
----在得到了IE浏览器对象以后,我们可以调用IWebBrowser2Ptr接口的方法来得到当前的文档对象的指针:
MSHTML::IHTMLDocument2Ptr spDoc(spBrowser->GetDocument());
----
然后我们就可以通过这个接口对这个文档对象进行 *** 作,比如通过Gettitle得到文档的标题。
----
我们在浏览网络的时候,一般总会同时开很多IE的实例,如果这些页面都是很好的话,我们可能想保存在硬盘上,这样,我们需要对每一个实例进行保存,而如果我们采用上面的原理,我们可以得到每一个IE的实例及其网页对象的接口,这样就可以通过一个简单的程序来批量的保存当前的所有打开的网页。采用上面介绍的方法实现了对当前IE实例的遍历,但是我们希望得到每一个IE实例所产生的事件,这就需要通过DLL的机制来实现。
---- 3.和IE相绑定的DLL的实现
----
我们介绍一下如何建立和IE进行绑定的DLL的实现的过程。为了和IE的运行实例进行绑定,我们需要建立一个能够和每一个IE实例进行绑定的DLL。IE的启动过程是这样的,当每一个IE的实例启动的时候,它都会在注册表中去寻找这个的一个CLSID,具体的注册表的键位置为:
HKEY_LOCALL_MACHINE\SOFTWARE\Microsoft\Windows
\CurrentVersion\Explorer\Browser Helper Objects
----
当在这个键位置下存在CLSIDs的时候,IE会通过使用CoCreateInstance()方法来创建列在该键位置下的每一个对象的实例。注意对象的CLSIDs必须用子键而非名字值的形式表现,比如{DD41D66E-CE4F-11D2-8DA9-00A0249EABF4}
就是一个有效的子键。我们使用DLL的形式而非EXE的形式的原因是因为DLL和IE实例运行在同一个进程空间里面。每一个这种形式的DLL必须实现接口IObjectWithSite,其中方法SetSite必须被实现。通过这个方法,我们自己的DLL就可以得到一个指向IE
COM对象的IUnknown的指针,实际上通过这个指针我们就可以通过COM对象中的方法QueryInterface来遍历所有可以得到的接口,这是COM的基本的机制。当然我们需要的只是IWebBrowser2这个接口。
----
实际上我们建立的是一个COM对象,DLL只不过是COM对象的一种表现形式。我们建立的COM对象需要建立和实现的方法有:
----1.
IOleObjectWithSite接口的方法SetSite必须实现。实际上IE实例通过这个方法向我们的COM对象传递一个接口的指针。假设我们有一个接口指针的变量,不妨设为:
----CComQIPtr< IWebBrowser2, &IID_IWebBrowser2 >
m_myWebBrowser2;
----
我们就可以在方法SetSite中把这个传进来的接口指针赋给m_myWebBrowser2。
2. 在我们得到了指向IE
COM对象的接口后,我们需要把自己的DLL和IE实例所发生的事件相关连,为了实现这个目的,需要介绍两个接口:
----(1)
IConnectionPointContainer。这里使用这个接口的目的是用来根据它得到的IID来建立和DLL的一个特定的连接。比如我们可以进行如下的定义:
CComQIPtr< IConnectionPointContainer,
&IID_IConnectionPointContainer
>
spCPContainer(m_myWebBrowser2);
----然后,我们需要把所有IE中发生的事件和我们的DLL进行通讯,可以使用
IConnectPoint。
----(2)
IConnectPoint。通过这个接口,客户可以对连接的对象开始或者是终止一个advisory循环。IConnectPoint有两个主要的方法,一个为Advice,另一个为Unadvise。对于我们的应用来说,Advise是用来在每一个IE发生的事件和DLL之间建立一个通道。而Unadvise就是用来终止以前用Advise建立的通知关系。比如我们可以定义IConnectPoint接口如下:
CComPtr< IConnectionPoint > spConnectionPoint;
----
然后,我们要使所有在IE实例中发生的事件和我们的DLL相关,可以使用如下的方法:
hr = spCPContainer->FindConnectionPoint(
DIID_DWebBrowserEvents2, &spConnectionPoint);
----然后我们通过IConnectPoint接口的方法Advice使每当IE有一个新的事件发生的时候,都能够让我们的DLL知道。可以用如下的语句实现:
hr = spConnectionPoint- >Advise(
(IDispatch)this, &m_dwIDCode);
----在把IE实例中的事件和我们的DLL之间建立联系以后,我们可以通过IDispatch接口的Invoke()方法来处理所有的IE的事件。
----3.
IDispatch接口的Invoke()方法。IDispatch是从IUnknown中继承的一个接口的类型,通过COM接口提供的任何服务都可以通过IDispatch接口来实现。IDispatch::Invoke的工作方式同vtbl幕后的工作方式是类似的,Invoke将实现一组按索引来访问的函数,我们可以对Invoke方法进行动态的定制以提供不同的服务。Invoke方法的表示如下:
STDMETHOD(Invoke)(DISPID dispidMember,REFIID
riid, LCID lcid, WORD wFlags,
DISPPARAMS pdispparams, VARIANT pvarResult,
EXCEPINFO pexcepinfo, UINT puArgErr);
----其中,DISPID是一个长整数,它标识的是一个函数。对于IDispatch的某一个特定的实现,DISPID都是唯一的。IDispatch的每一个实现都有其自己的IID,这里dispidMemeber实际上是可以认为是和IE实例所发生的每一个事件相关的方法,比如:DISPID_BEFORENAVIGATE2,DISPID_NAVIGATECOMPLETE2等等。这个方法中另外一个比较重要的参数是DISPPARAMS,它的结构如下:
typedef struct tagDISPPARAMS
{
VARIANTARG
rgvarg;
//VARIANTARG是同VARAIANT相同的,可以在
//OAIDLIDL中找到。所以实际上rgvarg是一个参数数
//组
DISPID rgdispidNameArgs; //命名参数的DISPID
unsigned
int
cArgs; //表示数组中元素的个数
unsigned
int
CnameArgs; //命名元素的个数
}DISPPARAMS
----要注意的是每一个参数的类型都是VARIANTARG,所以在IE和我们DLL之间可以传递的参数类型的数目是有限的。只有那些能够被放到VARIANTARG结构中的类型才可以通过调度接口进行传递。比如对于事件DISPID_NAVIGATECOMPLETE2来说:第一个参数表示IE在访问的URL的值,类型是VT_BYREF|VT_VARIANT。注意DISPID_NAVIGATECOMPLETE2等DISPID已经在VC中被定义,我们可以直接进行使用。如上说述,我们在方法Invoke中可以得到所有IE实例所发生的事件,我们可以把这些数据放到文件中进行事后的分析,也可以放到一个列表框中实时的显示。
---- 4.微软的HTML文档对象模型和应用分析
----
下面我们来看如何得到网页文档的接口:网页文档的接口为IHTMLDocument2,可以通过调用IE
COM对象的get_Document方法来得到网页的接口。使用如下的语句:
hr = m_spWebBrowser2- >get_Document(&spDisp);
CComQIPtr< IHTMLDocument2,
&IID_IHTMLDocument2 > spHTML;
spHTML = spDisp;
----
这样我们就得到了网页对象的接口,然后我们就可以对网页进行分析,比如通过IHTMLDocument2提供的方法get_URL我们可以得到和该网页相关的URL的地址值,通过get_forms方法可以该网页中所有的Form对象的集合。实际上W3C组织已经制定了一个DOM(Document
Objec
Model)标准,当然这个标准不仅仅是针对HTML,同时还是针对XML制定的。W3C组织只是定义了网页对象的接口,不同的公司可以采用不同的语言和方法进行具体的实现。按照W3C组织定义的网页对象被认为是动态的,即用户可以动态的对网页对象里面所包含的每一个对象进行 *** 作。这里的对象可以是指一个输入框,也可以是图象和声音等对象。同时按照W3C的正式文档的说明,网页对象是可以动态增加和删除的。事实上,很少有厂商实现了DOM定义的所有功能。微软对网页对象的定义也基本上是按照这个标准实现的。但是当前的接口还不支持动态的增加和删除元素,但是可以对网页中的基本元素进行属性的修改。比如IHTMLElementCollection表示网页中一些基本的元素的集合,IHTMLElement表示网页中的一个基本的元素。而象IHTMLOptionElement接口就表示一个特定的元素Option。基本的元素都有setAttribute和geAttribute方法来动态的设置和得到元素的名称和值。
----
较为常见的一个应用是我们能够分析网页中是否有需要填写的Forms,如果这个网址的Forms以前已经填写过而且数据我们已经保存下来的话,我们就可以把数据自动放到和该URL下的Forms的相关的位置中去。另外,我们可以总结网页上需要填写的Form的数据项,先对这些数据项进行赋值,以后碰到有相同的数据项的时候就自动把我们赋值的内容填写进去。实际上Form是对象,Form中包含的元素,比如INPUT,OPTION,SELECT等类型的输入元素都是对象。
----
另外一个可以想到的应用是自动对网页中的文本进行翻译,因为我们可以修改网页中任何对象的属性,所以我们可以把里面不属于本国语言的部分自动翻译成本国语言,当然真正的实现还要靠自然语言理解方面技术的突破,但是IE浏览器的接口和对象的形式使我们能够灵活的控制整个IE,无论是从事件对象还是到网页对象。
TCHAR szPath[MAX_PATH];
::GetModuleFileName(NULL,szPath,MAX_PATH);
CString strPath = szPath;
int index = strPathReverseFind(_T( '\\'));
strPath = strPathLeft(index + 1);
学习mfc到一定程度,必然要查看一下它的源代码。可是组成mfc源代码的文
件太多又太长,如何快速方便地找到我们要看的东西?
初次学习vc的朋友或许不知道在你的vc++60安装目录的某个角落里有这么一
个文件:mfcbsc。这可是学习掌握vc和mfc的好帮手。靠它可以找出vc和mfc中某
个类的声明和成员函数的定义,可以找到vc中每一个预定义名和宏的定义,找出
一个文件里都声明了什么类,类中有些什么成员,还可以找出mfc中各个类的各个
成员函数谁调用了谁。
打开你的vc++60,先随便打开一个project,然后选菜单File/Open,在“文
件类型”一栏里选Browse Info File(bsc),然后进入“你的vc++60的安装目录
vc98mfcsrc”里,选中文件mfcbsc,按“打开”。
然后在主菜单里选Tool/Source Browser,会d出一个对话框,里面包含两个
窗口。第一个窗口是Identifier,你可以在这里输入函数名,类名,预定义名,
宏名,文件名。
如果你在第一个窗口里输入了函数名,类名,预定义名,宏名,那么你在第
二个窗口里可以选第一项:Definitions and References。然后按OK,就可以查
看函数,类,预定义名和宏的定义以及在何处被引用。
如果你在第一个窗口里输入了文件名,那么你在第二个窗口里可以选择第二
项:File Outline,按OK后可以查看该文件里声明了什么类,什么函数,等等。
如果你在第一个窗口里输入了一个类名,那么在第二个窗口里你可以选择第
三项和第四项:Base Classes and Members和Derived Classes and Members。按
OK后分别可以查看该类的基类及其成员和该类的派生类及其成员。
如果你在第一个窗口里输入了一个函数名,那么你在第二个窗口里可以选择
最后两项:Call Graph和Caller Graph,按OK后分别可以查看该函数调用了谁和
被谁调用。
还有一个小技巧:当最后的结果显示出来后,你在结果中的函数名,类名,
预定义名,宏名上双击鼠标左键,那么包含这些名字的定义或实现的文件就被打
开了。
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。
以上就是关于VC++菜鸟问题 拖拽文件到文本框获取文件路径简单问题全部的内容,包括:VC++菜鸟问题 拖拽文件到文本框获取文件路径简单问题、IE的路径在哪、VC下使用COM实现和IE浏览器交互的几种方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)