10-09-2024 08:07 PM
Is there a way we can detect keyboard strokes from LabVIEW through a dynamic event?
The idea is to trigger an event whenever the user hits "LWIN + F" for example.
The keyboard strokes can be anywhere in windows, it could be on another application, not only on the LabVIEW application or controls.
10-10-2024 12:01 AM
I think Initialize Keyboard/Acquire Input Data should be helpful for you:
10-10-2024 12:49 AM
How do I register this as a user event?
This is what I have so far but it doesn't work.
10-10-2024 01:16 AM - edited 10-10-2024 01:18 AM
@Sable wrote:
How do I register this as a user event?
You can't do it directly. You have to run a polling loop to monitor the keyboard state and you can generate a user event whenever that array changes. This loop can be in a subVI, but then you also need a way to stop it.
Edit: this refers specifically to these VIs. Windows does have hooks for keyboard events, but I don't think you can write the code to intercept those directly in LV, at least not as a system-wide hook.
10-10-2024 01:46 AM
@tst wrote:
Edit: this refers specifically to these VIs. Windows does have hooks for keyboard events, but I don't think you can write the code to intercept those directly in LV, at least not as a system-wide hook.
One could but that requires external C code in a DLL. It could be a feature in the underlaying lvinput.dll but that DLL is old, and quite likely nobody at NI feels any temptation to touch the source code for that with a 10 foot pole. And if someone does feel like digging in there he would not be allowed to spend any time on that. Such a feature costs a lot of time, to get acquainted with the ancient code in it, to understand the exact troubles involved, to modify the code, add VI wrappers, test, crash, test, crash and test again. And finally update the whole documentation about these VIs. This easily can turn out to be a several man month project and for what? To let a few users avoid having to create a poll loop in their application! Any product manager will shoot down this idea immediately unless there is a very significant commercial gain to be had. Anybody thinks there will be even one single additional LabVIEW user because of that?
10-10-2024 04:41 AM - edited 10-10-2024 05:28 AM
@rolfk wrote:
@tst wrote:
Edit: this refers specifically to these VIs. Windows does have hooks for keyboard events, but I don't think you can write the code to intercept those directly in LV, at least not as a system-wide hook.
One could but that requires external C code in a DLL. ...
Well ,the "hardcore" way may looks like this (very quick and very dirty):
The C code for DLL:
//==============================================================================
//
// Title: DLLHook
// Purpose: Traverse Hot Keys to LabVIEW App via User Event.
//
// Created on: 10.10.2024 by AD.
// https://stackoverflow.com/questions/29734263/creating-global-keyboard-hook
//==============================================================================
#include <windows.h>
#include <stdio.h>
#include <utility.h>
#include "DLLHook.h"
HHOOK hKeyboardHook;
LVUserEventRef *lvEvent;
HANDLE hThread;
DWORD dwThread;
__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam)
{
DWORD LWIN_key = 0;
DWORD RWIN_key = 0;
int hotkey = -1;
if ((nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN))) {
KBDLLHOOKSTRUCT hooked_key = *((KBDLLHOOKSTRUCT*)lParam);
DWORD dwMsg = 1;
dwMsg += hooked_key.scanCode << 16;
dwMsg += hooked_key.flags << 24;
char lpszKeyName[1024] = {0};
GetKeyNameText(dwMsg, (lpszKeyName + 1), 0xFF) + 1;
int key = hooked_key.vkCode;
LWIN_key = GetAsyncKeyState(VK_LWIN);
RWIN_key = GetAsyncKeyState(VK_RWIN);
// Uncomment to see all key presses in DebugView:
// char buf[256];
// sprintf(buf, "Keycode = %c\n", key); OutputDebugStringA(buf);
if (LWIN_key !=0 && (key == 'f' || key == 'F') ) {
hotkey = 0; LWIN_key = 0;
}
if (RWIN_key !=0 && (key == 'f' || key == 'F') ) {
hotkey = 1; RWIN_key = 0;
}
if (hotkey >= 0 && lvEvent) PostLVUserEvent(*lvEvent, (void *)&hotkey); //Fire LV Event
}
return CallNextHookEx(hKeyboardHook, nCode,wParam,lParam);
}
void MessageLoop()
{
MSG message;
while (GetMessage (&message,NULL,0,0)) {
TranslateMessage (&message);
DispatchMessage (&message);
}
}
DWORD WINAPI my_HotKey(LPVOID lpParm)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
if (!hInstance) hInstance = LoadLibrary ((LPCSTR) lpParm);
if (!hInstance) return 1;
hKeyboardHook = SetWindowsHookEx (WH_KEYBOARD_LL, (HOOKPROC)KeyboardEvent, hInstance, 0);
MessageLoop();
UnhookWindowsHookEx(hKeyboardHook);
return 0;
}
//==============================================================================
// Exported function
//
int RegisterHook(LVUserEventRef *LVevent)
{
lvEvent = LVevent;
return 0;
}
//==============================================================================
// DLL main entry-point functions
//
int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (InitCVIRTE (hinstDLL, 0, 0) == 0)
return 0; /* out of memory */
if (!hThread) hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)my_HotKey, NULL, 0, &dwThread);
OutputDebugStringA("Hook attached");
break;
case DLL_PROCESS_DETACH:
PostQuitMessage(0);
if (hThread){
TerminateThread(hThread, 0);
CloseHandle(hThread);
hThread = 0;
}
CloseCVIRTE ();
OutputDebugStringA("Hook detached");
break;
}
return 1;
}
Block Diagram:
and works, also when focus not on LabVIEW's Front Panel:
But I'll not take any responsibilities for crashes or "side effects", use on own risk (I did this exercise long long time ago in the past, but unable to found 100% working solution).
Full source in the attachment, the DLL was built with latest NI CVI (could be easily ported to MSVC), the LabVIEW code downgraded to 2018, tested with x64 (2024Q3), should work in theory also with 32-bit (but wasn't tested).
10-10-2024 05:36 AM
This looks promising...do you mind to downgrade the LabVIEW code to 2013?
10-10-2024 05:44 AM
@Sable wrote:
This looks promising...do you mind to downgrade the LabVIEW code to 2013?
Here saved for LabVIEW 2013:
10-10-2024 07:01 AM
Do you know what does this error mean?
10-10-2024 07:13 AM
@Sable wrote:
Do you know what does this error mean?
Try to download and install latest CVI Run-Time 2020:
LabWindows/CVI Runtime Download
If this will not help, then I can recompile DLL using Visual Studio 2022 instead of NI CVI 2020.