登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

miaozk2006

点滴积累与收藏:关于技术,关于生活

 
 
 

日志

 
 

VB中用API实现文件拖放  

2013-02-11 18:08:47|  分类: 编程-VB |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

       借助API函数CallWindowProc、DragAcceptFiles、DragQueryFile、DragFinish同样可以实现文件从资源管理器EXPLORE到应用程序的拖放,另一种方法是采用OLE拖放,可以参照趣味编程栏目的相关内容。下面我们一起来看看程序编写的过程。
  借助API函数CallWindowProc、DragAcceptFiles、DragQueryFile、DragFinish同样可以实现文件从资源管理器EXPLORE到应用程序的拖放,另一种方法是采用OLE拖放,可以参照趣味编程栏目的相关内容。下面我们一起来看看程序编写的过程。

  对于每个需要引用的API函数,我们需要先在程序中说明,如果只在某一窗体内声明并使用它,则把它声明为Private,而如果在模块中声明,且需要在整个工程内使用它,则需要把它声明为Public。

     Public Declare Function CallWindowProc& Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc&, ByVal hWnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
   Public Declare Sub DragAcceptFiles Lib "shell32.dll" (ByVal hWnd&, ByVal fAccept&)
   Public Declare Function DragQueryFile& Lib "shell32.dll" Alias "DragQueryFileA" (ByVal hDrop&, ByVal iFile&,ByVal lpszFile$, ByVal cch&)
   Public Declare Sub DragFinish Lib "shell32.dll" (ByVal hDrop&)
   Private Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hWnd&,ByVal nIndex&, ByVal dwNewLong&)

  SetWindowLong函数的作用是在窗口结构中为指定的窗口设置属性,利用它我们来改变窗口的属性参数,其中各个参数的意义如下表所示:

参数 意义 hwnd Long,欲为其取得信息的窗口的句柄 nIndex Long,这里取GWL_WNDPROC,表示设置该窗口的窗口函数的地址 dwNewLong Long,由nIndex指定的窗口信息的新值
  返回值 Long,指定数据的前一个值

  在默认状态下WINDOWS操作系统会指定一个窗口函数来接受和处理WINDOWS消息,而通过使用SetWindowLong函数改变窗口函数的地址使它指向我们自己写的一个函数WindowProc,这样WINDOWS消息就会转由WindowProc函数接收和处理。于是我们就能判断文件拖放的消息并进行处理。改变窗口属性的语句如下:

procOld = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf WindowProc)
  DragAcceptFiles、DragQueryFile、DragFinish三个函数的作用分别是:把某个窗口设置为接收拖放的容器、返回拖放的文件的数量和信息、终止拖放。

  为了学习方便,以下提供了源代码:

'-------------------------------------------
' 采用API实现的文件拖放
'-------------------------------------------
'程序说明:
'本例是采用子类派生技术实现的文件从EXPLORE到VB程序的拖放
' 通过三个API函数DragAcceptFiles、DragQueryFiles和
'DragFinish,并通过回调函数WindowProc,窗口属性函数
'SetWindowLong、CallWindowProc的使用实现,而另一种同样
'效果的实现方法:OLE拖放,你可以参照文件拖放的另外一个实
'例。
'-------------------------------------------
Option Explicit
Private Const GWL_WNDPROC As Long = (-4&)
' API call to alter the class data for this window
Private Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hWnd&, _
                 ByVal nIndex&, ByVal dwNewLong&)
Private Sub Form_Load()
'定义 Picture1作为接收文件拖放的容器
DragAcceptFiles Me.hWnd, 1&
'整个procOld变量用来存储窗口的原始参数,以便恢复
' 调用了 SetWindowLong 函数,它使用了 GWL_WNDPROC 索引来创建窗口类的子类,通过这样设置
'操作系统发给窗体的消息将由回调函数 (WindowProc) 来截取, AddressOf是关键字取得函数地址
procOld = SetWindowLong(Me.hWnd, GWL_WNDPROC, AddressOf WindowProc)
   'AddressOf是一元运算符,它在过程地址传送到 API 过程之前,先得到该过程的地址
