News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

LabView

Started by Biterider, February 29, 2024, 04:37:28 AM

Previous topic - Next topic

Biterider

Hi
I would like to ask if anyone has experience of interfacing with LabView.
The situation is as follows: I have a compiled .vi with a nice LabView GUI and I need to automatically set some parameters on it. I discovered the hard way that the controls you see aren't child windows you can communicate with by sending messages. They are simply drawn on a large client window and the application does all the necessary management to react as if it were a normal Windows binary, but it is not.
After a few tries, I decided on a more or less ugly way of doing it, like AutoIt, moving and clicking the mouse using win32 APIs and using SendInput to send characters to this main window.

Has anyone discovered or know of a better way?

Regards, Biterider

Greenhorn

I have no clue about LabVIEW, but this is not helpful ? User Interface Manager for LabVIEW

Otherwise, to ask the LabVIEW Community is maybe more helpful. Just found this: https://forums.ni.com/t5/LabVIEW/pass-parameters-to-main-VI/m-p/3994226
Kole Feut un Nordenwind gift en krusen Büdel un en lütten Pint.

Biterider

Thanks Greenhorn
The "User Interface Manager for LabVIEW" is a GUI design tool. It is not intended to interact with a running vi.
Before posting to the LabView forum, I wanted to ask here first  :biggrin:

Biterider

Biterider

Hi
There seems to be no decent way to interact with the LabView GUI without having the .vi sources and adding a server to interact with.

Just as a reference in case anyone faces the same challenge, the approach described in the first post works pretty well using the SendInput API. The main issue here is that the input sequence should not be disturbed by hardware inputs that would lead to wrong mouse positions and keystrokes landing in the wrong windows.

The solution is to create all the required inputs together and send them with a single SendInput call. 
You also need to call BlockInput to temporarily disable mouse and keyboard input. The disadvantage is that you need administrator rights if UAC is enabled.

You can fine-tune by restoring the foreground window/focus and mouse position after the action has been performed.

Reference code:
FillMousePosition macro Position:req
  mov [xbx].INPUT.type_, INPUT_MOUSE
  mov ecx, WRect.left
  add ecx, &Position&_X
  invoke MulDiv, ecx, 65535, ScreenSize.x
  mov [xbx].INPUT.mi.dx_, eax
  mov ecx, WRect.top
  add ecx, &Position&_Y
  invoke MulDiv, ecx, 65535, ScreenSize.y
  mov [xbx].INPUT.mi.dy, eax
  mov [xbx].INPUT.mi.mouseData, 0
  mov [xbx].INPUT.mi.dwFlags, MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE
  mov [xbx].INPUT.mi.time, 0
  mov [xbx].INPUT.mi.dwExtraInfo, 0
  inc dInputCounter
  add xbx, sizeof(INPUT)
endm

FillMouseAction macro Action1:req, Action2:req
  mov [xbx].INPUT.type_, INPUT_MOUSE
  mov [xbx].INPUT.mi.dx_, 0
  mov [xbx].INPUT.mi.dy, 0
  mov [xbx].INPUT.mi.mouseData, 0
  mov [xbx].INPUT.mi.dwFlags, Action1
  mov [xbx].INPUT.mi.time, 0
  mov [xbx].INPUT.mi.dwExtraInfo, 0
  inc dInputCounter
  add xbx, sizeof(INPUT)
  mov [xbx].INPUT.type_, INPUT_MOUSE
  mov [xbx].INPUT.mi.dx_, 0
  mov [xbx].INPUT.mi.dy, 0
  mov [xbx].INPUT.mi.mouseData, 0
  mov [xbx].INPUT.mi.dwFlags, Action2
  mov [xbx].INPUT.mi.time, 0
  mov [xbx].INPUT.mi.dwExtraInfo, 0
  inc dInputCounter
  add xbx, sizeof(INPUT)
endm

FillMouseLeftClick textequ <FillMouseAction MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP>

