2013-07-30 30 views
5

Tôi cố gắng tìm ra thư mục phông chữ trên cài đặt cửa sổ. AFAICS cách được đề xuất là gọi SHGetKnownFolderPath trong Shell32.dll với KNOWNFOLDERID được đặt thành FOLDERID_Fonts.Chức năng cửa sổ cuộc gọi (nhận thư mục phông chữ)

Tôi không có ý tưởng gì để vượt qua các Call chức năng trong các mã dưới đây:

package main 

import (
    "syscall" 
) 

func main() { 
    // HRESULT SHGetKnownFolderPath(
    // _In_  REFKNOWNFOLDERID rfid, 
    // _In_  DWORD dwFlags, 
    // _In_opt_ HANDLE hToken, 
    // _Out_  PWSTR *ppszPath 
    //); 

    var (
     shell32    = syscall.NewLazyDLL("Shell32.dll") 
     shGetKnowFolderPath = shell32.NewProc("SHGetKnownFolderPath") 

     // Doesn't work, of course: 
     folderId int 
     flags int 
     handle int 
     retval int 
    ) 

    shGetKnowFolderPath.Call(uintptr(folderId), uintptr(flags), uintptr(handle), uintptr(retval)) 
} 

Bất kỳ ý tưởng? (Tôi đoán một giải pháp cho bây giờ sẽ là dính vào %windir%\Fonts, nhưng tôi muốn nhận được một giải pháp thích hợp).

Tài liệu tham khảo:

+0

Tại sao lưu ý lại? Tôi có thể làm gì để cải thiện câu hỏi? – topskip

Trả lời

8

Ví dụ,

package main 

import (
    "fmt" 
    "syscall" 
    "unsafe" 
) 

type GUID struct { 
    Data1 uint32 
    Data2 uint16 
    Data3 uint16 
    Data4 [8]byte 
} 

var (
    FOLDERID_Fonts = GUID{0xFD228CB7, 0xAE11, 0x4AE3, [8]byte{0x86, 0x4C, 0x16, 0xF3, 0x91, 0x0A, 0xB8, 0xFE}} 
) 

var (
    modShell32    = syscall.NewLazyDLL("Shell32.dll") 
    modOle32     = syscall.NewLazyDLL("Ole32.dll") 
    procSHGetKnownFolderPath = modShell32.NewProc("SHGetKnownFolderPath") 
    procCoTaskMemFree  = modOle32.NewProc("CoTaskMemFree") 
) 

func SHGetKnownFolderPath(rfid *GUID, dwFlags uint32, hToken syscall.Handle, pszPath *uintptr) (retval error) { 
    r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(rfid)), uintptr(dwFlags), uintptr(hToken), uintptr(unsafe.Pointer(pszPath)), 0, 0) 
    if r0 != 0 { 
     retval = syscall.Errno(r0) 
    } 
    return 
} 

func CoTaskMemFree(pv uintptr) { 
    syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(pv), 0, 0) 
    return 
} 

func FontFolder() (string, error) { 
    var path uintptr 
    err := SHGetKnownFolderPath(&FOLDERID_Fonts, 0, 0, &path) 
    if err != nil { 
     return "", err 
    } 
    defer CoTaskMemFree(path) 
    folder := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(path))[:]) 
    return folder, nil 
} 

func main() { 
    folder, err := FontFolder() 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Println("Font Folder:", folder) 
} 

Output:

Font Folder: C:\Windows\Fonts 
+0

Tuyệt vời, cảm ơn! Vẫn cố hiểu điều này. Hãy cho tôi một ngày :) – topskip

+1

Câu trả lời hay ... chỉ cần thêm mã sẽ không giúp các nhà phát triển mới ... Sẽ tốt hơn nếu bạn thêm chi tiết về quy trình của mình – Baba

-1

folderId cho thư mục phông chữ là {FD228CB7-AE11-4AE3-864C-16F3910AB8FE}

flags thể có thể được SHGFP_TYPE_DEFAULT

handle lẽ có thể NULL

retvalTôi nghĩ phải là một bool nhưng tôi không chắc chắn.

Tất cả câu trả lời là từ số SHGetFolderPath function được liên kết trước đó của bạn.

+0

Giá trị trả về là loại 'HRESULT'. Nó có thể được chuyển đổi thành một mã thành công boolean bằng cách sử dụng các macro 'SUCCEEDED (hr)' hoặc 'FAILED (hr)'. – IInspectable

+0

@Tim Cảm ơn, điều đó có ý nghĩa. – Intermernet

2

Chỉ trong trường hợp ai đó cần id thư mục cho các tài liệu ở định dạng golang:

Thay thế này trong ví dụ mã peterSO của:

FOLDERID_Documents = GUID {0xFDD39AD0, 0x238F, 0x46AF, [8] byte {0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7}}

FOLDERID_PublicDocuments = GUID {0xED4824AF, 0xDCE4, 0x45A8, [8] byte {0x81, 0xE2, 0xFC, 0x79, 0x65, 0x08, 0x36, 0x34}}

thấy

https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

Các vấn đề liên quan