End Sub
Private Sub Form_Unload(Cancel As Integer)
'此句关键,把窗口(不是窗体,而是具有句柄的任一控件,这里指Picture1)的属性复原
Call SetWindowLong(Me.hWnd, GWL_WNDPROC, procOld)
End Sub
Public Sub DropFiles(ByVal hDrop&)
Dim sFileName$, IReturn&
Dim nCount&, I As Integer
'为sFileName分配存储空间
sFileName = String$(MAX_PATH, vbNullChar)
'通过文件指针hDrop, DragQueryFile返回是否有文件拖放,nCount返回拖放文件的个数
nCount = DragQueryFile(hDrop, -1, sFileName, MAX_PATH)
'循环读取每一个拖放的文件,把它在列表框中显示出来
For I = 0 To nCount - 1
sFileName = String$(MAX_PATH, vbNullChar)
'如果有文件拖放,接收文件名,并试图把它在图片框中打开
'IReturn&
IReturn& = DragQueryFile(hDrop, I, sFileName, MAX_PATH)
List1.AddItem Left$(sFileName, IReturn)
Next I
'完成拖放操作
DragFinish hDrop
End Sub
'以下代码放在moudle中
Option Explicit
Public Const MAX_PATH As Long = 260&
'标示我们要截获的消息
Public Const WM_DROPFILES As Long = &H233&
'保存原 窗体属性的变量,其实是默认的 窗体函数 的地址
Public procOld As Long
'
Public Declare Function CallWindowProc& Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc&, _
ByVal hWnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
'拖放操作相关的API函数
Public Declare Sub DragAcceptFiles Lib "shell32.dll" (ByVal hWnd&, ByVal fAccept&)
Public Declare Function DragQueryFile& Lib "shell32.dll" Alias "DragQueryFileA" (ByVal hDrop&, ByVal iFile&, _
ByVal lpszFile$, ByVal cch&)
Public Declare Sub DragFinish Lib "shell32.dll" (ByVal hDrop&)
'WARNING!!!!-----------------------------------------------------------
'注意这段代码是不能用DEBUG一步步调试的,否则会造成错误(崩溃)
'对消息截获的机制可以按下述理解:
' 这里要仔细理解一下,我们为窗体新指定了窗体函数地址,也就是说操作系统发送给窗体的
'消息将被 WindowProc函数 所截获(而改变前消息是被默认的 窗体函数 所获得并作相应处理的)
' 这样我们在 WindowProc函数 中对所截获的消息进行判断,会有三种情况:
'<1>如果是需要通过程序来处理的消息就通过 WindowProc函数 中的相应语句处理;
'<2>如果是要原来的 窗体函数 来处理则把这个消息传递给原窗体函数(其实是指针指向的改变);
'<3>如果不是我们需要的消息,也传递给原 窗体函数 来处理。
  '可以参见 改变系统菜单 中的源码注释
'WARNING!!!!-----------------------------------------------------------
'回调函数,用来截取消息
Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, _
            ByVal wParam As Long, ByVal lParam As Long) As Long
  '确定接收到的是什么消息
  Select Case iMsg
  '如果是 通知文件放下 的消息,就拦截消息
  Case WM_DROPFILES
  '通知在FORM模块中定义的DropFiles函数来接收 指向 放下的文件 的句柄
  frmDragDropFiles.DropFiles wParam
  '返回0并退出这个WindowProc
  WindowProc = False
  Exit Function
  End Select
  '如果不是我们需要的消息,则传递给原来的窗体函数处理
  WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