FillKeyStroke macro Char:req
  mov [xbx].INPUT.type_, INPUT_KEYBOARD
  mov [xbx].INPUT.ki.wVk, Char
  mov [xbx].INPUT.ki.wScan, 0
  mov [xbx].INPUT.ki.dwFlags, 0
  mov [xbx].INPUT.ki.time, 0
  mov [xbx].INPUT.ki.dwExtraInfo, 0
  inc dInputCounter
  add xbx, sizeof(INPUT)
  mov [xbx].INPUT.type_, INPUT_KEYBOARD
  mov [xbx].INPUT.ki.wVk, Char
  mov [xbx].INPUT.ki.wScan, 0
  mov [xbx].INPUT.ki.dwFlags, KEYEVENTF_KEYUP
  mov [xbx].INPUT.ki.time, 0
  mov [xbx].INPUT.ki.dwExtraInfo, 0
  inc dInputCounter
  add xbx, sizeof(INPUT)
endm

.code

SetRoomTemp proc uses xbx xdi, dRoomID:DWORD, pRoomTempA:PSTRINGA
  local hRTF:HWND, WRect:RECT, SMI[200]:INPUT, dInputCounter:DWORD
  local hLastForeWnd:HWND, LastCursorPos:POINT, ScreenSize:POINT

  invoke FindWindow, $OfsCStr("LVDChild"), $OfsCStr("RTF.vi")
  .if xax != 0
    mov hRTF, xax
    DbgStrA pRoomTempA
    invoke GetSystemMetrics, SM_CXSCREEN
    mov ScreenSize.x, eax
    invoke GetSystemMetrics, SM_CYSCREEN
    mov ScreenSize.y, eax
    invoke GetCursorPos, addr LastCursorPos
    mov hLastForeWnd, $invoke(GetForegroundWindow)
    invoke BlockInput, TRUE                             ;Lock input from physical Mouse & Keyboard
                                                        ;Requires admin rights!
    invoke SetForegroundWindow, hRTF
    invoke GetWindowRect, hRTF, addr WRect

    ;Select Testroom
    mov dInputCounter, 0                                ;Reset structure offset counter
    lea xbx, [SMI]
    FillMousePosition ROOM_SELECTOR                     ;Move Mouse
    FillMouseLeftClick                                  ;Left-Click
    FillKeyStroke VK_HOME                               ;HOME keystroke
    mov edi, dRoomID                                    ;n-1 VK_DOWN keystrokes
    dec edi
    .while !ZERO?
      FillKeyStroke VK_DOWN                             ;DOWN keystroke
      dec edi
    .endw
    FillKeyStroke VK_RETURN                             ;ENTER keystroke

    ;Select Rooms Tab
    FillMousePosition ROOMS_TAB                         ;Move Mouse
    FillMouseLeftClick                                  ;Left-Click

    ;Select Selected Room Tab
    FillMousePosition ROOM_SELECTED                     ;Move Mouse
    FillMouseLeftClick                                  ;Left-Click

    ;Set Room Temperature
    FillMousePosition ROOM_TEMP                         ;Move Mouse
    FillMouseLeftClick                                  ;Left-Click
    repeat 7                                            ;7 BACK-Keystrokes
      FillKeyStroke VK_BACK                             ;BACK keystroke
    endm
    mov xdi, pRoomTempA
    .while TRUE
      movzx eax, BYTE ptr [xdi]
      .break .if al == 0
      .if al == "."
        mov eax, VK_DECIMAL
      .endif
      FillKeyStroke ax                                  ;Digit/point keystroke
      inc xdi
    .endw

    ;Send RETURN Keystroke
    FillKeyStroke VK_RETURN                             ;ENTER keystroke
    invoke SendInput, dInputCounter, addr SMI, sizeof(INPUT)  ;Send all INPUTs at once

    ;Housekeeping
    invoke SetForegroundWindow, hLastForeWnd
    invoke SetCursorPos, LastCursorPos.x, LastCursorPos.y
    invoke BlockInput, FALSE                            ;Restore input from Mouse & Keyboard
    mov eax, TRUE
  .else
    DbgText "Window not Found"
  .endif
  ret
SetRoomTemp endp

Biterider

Greenhorn

Nice. AutoIt in Assembly.  :thumbsup:  :cool:
Kole Feut un Nordenwind gift en krusen Büdel un en lütten Pint.