是否可以使用 IntPtr 激活另一个程序中的选项卡? [英] Is it possible to activate a tab in another program using an IntPtr?
问题描述
提前致谢.
是否可以使用 IntPtr 激活另一个程序中的选项卡?如果是这样,如何?
Is it possible to activate a tab in another program using an IntPtr? If so, how?
SendKeys 不是一个选项.
SendKeys is not an option.
也许我需要的是钓鱼课.我已经筋疲力尽了 Google 和我的首席开发人员.我希望得到一个彻底的解决方案或建议以继续我的 Google 工作.
Perhaps what I need is a fishing lesson. I have exhausted Google and my lead developer. I would appreciate an outright solution OR a recommendation to continue my Google efforts.
基本流程是:
我将快捷方式图标拖到启动器
I drag a shortcut icon to the launcher
这会打开目标应用程序(Notepad++)并抓取 IntPtr 等
This opens the target application (Notepad++) and grabs IntPtr, etc.
我想以编程方式选择 Notepad++ 中的各种项目,例如编辑、编辑下的菜单项或文档选项卡.
I would like to programmatically select various items in Notepad++ such as Edit, menu items under Edit, or a doc tab.
我运行的基本代码是:
'斑点'
- 项目 1:项目的 IntPtr
- 第 2 项:itemsChild 的 IntPtr
- item 3:item 1 的控制文本
- item 4:是item 1的矩形参数
root 包含类似信息:
root contains similar info:
推荐答案
正如其他人指出的那样,执行此操作的标准方法是使用 用户界面自动化.Notepad++ 确实支持 UI 自动化(在某种程度上,因为它以某种方式由 UI 自动化 Windows 层自动提供).
As others pointed out, the standard way of doing this is to use UI Automation. Notepad++ does support UI Automation (to some extent, as it's somehow automatically provided by the UI Automation Windows layers).
这是一个示例 C# 控制台应用程序,它演示了以下场景(您需要引用 UIAutomationClient.dll、UIAutomationProvider.dll 和 UIAutomationTypes.dll):
Here is a sample C# console app that demonstrates the following sceanrio (you need to reference UIAutomationClient.dll, UIAutomationProvider.dll and UIAutomationTypes.dll):
1) 获取第一个正在运行的 notepad++ 进程(必须至少启动一个)
1) get the first running notepad++ process (you must start at least one)
2) 打开两个文件(注意notepad++中可能已经有其他打开的标签页)
2) open two files (note there may be already other opened tabs in notepad++)
3) 无限循环选择所有标签
3) selects all tabs in an infinite loop
class Program
{
static void Main(string[] args)
{
// this presumes notepad++ has been started somehow
Process process = Process.GetProcessesByName("notepad++").FirstOrDefault();
if (process == null)
{
Console.WriteLine("Cannot find any notepad++ process.");
return;
}
AutomateNpp(process.MainWindowHandle);
}
static void AutomateNpp(IntPtr handle)
{
// get main window handle
AutomationElement window = AutomationElement.FromHandle(handle);
// display the title
Console.WriteLine("Title: " + window.Current.Name);
// open two arbitrary files (change this!)
OpenFile(window, @"d:\my path\file1.txt");
OpenFile(window, @"d:\my path\file2.txt");
// selects all tabs in sequence for demo purposes
// note the user can interact with n++ (for example close tabs) while all this is working
while (true)
{
var tabs = GetTabsNames(window);
if (tabs.Count == 0)
{
Console.WriteLine("notepad++ process seems to have gone.");
return;
}
for (int i = 0; i < tabs.Count; i++)
{
Console.WriteLine("Selecting tab:" + tabs[i]);
SelectTab(window, tabs[i]);
Thread.Sleep(1000);
}
}
}
static IList<string> GetTabsNames(AutomationElement window)
{
List<string> list = new List<string>();
// get tab bar
var tab = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Tab));
if (tab != null)
{
foreach (var item in tab.FindAll(TreeScope.Children, PropertyCondition.TrueCondition).OfType<AutomationElement>())
{
list.Add(item.Current.Name);
}
}
return list;
}
static void SelectTab(AutomationElement window, string name)
{
// get tab bar
var tab = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Tab));
// get tab
var item = tab.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, name));
if (item == null)
{
Console.WriteLine("Tab item '" + name + "' has been closed.");
return;
}
// select it
((SelectionItemPattern)item.GetCurrentPattern(SelectionItemPattern.Pattern)).Select();
}
static void OpenFile(AutomationElement window, string filePath)
{
// get menu bar
var menu = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuBar));
// get the "file" menu
var fileMenu = menu.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "File"));
// open it
SafeExpand(fileMenu);
// get the new File menu that appears (this is quite specific to n++)
var subFileMenu = fileMenu.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Menu));
// get the "open" menu
var openMenu = subFileMenu.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Open..."));
// click it
((InvokePattern)openMenu.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
// get the new Open dialog (from root)
var openDialog = WaitForDialog(window);
// get the combobox
var cb = openDialog.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ComboBox));
// fill the filename
((ValuePattern)cb.GetCurrentPattern(ValuePattern.Pattern)).SetValue(filePath);
// get the open button
var openButton = openDialog.FindFirst(TreeScope.Children, new AndCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
new PropertyCondition(AutomationElement.NameProperty, "Open")));
// press it
((InvokePattern)openButton.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
}
static AutomationElement WaitForDialog(AutomationElement element)
{
// note: this should be improved for error checking (timeouts, etc.)
while(true)
{
var openDialog = element.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
if (openDialog != null)
return openDialog;
}
}
static void SafeExpand(AutomationElement element)
{
// for some reason, menus in np++ behave badly
while (true)
{
try
{
((ExpandCollapsePattern)element.GetCurrentPattern(ExpandCollapsePattern.Pattern)).Expand();
return;
}
catch
{
}
}
}
}
如果您想知道这是如何实现的,那么您必须阅读 UI 自动化.所有工具之母都称为检查:https://msdn.microsoft.com/图书馆/窗口/桌面/dd318521.aspx确保您获得的版本至少为 7.2.0.0.请注意,还有一个叫做 UISpy,但检查更好.
If you wonder how this has been made, then you must read about UI Automation. The mother of all tools is called Inspect: https://msdn.microsoft.com/library/windows/desktop/dd318521.aspx Make sure you get version at least 7.2.0.0. Note there is another one called UISpy but inspect is better.
请注意,不幸的是,notepad++ 选项卡文本内容 - 因为它基于自定义 scintilla 编辑器控件 - 不能正确支持自动化(我们无法轻松读取,我想我们必须为此使用 scintilla Windows 消息),但它可以添加到它(嘿,闪烁的家伙,如果你读到这个...... :).
Note, unfortunately, notepad++ tab text content - because it's based on the custom scintilla editor control - does not properly supports automation (we can't read from it easily, I suppose we'd have to use scintilla Windows messages for this), but it could be added to it (hey, scintilla guys, if you read this ... :).
这篇关于是否可以使用 IntPtr 激活另一个程序中的选项卡?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!