| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- package main
- import (
- "encoding/json"
- "fmt"
- "log"
- "net/http"
- "os/exec"
- "syscall"
- "time"
- "unsafe"
- )
- type RequestData struct {
- Type string `json:"type"`
- Path string `json:"path"`
- FileName string `json:"fileName"`
- }
- // 常量
- const (
- VK_CONTROL = 0x11
- VK_V = 0x56
- )
- var (
- user32 = syscall.NewLazyDLL("user32.dll")
- findWindowW = user32.NewProc("FindWindowW")
- moveWindow = user32.NewProc("MoveWindow")
- setForegroundWindow = user32.NewProc("SetForegroundWindow")
- getWindowRect = user32.NewProc("GetWindowRect")
- setCursorPos = user32.NewProc("SetCursorPos")
- mouse_event = user32.NewProc("mouse_event")
- keybd_event = user32.NewProc("keybd_event")
- )
- type RECT struct {
- Left int32
- Top int32
- Right int32
- Bottom int32
- }
- // 回车键的虚拟键码
- const VK_RETURN = 0x0D
- const KEYEVENTF_KEYUP = 0x0002
- // 简化函数
- func FindWindow(title string) (uintptr, error) {
- titlePtr, err := syscall.UTF16PtrFromString(title)
- if err != nil {
- return 0, err
- }
- hwnd, _, err := findWindowW.Call(0, uintptr(unsafe.Pointer(titlePtr)))
- if hwnd == 0 {
- return 0, fmt.Errorf("窗口未找到: %v", err)
- }
- return hwnd, nil
- }
- func MoveWindow(hwnd uintptr, x, y, w, h int32) error {
- ret, _, err := moveWindow.Call(hwnd, uintptr(x), uintptr(y), uintptr(w), uintptr(h), 1)
- if ret == 0 {
- return fmt.Errorf("移动窗口失败: %v", err)
- }
- return nil
- }
- func SetForegroundWindow(hwnd uintptr) error {
- ret, _, err := setForegroundWindow.Call(hwnd)
- if ret == 0 {
- return fmt.Errorf("设置前台窗口失败: %v", err)
- }
- return nil
- }
- func GetWindowRect(hwnd uintptr) (RECT, error) {
- var rect RECT
- ret, _, err := getWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&rect)))
- if ret == 0 {
- return rect, fmt.Errorf("获取窗口矩形失败: %v", err)
- }
- return rect, nil
- }
- func SetCursorPos(x, y int32) error {
- ret, _, err := setCursorPos.Call(uintptr(x), uintptr(y))
- if ret == 0 {
- return fmt.Errorf("设置光标位置失败: %v", err)
- }
- return nil
- }
- func MouseClick(x, y int32) error {
- // 移动鼠标
- if err := SetCursorPos(x, y); err != nil {
- return err
- }
- time.Sleep(100 * time.Millisecond)
- // 左键按下 (0x0002 = MOUSEEVENTF_LEFTDOWN)
- mouse_event.Call(2, 0, 0, 0, 0)
- time.Sleep(50 * time.Millisecond)
- // 左键释放 (0x0004 = MOUSEEVENTF_LEFTUP)
- mouse_event.Call(4, 0, 0, 0, 0)
- return nil
- }
- func Paste() {
- // Ctrl 按下
- keybd_event.Call(uintptr(VK_CONTROL), 0, 0, 0)
- time.Sleep(50 * time.Millisecond)
- // V 按下
- keybd_event.Call(uintptr(VK_V), 0, 0, 0)
- time.Sleep(50 * time.Millisecond)
- // V 释放 (0x0002 = KEYEVENTF_KEYUP)
- keybd_event.Call(uintptr(VK_V), 0, 2, 0)
- time.Sleep(50 * time.Millisecond)
- // Ctrl 释放
- keybd_event.Call(uintptr(VK_CONTROL), 0, 2, 0)
- }
- func PressEnter() {
- // 按下回车键
- keybd_event.Call(
- uintptr(VK_RETURN), // bVk
- 0, // bScan
- 0, // dwFlags (按下)
- 0, // dwExtraInfo
- )
- time.Sleep(5 * time.Millisecond)
- // 释放回车键
- keybd_event.Call(
- uintptr(VK_RETURN), // bVk
- 0, // bScan
- uintptr(KEYEVENTF_KEYUP), // dwFlags (释放)
- 0, // dwExtraInfo
- )
- }
- // 使用系统命令设置剪贴板(更可靠)
- func SetClipboard(text string) error {
- // 方法1:使用 clip 命令
- cmd := exec.Command("cmd", "/c", fmt.Sprintf("echo %s | clip", text))
- if err := cmd.Run(); err == nil {
- return nil
- }
- // 方法2:使用 PowerShell
- cmd2 := exec.Command("powershell", "-Command", fmt.Sprintf("Set-Clipboard -Value '%s'", text))
- return cmd2.Run()
- }
- func findAndOperateWindow(title string, filePath string, fileName string) {
- fmt.Printf("开始查找窗口: %s\n", title)
- var hwnd uintptr
- var err error
- found := false
- // 10秒内每秒尝试查找窗口
- for i := 0; i < 10; i++ {
- fmt.Printf("尝试第 %d 次查找...\n", i+1)
- hwnd, err = FindWindow(title)
- if err == nil && hwnd != 0 {
- found = true
- fmt.Printf("找到窗口: %s (句柄: 0x%X)\n", title, hwnd)
- break
- }
- time.Sleep(1 * time.Second)
- }
- if !found {
- log.Printf("在10秒内未找到窗口: %s", title)
- log.Println("请确保:")
- log.Println("1. 窗口已经打开")
- log.Println("2. 窗口标题完全匹配: " + title)
- log.Println("3. 可能需要以管理员身份运行此程序")
- return
- }
- // 激活窗口
- if err := SetForegroundWindow(hwnd); err != nil {
- log.Printf("激活窗口失败: %v", err)
- }
- time.Sleep(500 * time.Millisecond)
- // 调整窗口大小到800x600
- fmt.Println("正在修改窗口大小为800x600...")
- if err := MoveWindow(hwnd, 100, 100, 800, 600); err != nil {
- log.Printf("调整窗口大小失败: %v", err)
- } else {
- fmt.Println("窗口大小修改成功")
- }
- // 获取窗口位置
- rect, err := GetWindowRect(hwnd)
- if err != nil {
- log.Printf("获取窗口位置失败: %v", err)
- } else {
- fmt.Printf("窗口位置: X=%d, Y=%d\n", rect.Left, rect.Top)
- }
- // 等待窗口调整完成
- time.Sleep(500 * time.Millisecond)
- MouseClick(rect.Left+270, rect.Top+60)
- SetClipboard(filePath)
- time.Sleep(500 * time.Millisecond)
- // 粘贴剪贴板内容
- fmt.Println("正在粘贴剪贴板内容...")
- Paste()
- fmt.Println("粘贴完成")
- time.Sleep(500 * time.Millisecond)
- fmt.Println("按回车键")
- PressEnter()
- fmt.Println("操作完成")
- MouseClick(rect.Left+380, rect.Top+530)
- time.Sleep(2 * time.Second)
- SetClipboard(fileName)
- time.Sleep(500 * time.Millisecond)
- Paste()
- time.Sleep(500 * time.Millisecond)
- PressEnter()
- }
- func handlePostRequest(w http.ResponseWriter, r *http.Request) {
- // 只处理POST请求
- if r.Method != http.MethodPost {
- http.Error(w, "只支持POST请求", http.StatusMethodNotAllowed)
- return
- }
- // 解析JSON数据
- var data RequestData
- decoder := json.NewDecoder(r.Body)
- if err := decoder.Decode(&data); err != nil {
- http.Error(w, "JSON解析错误: "+err.Error(), http.StatusBadRequest)
- return
- }
- defer r.Body.Close()
- // 输出接收到的数据
- fmt.Println("=== 接收到POST请求数据 ===")
- fmt.Printf("类型 (type): %s\n", data.Type)
- fmt.Printf("路径 (path): %s\n", data.Path)
- fmt.Printf("文件名 (fileName): %s\n", data.FileName)
- fmt.Println("==========================")
- // 根据type执行不同操作
- if data.Type == "openFile" {
- // 在新goroutine中执行窗口操作,避免阻塞HTTP响应
- go func() {
- findAndOperateWindow("打开", data.Path, data.FileName)
- }()
- // 返回响应
- w.Header().Set("Content-Type", "application/json")
- response := map[string]interface{}{
- "status": "processing",
- "message": "正在执行窗口操作",
- "data": data,
- }
- json.NewEncoder(w).Encode(response)
- return
- }
- // 返回成功响应
- w.Header().Set("Content-Type", "application/json")
- response := map[string]interface{}{
- "status": "success",
- "message": "数据接收成功",
- "data": data,
- }
- json.NewEncoder(w).Encode(response)
- }
- func main() {
- fmt.Println("窗口操作服务启动...")
- fmt.Println("注意:某些窗口操作可能需要管理员权限")
- fmt.Println("如果需要,请以管理员身份运行此程序")
- fmt.Println()
- // 设置处理POST请求的路由
- http.HandleFunc("/", handlePostRequest)
- // 设置服务器监听8866端口
- port := ":8866"
- fmt.Printf("服务器正在监听端口 %s ...\n", port)
- fmt.Println("等待POST请求...")
- fmt.Println()
- // 启动HTTP服务器
- if err := http.ListenAndServe(port, nil); err != nil {
- log.Fatal("服务器启动失败:", err)
- }
- }
- // 前端JS请求示例
- // const myHeaders = new Headers();
- // myHeaders.append("Content-Type", "application/json");
- // const raw = JSON.stringify({
- // "type": "openFile",
- // "path": "C:\\Users\\mail\\Downloads",
- // "fileName": "128.png"
- // });
- // const requestOptions = {
- // method: "POST",
- // headers: myHeaders,
- // body: raw,
- // };
- // fetch("http://127.0.0.1:8866/", requestOptions)
- // .then((response) => response.text())
- // .then((result) => console.log(result))
- // .catch((error) => console.error(error));
|