API pour utiliser l'onglet "edition textuel" du tableau de chargement /API for using the "text edition" tab of the loading table

API pour utiliser l'onglet "edition textuel" du tableau de chargement /API for using the "text edition" tab of the loading table

danielroure2267
Enthusiast Enthusiast
1,058 Views
4 Replies
Message 1 of 5

API pour utiliser l'onglet "edition textuel" du tableau de chargement /API for using the "text edition" tab of the loading table

danielroure2267
Enthusiast
Enthusiast

bonjour, je souhaite pouvoir rentrer à partir de l'API des lignes de code dans l'"édition textuelle" du tableau de chargement pour rentrer directement des charges du type : exemple charge nodale

      1:cas n°1 / nodal force / 5 /  fx= 10 'test1
ainsi on peut définir une charge  avec une opération et un texte en memo

est ce possible ? si oui par quelle objet?

cordialement Daniel

 

hello, I would like to be able to use the API to enter lines of code in the "text edition" of the load table to enter loads directly, such as: example nodal load

1:case n°1 / nodal force / 5 / fx= 10 'test1
so you can define a load with an operation and a text memo

is this possible? if so, by which object?

Sincerely Daniel

0 Likes
Accepted solutions (2)
1,059 Views
4 Replies
Replies (4)
Message 2 of 5

Stephane.kapetanovic
Mentor
Mentor
Accepted solution

hi @danielroure2267 

Your idea is "feasible" using user32.dll and kernel32.dll by locating the “Loads” window among the active applications.
However, all these copy and paste operations are not native to the Autodesk API but instead rely on Windows level functions.
You won’t find assistance for this here, you’ll need to look for guidance on other forums.

Video tutorial of the PasteCells method

(view in My Videos)

For once, here’s a method to copy loads (using the GetLoads method) to the clipboard and paste them into the active load table according to the per-cell mode.

Naturally, this approach can be applied to any other type of table as well.

public static void PasteFromClipboardIntoActiveWindow() { var r = new RobotApplication();
    string tbName = "Loads", wName = $"Autodesk Robot Structural Analysis Professional 20{r.Version} - [{tbName}]";
    foreach (var method in Enum.GetValues<WindowMngr.PasteMethod>()) {
        var tb = r.Project.ViewMngr.CreateTable(I_TT_LOADS, I_TDT_DEFAULT); tb.Window.Caption = tbName;
        WriteLine(WindowMngr.Paste(wName, method) ? "TEST PASSED" : "TEST FAILED");
        tb.Window.SendMessage(0x10, 0, 0);
    }
}

The GetLoads method is shown here in a hard-coded form, but it can also be generated by other methods in your programs (mass calculation, sorting, selection, etc.).

using System.Text;
using System.Runtime.InteropServices;
using static System.Console;

