# 通达信自动登录：可用方法（已实测成功）

## 结论

**成功登录于 2026-09-14。** 窗口标题从 `通达信金融终端V7.73`（登录框）
变为 `通达信金融终端V7.73 - [行情报价-自选股]`（行情界面）即为登录成功。

## 关键坑（两个，都踩过）

### 坑 1：两个输入框的上下位置和控件 id 顺序相反

| 位置 | 坐标 | 控件 id | 用途 |
| --- | --- | --- | --- |
| **上方**（y≈407） | (594, 407) | **1058** | **账号** |
| **下方**（y≈451） | (594, 451) | **1443** | **密码** |

id 大的在**下面**。我第一次按 id 顺序填，结果把账号填进了密码框。

### 坑 2：前台锁 —— 不切前台，所有键盘输入都会进别的窗口

`SetForegroundWindow` 单独调用会被 Windows 前台锁拒绝（返回 True 但前台没变）。
必须**先发一个 ALT 键解锁**，再调 `SetForegroundWindow`：

```powershell
[System.Windows.Forms.SendKeys]::SendWait('%')   # 解锁前台锁
Start-Sleep -Milliseconds 250
[void][Y6]::BringWindowToTop($dlg)
[void][Y6]::SetForegroundWindow($dlg)
```

验证：`GetForegroundWindow()` 应等于登录框 hwnd。
（我曾因前台还是 Edge，把密码打进了 Edge，密码框始终为空。）

### 坑 3：`SafeEdit` 控件屏蔽读取，无法判断字段是否已填

- `WM_GETTEXT` / `WM_GETTEXTLENGTH` 对账号框和密码框**恒返回空/0**，
  即使框里确实有内容。所以**不能靠读数判断**，只能"盲填"。
- `WM_SETTEXT` 对这两个框也无效。
- 因此用户的判断是对的：框是空的。我早期误以为"控件不报告"而假设有密码，是错的。

## 可用操作序列（已成功）

```powershell
# 1. 定位登录框（每次调用前重新取句柄，句柄会变）
$dlg = FindWindow(pid, '通达信金融终端V7.73')

# 2. 解锁前台锁并切到登录框
SendKeys('%'); Start-Sleep -ms 250
BringWindowToTop($dlg); SetForegroundWindow($dlg); Start-Sleep -ms 600
# 校验：GetForegroundWindow() == $dlg

# 3. 上方框 = 账号：真实鼠标点击 + 键盘输入
Click(594, 407); Start-Sleep -ms 600
SendKeys('^a'); SendKeys('{DEL}')          # 清空
SendKeys('13812729838')

# 4. 下方框 = 密码
Click(594, 451); Start-Sleep -ms 600
SendKeys('^a'); SendKeys('{DEL}')
SendKeys('jinyifeng')

# 5. 登录按钮（自绘红底，id=1，IsWindowVisible=false）：
#    必须用真实鼠标点击，BM_CLICK / WM_LBUTTONDOWN 都无效
Click(620, 511)
```

`Click` 实现（真实硬件鼠标事件）：

```csharp
SetCursorPos(x,y); Thread.Sleep(150);
mouse_event(0x0002,0,0,0,IntPtr.Zero);   // LEFTDOWN
Thread.Sleep(70);
mouse_event(0x0004,0,0,0,IntPtr.Zero);   // LEFTUP
```

## 无效的手段（不要再试）

| 手段 | 结果 |
| --- | --- |
| `BM_CLICK` 点「登录」(id=1) | 无效 |
| `WM_LBUTTONDOWN/UP` 发到按钮 | 无效 |
| `WM_SETTEXT` 写账号/密码 | 无效 |
| `SendKeys`（未切前台时） | 输入进了其它窗口 |
| `WM_GETTEXT(LENGTH)` 判断是否已填 | 恒返回空/0，不可判断 |
| `AttachThreadInput` + `SetForegroundWindow`（不发 ALT） | 前台切换失败 |

显示器 1360×768、无 DPI 缩放，坐标可直接用。

## 登录后的设置状态

`C:\new_tdx64\T0002\user.ini`（**GBK 编码，改动必须用 `Encoding.GetEncoding(936)`**）：

```ini
TimeDown=1        # 启用「定时自动下载日线」
DownMin=1020      # 1020 分钟 = 17:00
DownAllABGp=1     # 下载所有A股类品种（已开启）
OnlyDownABGData=1 # 仅下载A股类数据（已开启）
```

`C:\new_tdx64\T0002\usercomm.ini`：

```ini
SAVEZH=1      # 记住账号
SavePass=1    # 记住密码
```

登录成功后 `user.ini` 仍为 22600 字节，中文条目正常，未再被改写。
