VB中实现带预览的对话框
作者:四川 陈东 
  用户在图片框中选择图片时,希望预先对图片的轮廓及大小有初步了解,但是VB的通用对话框没有预览的功能,为此需要定制一个自定义对话框。我们可以通过image控件加入窗体中来实现其功能。
  程序示例:
  程序功能说明:
  在窗体的file1中选择一个图片文件,点选“预览”复选框,image控件就显示相应的图片,label1就显示该图片的大小。
  新建一个工程,加入以下控件:
  控件 名称 属性
  form form1 borderstyle=3 
   (vbsizedouble)
  caption=“图片预览对话框"
  drivelistbox drive1 
  dirlistbox dir1
  filelistbox file1 pattern=“*.bmp;
   *.jpg;*.gif"
  image image1 stretch=true
  checkbox chk value=“预览"
  commandbutton cmd1 caption=“确定"
  cmd2 caption=“退出" 
   label lab1 caption=“" 
  源代码:
  'declare
  Public filename$
  dim sfilename$
   Private sub drive1_change()
  dir1.path=drive1.drive
  End sub
  Private sub dir1_change()
  file1.path=dir1.path
  End sub
  Private sub cmd1_click()
  filename=sfilename 
  End sub
  Private sub cmd2_click()
  End
  End sub
  Private sub file1_click()
  dim ssize as long
  if fille1.listcount>0 then
  if right(file1.path,1)<>“\" then
  sfilename=file1.path&“\"&file1.filename
  else
  sfilename=file1.path&file1.filename
  End if
  if chk.checked then
  image1.picture=loadpicture(“")
  image1.picture=loadpicture(sfilename)
  ssize=filelen(sfilename)
  ssize=ssize/1000
  lab1.caption=str(ssize)&“k"
  else
  lab1.caption=“"
  image1.picture=loadpicture(“")
  end if
  end if 
  End sub 

解决方案 »

  1.   

    从MSDN中可以知道调用文件打开通用对话框需调用API 函数GetOpenFileName,原形如下:BOOL GetOpenFileName( LPOPENFILENAME lpofn );// lpofn 为初始化数据结构的地址其参数lpofn指向类型为OPENFILENAME变量的地址,Windows已经为我们实现自定义的文件打开对话框留了接口。为了实现这个自定义的对话框,重点设置OPENFILENAME中的如下几个参数:Flags OFN_ENABLEHOOK 使由lpfnHook成员指定的钩子函数有效 
      OFN_ENABLETEMPLATE 表示由lpTemplateName指定一个对话框模板资源,这个资源存在于由hInstance指定的模块中 
    OFN_EXPLORER 如果指定了上述两个标志则必须指定这标志 
    lpfnHook 指向钩子函数的地址 
    lpTemplateName 对话框模板资源的字符串名,而不是ID 
    就是说你要在你的程序中包含一个对话框模板,Windows将以这个模板为基础显示通用对话框。从很多资料上都可以知道如果要在自定义的对话框中显示通用对话框,在您的对话框资源中必须包含一个Static,它的ID是stc32,十进制值为1119,这个Static也就是显示原来通用对话框的地方。当然他对对话框也有一些要求,这里就不废话了,自己看MSDN吧。我们在一个可以制作对话框资源的环境(我用的是VC)中制作出这个对话框,并将它存为res文件。从这里开始我们进入VB IDE中,把这个资源文件加入到你的VB应用程序中,假设它的名字是“DLGOPENTEMP”。接下来我们在VB工程中加入一个FORM,假设它的名字是FrmPreview,将它的BorderStyle 设定为None。并将一个PictureBox或者Image加入到窗体中,名字就叫做Picture1吧,我们就将在它里边显示预览的内容。下边呢也就是最关键的一步,编写Hook。在工程中加入一个Module,名字无所谓啦。假设我们的钩子叫wndProc,定义如下:Public Function wndProc(ByVal hDlg As Long, ByVal uiMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    On Error GoTo lblExitSelect Case uiMsg
    Case WM_NOTIFY
    CopyMemory NMHeader, ByVal lParam, Len(NMHeader)
    Select Case NMHeader.code
    Case CDN_INITDONE
    GetWindowRect GetDlgItem(hDlg, 1119), staticRect
    MapWindowPoints 0, hDlg, staticRect, 2SetParent FrmPreview.hwnd, hDlg
    FrmPreview.Visible = True
    FrmPreview.Move (staticRect.Right - staticRect.Left + 10) * Screen.TwipsPerPixelX, 5 * Screen.TwipsPerPixelX
    FrmPreview.Refresh
    wndProc = 0
    Case CDN_SELCHANGE
    FrmPreview.LoadPic GetFilesName(hDlg)
    wndProc = 0
    End Select
    Case WM_DESTROY
    FrmPreview.Visible = False
    SetParent FrmPreview.hwnd, 0
    Unload FrmPreview
    Case Else
    End Select
    Exit Function
    lblExit:
    End Function 在FrmPreview 中增加一个方法LoadPic,此方法将用户选中的可识别的图像文件显示在FrmPreview中的Picture1中,如何显示看您自己了。在得到CDN_SELCHANGE时,调用GetFilesName得到此时用户选中的文件,代码如下:Private Function GetFilesName(hWindow As Long) As String
    Dim hParent As Long
    Dim lRetValue As Long
    Dim theFileName(1024) As ByteFor i = 0 To UBound(theFileName)
    theFileName(i) = 0
    NexthParent = GetParent(hWindow)
    lRetValue = SendMessage(hParent, CDM_GETFILEPATH, 1024, theFileName(0))
    GetFilesName = StrConv(theFileName, vbUnicode)
    End Function调用GetOpenFileName API的方法如下:Public Function ShowOpenFileDlg(hParent As Long) As Long
    On Error GoTo lblExit
    Static strFilter As StringstrFilter = "All Pictures" & Chr(0) & "*.bmp;*.dib;*.jpg;*.gif;*.wmf;*.emf;*.ico;*.cur" & Chr(0) & _
    "Bitmap (*.bmp;*.dib)" & Chr(0) & "*.bmp;*.dib" & Chr(0) & _
    "JPEG (*.jpg)" & Chr(0) & "*.jpg" & Chr(0) & _
    "GIF (*.gif)" & Chr(0) & "*.gif" & Chr(0) & _
    "Metafile (*.wmf;*.emf)" & Chr(0) & "*.wmf;*.emf" & Chr(0) & _
    "Icons (*.ico;*.cur)" & Chr(0) & "*.ico;*.cur" & Chr(0) & _
    "All files (*.*)" & Chr(0) & "*.*" & Chr(0) & Chr(0)
    FrmPreview.Hide
    pointer = GetProcAddr(AddressOf wndProc)
    Dim MyID As Long
    With openfile
    .lStructSize = Len(openfile)
    .hwndOwner = hParent
    .hInstance = App.hInstance
    .lpstrFilter = strFilter
    .lpstrCustomFilter = ""
    .nMaxCustFilter = 0 
    .nFilterIndex = 0
    .lpstrFile = filesname
    .nMaxFile = 1023
    .lpstrFileTitle = ""
    .nMaxFileTitle = 0
    .lpstrInitialDir = ""
    .lpstrTitle = ""
    .flags = OFN_ENABLEHOOK + OFN_HIDEREADONLY + OFN_ENABLETEMPLATE + OFN_EXPLORER
    .nFileOffset = 0
    .nFileExtension = 0
    .lpstrDefExt = ""
    .lCustData = 0
    .lpfnHook = pointer
    .lpTemplateName = "DLGOPENTEMP"
    End With
    ShowOpenFileDlg = GetOpenFileName(openfile)
    lblExit:
    End Function
    文件就放在filesname里,它必须预先分配好空间。