internal class WindowMngr {
    [DllImport("user32.dll", SetLastError = true)] private static extern bool CloseClipboard();
    [DllImport("user32.dll", SetLastError = true)] private static extern bool EmptyClipboard();
    [DllImport("user32.dll", SetLastError = true)] private static extern bool OpenClipboard(IntPtr hWndNewOwner);
    [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GlobalUnlock(IntPtr hMem);
    [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
    [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
    [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GlobalLock(IntPtr hMem);
    [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GlobalFree(IntPtr hMem);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(string? lpClassName, string lpWindowName);
    [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")] private static extern bool IsIconic(IntPtr hWnd);
    [DllImport("user32.dll")] private static extern bool IsWindow(IntPtr hWnd);
    [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, IntPtr dwExtraInfo);
    [DllImport("user32.dll")] private static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
    [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)] private static extern bool BringWindowToTop(IntPtr hWnd);

    private const uint CF_UNICODETEXT = 13, GMEM_MOVEABLE = 0x0002, KEYEVENTF_KEYUP = 0x0002;
    private const byte VK_CONTROL = 0x11, VK_V = 0x56, VK_RETURN = 0x0D, VK_LEFT = 0x25, VK_DOWN = 0x28, VK_ESCAPE = 0x1B;
    private const int SW_RESTORE = 9;

    private static IntPtr _targetHwnd = IntPtr.Zero;
    private static bool SendKeyCombination(byte keyCode, int delay = 50) {
        if (!EnsureTargetWindowActive()) return false;
        keybd_event(VK_CONTROL, 0, 0, IntPtr.Zero);
        keybd_event(keyCode, 0, 0, IntPtr.Zero); Thread.Sleep(20);
        keybd_event(keyCode, 0, KEYEVENTF_KEYUP, IntPtr.Zero);
        keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, IntPtr.Zero); Thread.Sleep(delay);
        return true;
    }
    private static bool PressKey(byte keyCode, int delay = 50) {
        if (!EnsureTargetWindowActive()) return false;
        keybd_event(keyCode, 0, 0, IntPtr.Zero); Thread.Sleep(20);
        keybd_event(keyCode, 0, KEYEVENTF_KEYUP, IntPtr.Zero); Thread.Sleep(delay);
        return true;
    }
    private static bool CtrlDown(int delay = 50) => SendKeyCombination(VK_DOWN, delay);
    private static bool CtrlLeft(int delay = 50) => SendKeyCombination(VK_LEFT, delay);
    private static bool SendPaste(int delay = 50) => SendKeyCombination(VK_V, delay);
    private static bool PressEscape(int delay = 50) => PressKey(VK_ESCAPE, delay);

    public static string[] GetLoads() {
        return [
            "1;nodal force;1;0.0;0.0;2500.00;0.0;0.0;0.0;0.0;0.0;0.0;load 1",
            "1;uniform load;1;0.0;0.0;2000.00;global;projected;relative;0.0;0.0;0.0;0.0;0.0;load 2",
            "1;trapezoidal load (2p);1;0.0;0.0;0.0;1500.00;1.00;0.0;0.0;500.00;global;not project.;relative;0.0;0.0;0.0;load 3",
            "1;bar force;1;0.0;0.0;1750.00;0.0;0.0;0.0;0.40;global;relative;0.0;0.0;0.0;0.0;0.0;No node;load 4",
            "1;thermal load;1;0.0;0.0;30.00;load 5",
            "1;imp. displacement;1;0.0;0.0;0.01;0.0;0.0;0.0;load 6"
        ];
    }
    public static bool SetClipboardText(string text) {
        const int maxAttempts = 5, retryDelay = 250; int attempt = 0;
        while (attempt < maxAttempts) { attempt++;
            if (OpenClipboard(IntPtr.Zero)) {
                try { EmptyClipboard();
                    byte[] bytes = Encoding.Unicode.GetBytes(text + '\0');
                    IntPtr hGlobal = GlobalAlloc(GMEM_MOVEABLE, (UIntPtr)bytes.Length);
                    if (hGlobal == IntPtr.Zero) return false;

                    IntPtr pGlobal = GlobalLock(hGlobal);
                    Marshal.Copy(bytes, 0, pGlobal, bytes.Length); GlobalUnlock(hGlobal);

                    if (SetClipboardData(CF_UNICODETEXT, hGlobal) == IntPtr.Zero) {
                        WriteLine("Failed to set clipboard data"); GlobalFree(hGlobal); return false;
                    }
                    return true;
                } finally { CloseClipboard(); }
            } else { Thread.Sleep(retryDelay * attempt); }
        }
        WriteLine("Cannot open clipboard after multiple attempts"); return false;
    }
    public enum PasteMethod { ByCell, ByLine, EntireTable }
    public static bool Paste(string windowName, PasteMethod method = EntireTable) => Paste(windowName, GetLoads(), method);
    public static bool Paste(string windowName, string[] datas, PasteMethod method = EntireTable) {
        _targetHwnd = FindWindow(null, windowName);
        if (_targetHwnd == IntPtr.Zero) { WriteLine($"Window '{windowName}' not found"); return false; }
        Thread.Sleep(500); if (!CtrlDown() || !CtrlLeft() || !PressEscape()) return false;
        return method switch {
            ByCell => PasteCells(datas), ByLine => PasteLines(datas), EntireTable => PasteTable(datas),
            _ => PasteTable(datas)
        };
    }
    private static bool EnsureTargetWindowActive() {
        if (_targetHwnd == IntPtr.Zero) { WriteLine("No target window specified"); return false; }
        if (!IsWindow(_targetHwnd)) { WriteLine("Target window handle is no longer valid"); return false; }
        if (GetForegroundWindow() == _targetHwnd) return true;
        if (IsIconic(_targetHwnd)) ShowWindow(_targetHwnd, SW_RESTORE);
        foreach (var (method, delay) in new (Func<bool>, int)[] {
                (() => SetForegroundWindow(_targetHwnd), 80),
                (() => { BringWindowToTop(_targetHwnd); return true; }, 80),
                (() => { SwitchToThisWindow(_targetHwnd, true); return true; }, 100)}) {
            method(); Thread.Sleep(delay); if (GetForegroundWindow() == _targetHwnd) return true;
        }
        WriteLine("Warning: unable to bring target window to foreground"); return false;
    }
    public static bool Write(string Text) {
        if (!EnsureTargetWindowActive()) return false;
        if (!SetClipboardText(Text)) { WriteLine("Failed to set clipboard"); return false; }
        Thread.Sleep(250);
        for (int i = 0; i < 2; i++) { if (SendPaste()) { Thread.Sleep(125); return true; } Thread.Sleep(100); }
        WriteLine("Paste operation failed"); return false;
    }
}
    public static bool PasteCells(string[] datas) {
        for (int lineIndex = 0; lineIndex < datas.Length; lineIndex++) {
            string[] cells = datas[lineIndex].Split(';');
            for (int idx = 0; idx < cells.Length; idx++) if (!Write(cells[idx]) || !PressKey(VK_RETURN)) return false;
            if (lineIndex < datas.Length - 1) if (!CtrlLeft() || !PressKey(VK_DOWN)) return false;
        }
        WriteLine("\nAll cells pasted successfully"); return true;
    }

To ensure safe and correct use:

These functions are provided as an example for pasting a data table into a pre-configured load table. Windows keyboard emulation, the system clipboard, and Robot event handling operate asynchronously. The key sequences and timings used here are calibrated for a general demonstration context. The provided code may require adjustments to timings, batch sizes, or navigation keys. Therefore, it is recommended to use this code only if you fully understand how these sequences interact with the Windows message loop and the asynchronous clipboard, and can adapt it to your hardware and projects. Incorrect settings may result in incomplete copies, misaligned pastes, or unpredictable behavior.

Best Regards

Stéphane Kapetanovic

Did you find this post helpful? If it gave you one or more solutions,
don't forget to click the Accept Solution button and leave a < like !
EESignature
Message 3 of 5

danielroure2267
Enthusiast
Enthusiast

Thanks for you idea

0 Likes
Message 4 of 5

danielroure2267
Enthusiast
Enthusiast

I have a lot of lines to transfer and in this case the RSA processing takes a long time/ j'ai beaucoup de ligne à transférer et dans ce cas le traitement RSA est long

Thanks

0 Likes
Message 5 of 5

Stephane.kapetanovic
Mentor
Mentor
Accepted solution

Updated Message, Video, Code, and Security Notice

Stéphane Kapetanovic

Did you find this post helpful? If it gave you one or more solutions,
don't forget to click the Accept Solution button and leave a < like !
EESignature
0 Likes