基于C#实现FL Studio 20的UI自动化适配方案及GUI技术问询
FL Studio's GUI Technology
You’re right that FL Studio is built with Delphi, but the critical detail here is: it uses heavily customized Delphi VCL (Visual Component Library) controls. Image-Line modified standard VCL components extensively to create FL’s unique, skinnable interface. This customization means most interactive elements don’t expose the standard accessibility properties that tools like TestStack.White rely on—which is why you can only detect container controls, not individual clickable buttons or elements.
Better Automation Frameworks for Custom Delphi UIs
Since TestStack.White struggles with FL’s non-standard controls, these tools are better suited for your use case:
- AutoIt: A scripting language built specifically for Windows automation, ideal for handling custom controls. It can target windows by title, control class names, or even use image recognition to locate elements. You can write AutoIt scripts and call them from your C# app, or compile scripts to standalone EXEs.
- SikuliX: Uses visual image recognition to find UI elements—you capture screenshots of buttons/controls, and SikuliX locates them on screen regardless of resolution (as long as UI scaling stays consistent). It has Python/Java APIs, and you can integrate it with C# via interop or process calls.
- Windows API via P/Invoke: Since FL uses VCL, you can directly interact with control handles (HWND) using Windows API functions like
FindWindowExandSendMessage. This requires basic knowledge of Delphi VCL internals, but it’s the most precise method. You can call these APIs from C# using P/Invoke to send clicks or commands directly to controls without relying on mouse position. - WinAppDriver: While designed for UWP apps, it can work with some Win32 apps that support the UI Automation Provider. It’s worth testing as a more modern alternative to TestStack.White, though it may still have limitations with FL’s deeply customized controls.
Improving Your Current Offset Click Method
If you want to stick with C# and TestStack.White for now, you can make your click position resolution-independent by using relative sizing instead of fixed pixel offsets:
TestStack.White.Application application = TestStack.White.Application.Launch(@"C:\Program Files (x86)\Image-Line\FL Studio 20\FL.exe"); var window = application.GetWindow("FL Studio 20", InitializeOption.NoCache); UIItemCollection coll = window.Items; Panel pianoRollPanel = null; foreach (UIItem item in coll) { if (item.Name.Contains("Piano roll")) { var panel = item as Panel; if (panel?.Items.Count == 0) { pianoRollPanel = panel; break; } } } if (pianoRollPanel != null) { window.Focus(); var mouse = window.Mouse; // Calculate click position as a percentage of the panel's size (e.g., 5% from top-left) int relativeX = (int)(pianoRollPanel.Bounds.Width * 0.05); int relativeY = (int)(pianoRollPanel.Bounds.Height * 0.05); Point clickPoint = new Point( pianoRollPanel.Location.X + relativeX, pianoRollPanel.Location.Y + relativeY ); mouse.Click(clickPoint); }
This approach scales the click position with the panel’s dimensions instead of tying it to fixed pixels, making it more robust across different resolutions or window sizes.
内容的提问来源于stack exchange,提问作者Kevin Mueller

