github.com/Mrs4s/go-cqhttp@v1.2.0/global/terminal/double_click_windows.go (about)

     1  package terminal
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"unsafe"
     7  
     8  	"golang.org/x/sys/windows"
     9  
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  // RunningByDoubleClick 检查是否通过双击直接运行
    14  func RunningByDoubleClick() bool {
    15  	kernel32 := windows.NewLazySystemDLL("kernel32.dll")
    16  	lp := kernel32.NewProc("GetConsoleProcessList")
    17  	if lp != nil {
    18  		var ids [2]uint32
    19  		var maxCount uint32 = 2
    20  		ret, _, _ := lp.Call(uintptr(unsafe.Pointer(&ids)), uintptr(maxCount))
    21  		if ret > 1 {
    22  			return false
    23  		}
    24  	}
    25  	return true
    26  }
    27  
    28  // NoMoreDoubleClick 提示用户不要双击运行,并生成安全启动脚本
    29  func NoMoreDoubleClick() error {
    30  	toHighDPI()
    31  	r := boxW(getConsoleWindows(), "请勿通过双击直接运行本程序, 这将导致一些非预料的后果.\n请在shell中运行./go-cqhttp.exe\n点击确认将释出安全启动脚本,点击取消则关闭程序", "警告", 0x00000030|0x00000001)
    32  	if r == 2 {
    33  		return nil
    34  	}
    35  	r = boxW(0, "点击确认将覆盖go-cqhttp.bat,点击取消则关闭程序", "警告", 0x00000030|0x00000001)
    36  	if r == 2 {
    37  		return nil
    38  	}
    39  	f, err := os.OpenFile("go-cqhttp.bat", os.O_CREATE|os.O_RDWR, 0o666)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	if err != nil {
    44  		return errors.Errorf("打开go-cqhttp.bat失败: %v", err)
    45  	}
    46  	_ = f.Truncate(0)
    47  
    48  	ex, _ := os.Executable()
    49  	exPath := filepath.Base(ex)
    50  	_, err = f.WriteString("%Created by go-cqhttp. DO NOT EDIT ME!%\nstart cmd /K \"" + exPath + "\"")
    51  	if err != nil {
    52  		return errors.Errorf("写入go-cqhttp.bat失败: %v", err)
    53  	}
    54  	f.Close()
    55  	boxW(0, "安全启动脚本已生成,请双击go-cqhttp.bat启动", "提示", 0x00000040|0x00000000)
    56  	return nil
    57  }
    58  
    59  // BoxW of Win32 API. Check https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw for more detail.
    60  func boxW(hwnd uintptr, caption, title string, flags uint) int {
    61  	captionPtr, _ := windows.UTF16PtrFromString(caption)
    62  	titlePtr, _ := windows.UTF16PtrFromString(title)
    63  	u32 := windows.NewLazySystemDLL("user32.dll")
    64  	ret, _, _ := u32.NewProc("MessageBoxW").Call(
    65  		hwnd,
    66  		uintptr(unsafe.Pointer(captionPtr)),
    67  		uintptr(unsafe.Pointer(titlePtr)),
    68  		uintptr(flags))
    69  
    70  	return int(ret)
    71  }
    72  
    73  // GetConsoleWindows retrieves the window handle used by the console associated with the calling process.
    74  func getConsoleWindows() (hWnd uintptr) {
    75  	hWnd, _, _ = windows.NewLazySystemDLL("kernel32.dll").NewProc("GetConsoleWindow").Call()
    76  	return
    77  }
    78  
    79  // toHighDPI tries to raise DPI awareness context to DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
    80  func toHighDPI() {
    81  	systemAware := ^uintptr(2) + 1
    82  	unawareGDIScaled := ^uintptr(5) + 1
    83  	u32 := windows.NewLazySystemDLL("user32.dll")
    84  	proc := u32.NewProc("SetThreadDpiAwarenessContext")
    85  	if proc.Find() != nil {
    86  		return
    87  	}
    88  	for i := unawareGDIScaled; i <= systemAware; i++ {
    89  		_, _, _ = u32.NewProc("SetThreadDpiAwarenessContext").Call(i)
    90  	}
    91  }