2016-02-12 18:02:16 +00:00
// Copyright 2010-2012 The W32 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
2017-02-02 06:25:39 +00:00
// +build windows
2016-02-12 18:02:16 +00:00
package w32
import (
"errors"
"fmt"
"syscall"
"unsafe"
)
var (
modshell32 = syscall . NewLazyDLL ( "shell32.dll" )
procSHBrowseForFolder = modshell32 . NewProc ( "SHBrowseForFolderW" )
procSHGetPathFromIDList = modshell32 . NewProc ( "SHGetPathFromIDListW" )
procDragAcceptFiles = modshell32 . NewProc ( "DragAcceptFiles" )
procDragQueryFile = modshell32 . NewProc ( "DragQueryFileW" )
procDragQueryPoint = modshell32 . NewProc ( "DragQueryPoint" )
procDragFinish = modshell32 . NewProc ( "DragFinish" )
procShellExecute = modshell32 . NewProc ( "ShellExecuteW" )
procExtractIcon = modshell32 . NewProc ( "ExtractIconW" )
)
func SHBrowseForFolder ( bi * BROWSEINFO ) uintptr {
ret , _ , _ := procSHBrowseForFolder . Call ( uintptr ( unsafe . Pointer ( bi ) ) )
return ret
}
func SHGetPathFromIDList ( idl uintptr ) string {
buf := make ( [ ] uint16 , 1024 )
procSHGetPathFromIDList . Call (
idl ,
uintptr ( unsafe . Pointer ( & buf [ 0 ] ) ) )
return syscall . UTF16ToString ( buf )
}
func DragAcceptFiles ( hwnd HWND , accept bool ) {
procDragAcceptFiles . Call (
uintptr ( hwnd ) ,
uintptr ( BoolToBOOL ( accept ) ) )
}
func DragQueryFile ( hDrop HDROP , iFile uint ) ( fileName string , fileCount uint ) {
ret , _ , _ := procDragQueryFile . Call (
uintptr ( hDrop ) ,
uintptr ( iFile ) ,
0 ,
0 )
fileCount = uint ( ret )
if iFile != 0xFFFFFFFF {
buf := make ( [ ] uint16 , fileCount + 1 )
ret , _ , _ := procDragQueryFile . Call (
uintptr ( hDrop ) ,
uintptr ( iFile ) ,
uintptr ( unsafe . Pointer ( & buf [ 0 ] ) ) ,
uintptr ( fileCount + 1 ) )
if ret == 0 {
panic ( "Invoke DragQueryFile error." )
}
fileName = syscall . UTF16ToString ( buf )
}
return
}
func DragQueryPoint ( hDrop HDROP ) ( x , y int , isClientArea bool ) {
var pt POINT
ret , _ , _ := procDragQueryPoint . Call (
uintptr ( hDrop ) ,
uintptr ( unsafe . Pointer ( & pt ) ) )
return int ( pt . X ) , int ( pt . Y ) , ( ret == 1 )
}
func DragFinish ( hDrop HDROP ) {
procDragFinish . Call ( uintptr ( hDrop ) )
}
func ShellExecute ( hwnd HWND , lpOperation , lpFile , lpParameters , lpDirectory string , nShowCmd int ) error {
var op , param , directory uintptr
if len ( lpOperation ) != 0 {
op = uintptr ( unsafe . Pointer ( syscall . StringToUTF16Ptr ( lpOperation ) ) )
}
if len ( lpParameters ) != 0 {
param = uintptr ( unsafe . Pointer ( syscall . StringToUTF16Ptr ( lpParameters ) ) )
}
if len ( lpDirectory ) != 0 {
directory = uintptr ( unsafe . Pointer ( syscall . StringToUTF16Ptr ( lpDirectory ) ) )
}
ret , _ , _ := procShellExecute . Call (
uintptr ( hwnd ) ,
op ,
uintptr ( unsafe . Pointer ( syscall . StringToUTF16Ptr ( lpFile ) ) ) ,
param ,
directory ,
uintptr ( nShowCmd ) )
errorMsg := ""
if ret != 0 && ret <= 32 {
switch int ( ret ) {
case ERROR_FILE_NOT_FOUND :
errorMsg = "The specified file was not found."
case ERROR_PATH_NOT_FOUND :
errorMsg = "The specified path was not found."
case ERROR_BAD_FORMAT :
errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
case SE_ERR_ACCESSDENIED :
errorMsg = "The operating system denied access to the specified file."
case SE_ERR_ASSOCINCOMPLETE :
errorMsg = "The file name association is incomplete or invalid."
case SE_ERR_DDEBUSY :
errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
case SE_ERR_DDEFAIL :
errorMsg = "The DDE transaction failed."
case SE_ERR_DDETIMEOUT :
errorMsg = "The DDE transaction could not be completed because the request timed out."
case SE_ERR_DLLNOTFOUND :
errorMsg = "The specified DLL was not found."
case SE_ERR_NOASSOC :
errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable."
case SE_ERR_OOM :
errorMsg = "There was not enough memory to complete the operation."
case SE_ERR_SHARE :
errorMsg = "A sharing violation occurred."
default :
errorMsg = fmt . Sprintf ( "Unknown error occurred with error code %v" , ret )
}
} else {
return nil
}
return errors . New ( errorMsg )
}
func ExtractIcon ( lpszExeFileName string , nIconIndex int ) HICON {
ret , _ , _ := procExtractIcon . Call (
0 ,
uintptr ( unsafe . Pointer ( syscall . StringToUTF16Ptr ( lpszExeFileName ) ) ) ,
uintptr ( nIconIndex ) )
return HICON ( ret )
}