End Function

 

  附:子类派生技术

  WINDOWS运行的基础是“消息机制”,所谓的“消息”是一个唯一的值,这个值会被一个窗体或操作系统收到,它能告诉什么事件发生了以及需要采用什么样的动作来响应。这与我们人类的神经系统将感知的信息传递给大脑,而大脑发出指令给我们的身体非常相似。于是每一个窗体都具有一个消息句柄,这个机制使得所有发自于WINDOWS操作系统的消息能被接收到需要强调的是每个窗体以及每个控件,包括按钮、文本框、图片框等都具有这样的消息句柄。WINDOWS操作系统会跟踪这些消息句柄,这称为类结构中的一个WindowProc,所谓的类结构是于窗体句柄相关联的。

  当我们加入一个新的WindowProc函数而这个WindowProc与原始的窗体函数相符合的话,我们称这个窗被子类化了。换言之,如果WINDOWS操作系统发给你所在的WindowProc一个消息,而你所在的WindowProc正在响应其它的动作,这时你必须将剩余的消息传递给一个默认的WindoProc。

  如下所示: 操作系统消息-->你所在WindoProc-->默认的WindoProc而一个窗体是可以被子类化多次的,这样就产生了如下的情况:

  Windows Message Sender --> Your WindowProc --> Another WindowProc _--> Yet Another WindowProc --> Default WindowProc

  What is subclassing anyway?

  通过窗体子类化,你可以改变响应消息的顺序,也就是说,你可以把消息传递到默认的WindowProc上而不立即响应。举个例子:

  如果我们要在接收到WM_PAINT 消息后,在窗体上画出一些东西,可以用下面的语句实现:

Public Function WindowProc(Byval hWnd, Byval etc....)
    Select Case iMsg      '筛选出WM_PAINT消息
        Case SOME_MESSAGE    '如果是其他消息
        DoSomeStuff
        Case WM_PAINT    '如果是WM_PAINT 消息
        '首先把消息传递给一个默认的WindowProc
        WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
        DoDrawingStuff      '进行画图操作
        Exit Function
        '因为我们已经把消息传递给默认的WindowProc,我们可以退出这个WindowProc
        '
    End Select
    '
 End Function
摘自:网络整理
  

VB相关


VB 释放资源文件到指定目录函数

VB 读取资源文件里面的字符串

VB中资源文件.res的使用方法详解

VB6.0中创建和使用文本资源文件

VB WindowsMediaPlayer 播放

vbWindowsMediaPlayer的常用属性和方法

VB Environ系统环境变量函数大全

VB 去除文本框粘贴功能

VB LISTBOX

VB 删除数组中的重复元素

VB数组快速排序算法

关于三个概念:ActiveXOLECOM

VB 获得磁盘的文件系统

VB中用API实现文件拖放

加密算法-MD5算法

VB中使用MD5算法

VB 全局热键HOOK (不占系统资源版本)

VB 小技巧自定义TextBox文本框右键菜单

VB 写下载者代码

VB 一行代码的诀窍

VBS教程-wscript对象

vb枚举进程

VB中如何让线程或进程在指定的CPU上运行

VB判断指定的WORD文档是否被打开

VB如何读取快捷方式的目标路径

VBAPI控制输入法状态

为系统加载右键注册控件选项【VB 注册控件】

VB如何根据窗口标题获得进程名称

VB快速查找大型文件中包含的字符串

VB实现可执行文件运行时自删除

VB 打开txt,bat,jpg 任意后缀程序

VB 写文件关联程序

VB 自启动建立右键菜单

VB 判断IP能否ping

VB FTP操作类(可上传、下载、创建文件夹等等)

VB部分文件汇总B

Vb 求素数最经典的方法也是最快的方法

vb用数组方式快速导出MSFlexGrid表格数据到Excel表格中

VBMsFlexGrid控件的使用细则

点击MSFlexGrid数据控件的标题进行数据排序

VB 获取鼠标坐标

VBNEW的用法(申请内存空间)

VB CreateObject函数

VB中的New CreateObject的区别

VB ListBox 添加不重复的值

VB 单击ListView控件某列表头进行排序

VB 简单实现简体与繁体互转

VB 阿拉伯数字转换为中文大写数值函数

VB 获取Textbox文本框中的行数函数


更多精彩>>>
  评论这张
 
阅读(1012)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018