You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#触发TradingView的Alt+G打开日期跳转对话框?

问题:TradingView页面无法触发Alt+G快捷键调出日期跳转对话框

我用C#编写了ChromeWrapper类,目标是打开TradingView页面后触发Alt+G快捷键调出日期跳转对话框。参考相关线程新增SendAltKey方法后,在Stack Overflow页面测试Tab、Enter等普通按键有效,但在TradingView中调用SendAltKey('G')和SendKeys.Send("%G")均无效,且页面无日期相关查询参数,求可行解决方案。

调用代码

ChromeWrapper chrome = new ChromeWrapper(@"https://stackoverflow.com");
Thread.Sleep(1000);
chrome.SendKey((char)9);// tab
chrome.SendKey((char)13);//enter

// 打开TradingView并调出日期跳转对话框,目前卡在这一步
chrome = new ChromeWrapper(@"https://www.tradingview.com/chart/?symbol=NASDAQ%3AMSFT");
Thread.Sleep(10000);
chrome.SendAltKey('G'); // 无效
SendKeys.Send("%G"); // 同样无效

ChromeWrapper类代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Meh
{
    public class ChromeWrapper
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        private static uint WM_KEYDOWN = 0x100, WM_KEYUP = 0x101;

        public Process chromeProcess;

        public ChromeWrapper(string url)
        {
            chromeProcess = new Process();
            chromeProcess.StartInfo = new ProcessStartInfo("chrome.exe", url);
            chromeProcess.StartInfo.UseShellExecute = true;
            chromeProcess.Start();
            Thread.Sleep(600);

            Process[] procsChrome = Process.GetProcessesByName("chrome");
            foreach (Process chrome in procsChrome)
            {
                if (chrome.MainWindowHandle == IntPtr.Zero)
                    continue;
                chromeProcess = chrome;
                return;
            }
        }

        public void SendKey(char key)
        {
            try
            {
                if (chromeProcess.MainWindowHandle != IntPtr.Zero)
                {
                    SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
                    Thread.Sleep(30);
                    SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYUP, (IntPtr)key, IntPtr.Zero);
                }
            }
            catch (Exception e)
            {
            }
        }

        public void SendAltKey(char key)
        {
            try
            {
                if (chromeProcess.MainWindowHandle != IntPtr.Zero)
                {
                    uint lparam = (0x01 << 28);
                    SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYDOWN, (IntPtr)key, (IntPtr) lparam);
                    Thread.Sleep(30); 
                    SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYUP, (IntPtr)key, (IntPtr) lparam);
                }
            }
            catch (Exception e)
            {
            }
        }
    }
}
解决方案

1. 改用SendInput模拟硬件级按键(推荐)

SendMessage是直接向顶层窗口发送消息,而TradingView这类现代网页应用的快捷键监听在浏览器渲染进程中,并非顶层窗口。改用SendInput模拟真实用户的硬件按键操作,兼容性更强:

首先在ChromeWrapper类中添加必要的结构体和DllImport:

[StructLayout(LayoutKind.Sequential)]
private struct INPUT
{
    public uint Type;
    public KEYBDINPUT Ki;
}

[StructLayout(LayoutKind.Sequential)]
private struct KEYBDINPUT
{
    public ushort Vk;
    public ushort Scan;
    public uint Flags;
    public uint Time;
    public IntPtr ExtraInfo;
}

[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

private const uint INPUT_KEYBOARD = 1;
private const uint KEYEVENTF_KEYUP = 0x0002;
private const ushort VK_MENU = 0x12; // Alt键虚拟键码

然后添加模拟Alt+G的方法:

public void SendAltGSimulated()
{
    if (chromeProcess.MainWindowHandle == IntPtr.Zero) return;

    // 先激活Chrome窗口,确保按键被正确接收
    SetForegroundWindow(chromeProcess.MainWindowHandle);
    Thread.Sleep(100);

    INPUT[] inputs = new INPUT[4];
    // 按下Alt
    inputs[0].Type = INPUT_KEYBOARD;
    inputs[0].Ki.Vk = VK_MENU;
    inputs[0].Ki.Scan = 0;
    inputs[0].Ki.Flags = 0;

    // 按下G
    inputs[1].Type = INPUT_KEYBOARD;
    inputs[1].Ki.Vk = (ushort)'G';
    inputs[1].Ki.Scan = 0;
    inputs[1].Ki.Flags = 0;

    // 松开G
    inputs[2].Type = INPUT_KEYBOARD;
    inputs[2].Ki.Vk = (ushort)'G';
    inputs[2].Ki.Scan = 0;
    inputs[2].Ki.Flags = KEYEVENTF_KEYUP;

    // 松开Alt
    inputs[3].Type = INPUT_KEYBOARD;
    inputs[3].Ki.Vk = VK_MENU;
    inputs[3].Ki.Scan = 0;
    inputs[3].Ki.Flags = KEYEVENTF_KEYUP;

    SendInput(4, inputs, Marshal.SizeOf(typeof(INPUT)));
}

2. 确保焦点在TradingView图表区域

TradingView的Alt+G快捷键需要焦点落在图表画布上,而非页面其他元素。可以先模拟鼠标点击图表中心位置(需结合SendInput模拟鼠标操作),再发送快捷键。

3. 替代方案:用Selenium直接操作前端DOM

如果模拟按键始终存在问题,改用Selenium WebDriver直接和TradingView的前端交互,稳定性更高:

  • 安装Selenium ChromeDriver依赖
  • 直接调用TradingView的JavaScript API触发日期跳转

示例代码:

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

var driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.tradingview.com/chart/?symbol=NASDAQ%3AMSFT");
Thread.Sleep(10000);

// 调用TradingView内置API调出日期跳转对话框
driver.ExecuteScript("chart.executeActionById('symbolSearch.gotoDate')");
// 后续可继续输入日期并确认

内容的提问来源于stack exchange,提问作者SeanK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:41:04