shell32.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2010-2012 The W32 Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build windows
  5. package w32
  6. import (
  7. "errors"
  8. "fmt"
  9. "syscall"
  10. "unsafe"
  11. )
  12. var (
  13. modshell32 = syscall.NewLazyDLL("shell32.dll")
  14. procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolderW")
  15. procSHGetPathFromIDList = modshell32.NewProc("SHGetPathFromIDListW")
  16. procDragAcceptFiles = modshell32.NewProc("DragAcceptFiles")
  17. procDragQueryFile = modshell32.NewProc("DragQueryFileW")
  18. procDragQueryPoint = modshell32.NewProc("DragQueryPoint")
  19. procDragFinish = modshell32.NewProc("DragFinish")
  20. procShellExecute = modshell32.NewProc("ShellExecuteW")
  21. procExtractIcon = modshell32.NewProc("ExtractIconW")
  22. )
  23. func SHBrowseForFolder(bi *BROWSEINFO) uintptr {
  24. ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi)))
  25. return ret
  26. }
  27. func SHGetPathFromIDList(idl uintptr) string {
  28. buf := make([]uint16, 1024)
  29. procSHGetPathFromIDList.Call(
  30. idl,
  31. uintptr(unsafe.Pointer(&buf[0])))
  32. return syscall.UTF16ToString(buf)
  33. }
  34. func DragAcceptFiles(hwnd HWND, accept bool) {
  35. procDragAcceptFiles.Call(
  36. uintptr(hwnd),
  37. uintptr(BoolToBOOL(accept)))
  38. }
  39. func DragQueryFile(hDrop HDROP, iFile uint) (fileName string, fileCount uint) {
  40. ret, _, _ := procDragQueryFile.Call(
  41. uintptr(hDrop),
  42. uintptr(iFile),
  43. 0,
  44. 0)
  45. fileCount = uint(ret)
  46. if iFile != 0xFFFFFFFF {
  47. buf := make([]uint16, fileCount+1)
  48. ret, _, _ := procDragQueryFile.Call(
  49. uintptr(hDrop),
  50. uintptr(iFile),
  51. uintptr(unsafe.Pointer(&buf[0])),
  52. uintptr(fileCount+1))
  53. if ret == 0 {
  54. panic("Invoke DragQueryFile error.")
  55. }
  56. fileName = syscall.UTF16ToString(buf)
  57. }
  58. return
  59. }
  60. func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) {
  61. var pt POINT
  62. ret, _, _ := procDragQueryPoint.Call(
  63. uintptr(hDrop),
  64. uintptr(unsafe.Pointer(&pt)))
  65. return int(pt.X), int(pt.Y), (ret == 1)
  66. }
  67. func DragFinish(hDrop HDROP) {
  68. procDragFinish.Call(uintptr(hDrop))
  69. }
  70. func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
  71. var op, param, directory uintptr
  72. if len(lpOperation) != 0 {
  73. op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
  74. }
  75. if len(lpParameters) != 0 {
  76. param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
  77. }
  78. if len(lpDirectory) != 0 {
  79. directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
  80. }
  81. ret, _, _ := procShellExecute.Call(
  82. uintptr(hwnd),
  83. op,
  84. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
  85. param,
  86. directory,
  87. uintptr(nShowCmd))
  88. errorMsg := ""
  89. if ret != 0 && ret <= 32 {
  90. switch int(ret) {
  91. case ERROR_FILE_NOT_FOUND:
  92. errorMsg = "The specified file was not found."
  93. case ERROR_PATH_NOT_FOUND:
  94. errorMsg = "The specified path was not found."
  95. case ERROR_BAD_FORMAT:
  96. errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
  97. case SE_ERR_ACCESSDENIED:
  98. errorMsg = "The operating system denied access to the specified file."
  99. case SE_ERR_ASSOCINCOMPLETE:
  100. errorMsg = "The file name association is incomplete or invalid."
  101. case SE_ERR_DDEBUSY:
  102. errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
  103. case SE_ERR_DDEFAIL:
  104. errorMsg = "The DDE transaction failed."
  105. case SE_ERR_DDETIMEOUT:
  106. errorMsg = "The DDE transaction could not be completed because the request timed out."
  107. case SE_ERR_DLLNOTFOUND:
  108. errorMsg = "The specified DLL was not found."
  109. case SE_ERR_NOASSOC:
  110. 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."
  111. case SE_ERR_OOM:
  112. errorMsg = "There was not enough memory to complete the operation."
  113. case SE_ERR_SHARE:
  114. errorMsg = "A sharing violation occurred."
  115. default:
  116. errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
  117. }
  118. } else {
  119. return nil
  120. }
  121. return errors.New(errorMsg)
  122. }
  123. func ExtractIcon(lpszExeFileName string, nIconIndex int) HICON {
  124. ret, _, _ := procExtractIcon.Call(
  125. 0,
  126. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszExeFileName))),
  127. uintptr(nIconIndex))
  128. return HICON(ret)
  129. }