December 2, 201015 yr Commercial Member Most of you are probably aware that you can trap FS9/FSX events via an EventHandler, like this:void FSAPI EventHandler (ID32 event, UINT32 evdata, PVOID userdata) { // FS2CREW PAUSE (EVENTS AND AUDIO) if (event == KEY_PAUSE_TOGGLE) { Paused = !Paused; FS2_Audio_PauseEngine( Paused ) ; }}What I want to do, however, is use this same system to know if the user is "Pushing and Holding" a joystick/keyboard button, not just pressing it once like what happens in the Pause example above.The closest Event that I could use that I found is KEY_BRAKES.So basically if the user holds down the button assigned to the brakes, then my "isButtonHeldDown" variable will be be true.When the user releases the brakes, then "isButtonHeldDown" variable becomes false.But obviously I can't use brakes for my push and hold key because it'll cause problems when the user is taxiing.Clear as mud :( Can anyone think of a better KEY_EVENT that I could use so I can determine when the user is "Pushing and Holding" his joystick/keyboard button? Cheers, B. York FS2Crew Web Site / FS2Crew Facebook Page / FS2Crew Discord
December 4, 201015 yr Commercial Member Hi BryanI've had a think about this but I can't help. It seems that you need to intercept a keypress rather than an event and we all know what FS9 and FSX think of the keyboard.-Dai
December 5, 201015 yr Hi BryanI've had a think about this but I can't help. It seems that you need to intercept a keypress rather than an event and we all know what FS9 and FSX think of the keyboard.-DaiKnowing next to nothing about how FS9.FSX handles the keyboard, would directly polling the keyboard inside a loop help?#include <windows.h>unsigned char Keys[256];char State; // Start of loop // Get keyboard state if (GetKeyboardState(Keys)) { // Check statue of Esc key as an example if (Keys[VK_ESCAPE] & 0x80) State = 'D'; else State = 'U'; } // End of loop EDIT: Code edited to make general C Gerry Howard
December 6, 201015 yr Commercial Member No... it won't work.DirectX has total control of the keyboard once FS is up and running. It doesn't share it as long as FS's window has focus. Ed Wilson Mindstar AviationMy Playland - I69
December 6, 201015 yr No... it won't work.DirectX has total control of the keyboard once FS is up and running. It doesn't share it as long as FS's window has focus.But it does work.I modified the fuel gauge that comes with the SDKs as shown in the snippet. I used the delete key because it was the first unassigned key I found. I also increased the needle's MAX_DEG_PER_SEC in MAKE_NEEDLE to 180 to speed up the response. Pressing and holding the delete key causes the displayed fuel quantity to drop to zero instantly - releasing it causes it to increase back to the actual value instantly. Try it.FLOAT64 FSAPI fuel_needle_cb( PELEMENT_NEEDLE pelement ){FLOAT64 val = pelement->source_var.var_value.n; //************************ FOLLOWING LINE ADDED *************************** unsigned char Keys[256]; if (val > GAUGE_MAX_FUEL) val = GAUGE_MAX_FUEL;else if (val < GAUGE_MIN_FUEL) val = GAUGE_MIN_FUEL; // ******************** INSERTED CODE BEGINS ***************************** // Get keyboard state if (GetKeyboardState(Keys)) { // If delete key pressed set val = 0 if (Keys[VK_DELETE] & 0x80) val = 0.0; } // ********************* INSERTED CODE ENDS ******************************** return val;}//---------------------------------------------------------------------------// Create needle//---------------------------------------------------------------------------MAKE_NEEDLE(fuel_needle,BMP_FUEL_SMALL_NEEDLE,NULL,fuel_fail,IMAGE_USE_TRANSPARENCY|IMAGE_USE_ERASE|IMAGE_BILINEAR_COLOR,0,150, 150,6, 12,TOTAL_FUEL_QUANTITY_GALLONS,fuel_needle_cb,fuel_nonlinearity, // **************** DEGREES/SEC INCREASED to 180 FROM 6 *******************180 ) Gerry Howard
December 7, 201015 yr Commercial Member I used the delete key because it was the first unassigned key I found.That's the catch - the key has to be unassigned. FSX allows you to capture keys for a gauge - inside the gauge code - but FS9 just doesn't. As soon as you select an assigned key you get the keypress but the assigned action also takes place. I spent hours with DirectInput inside FS9 trying to override assigned key actions - failed - and realised that in general the same was likely to happen in FSX. Someone can tell me different because I haven't done the same testing on FSX.-Dai
December 7, 201015 yr That's the catch - the key has to be unassigned. FSX allows you to capture keys for a gauge - inside the gauge code - but FS9 just doesn't. As soon as you select an assigned key you get the keypress but the assigned action also takes place. I spent hours with DirectInput inside FS9 trying to override assigned key actions - failed - and realised that in general the same was likely to happen in FSX. Someone can tell me different because I haven't done the same testing on FSX.-DaiWe may be at cross purposes but in FSX (all I have) if the key is assigned the action associated with that key takes place as well as the specific one in the gauge. I haven't looked into how rhe assigned action can be supressed from within a gauge if that's what's needed. Gerry Howard
December 7, 201015 yr Before I rush off in (totally) the wrong direction, did you try a hook? Gerry Howard
December 7, 201015 yr Commercial Member We're not at cross-purposes - you've found the same problem that I did. No, I didn't try a hook and I didn't try subclassing either; but I couldn't see the latter working anyway.-Dai
December 9, 201015 yr Most of you are probably aware that you can trap FS9/FSX events via an EventHandler, like this:void FSAPI EventHandler (ID32 event, UINT32 evdata, PVOID userdata) { // FS2CREW PAUSE (EVENTS AND AUDIO) if (event == KEY_PAUSE_TOGGLE) { Paused = !Paused; FS2_Audio_PauseEngine( Paused ) ; }}What I want to do, however, is use this same system to know if the user is "Pushing and Holding" a joystick/keyboard button, not just pressing it once like what happens in the Pause example above.The closest Event that I could use that I found is KEY_BRAKES.So basically if the user holds down the button assigned to the brakes, then my "isButtonHeldDown" variable will be be true.When the user releases the brakes, then "isButtonHeldDown" variable becomes false.But obviously I can't use brakes for my push and hold key because it'll cause problems when the user is taxiing.Clear as mud :( Can anyone think of a better KEY_EVENT that I could use so I can determine when the user is "Pushing and Holding" his joystick/keyboard button? Cheers,Hi,I can only address this from an XML-coded gauge perspective :( , but if it can be solved in XML I assume it can be done the same way in a C/C++ coded gauge as well.I suggest you have a look on how I solved a simular problem for a cannon-trigger (single trigger vs. push&hold) using the CarbHeat toggle event.File rcbsc-20.zip here in the library..Based on timing of course, of keyboard key repetition time or set controller button repetition time.As far as I can tell, the only difference between FS9 and FSX wrt. OnEvent coding (= detecting if a certain Event is given, without suppressing the execution of the Event) and OnKey coding (= true "interception" of a specific keystroke), is the following:- In FS9, OnEvent works always once the gauge is loaded.- In FSX, OnEVent works only if the window in which the gauge is defined, has focus (== is visible)- In both FS9 and FSX, OnKey works only if the window in which the gauge is defined, has focus.Where applicable, I bypass this "has focus" constraint by defining a gauge, that uses such OnEvent of OnKey code, in a transparant 2D-panel window that I keep "forced open", using Doug Dawson's WindowStatus gauge to determine the "open/closed" status of a window (with the window-ident as reference).Hope that helps .....Cheers, Rob
December 9, 201015 yr I've managed to intercept key messages so that they are acted on by a gauge but not passed onto Flight Simulator. I used the same simple fuel gauge mentioned in my previous post. For testing, I arranged for it to respond to the Q-key which toggles the sound on and off on my FSX setup. Pressing and holding the Q-key causes the displayed fuel quantity to drop to zero instantly - releasing it causes it to increase back to the actual value instantly but doesn't affect the sound.I used the FSX module_int() and module_deinit() functions to create and release a low-level keyboard hook respectively and added a callback function. These are shown in the following snippet together with the additional variables needed. All this appears in the file before the line:int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) //---------------------------------------------------------------------------// ************ ADDITIONAL CODE FOR HOOK BEGINS HERE ***********************//---------------------------------------------------------------------------// Variables for hookHHOOK MyHook;unsigned Q_KeyDown;// Callback function for hookLRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); //---------------------------------------------------------------------------// FS initialisation function//---------------------------------------------------------------------------void FSAPI module_init(void){// Create hook // NOTE: Low level hook needs a handle to a module even though it doesn't// then use it! LoadLibrary("user32.dll") provides one. user32.dll is generally// availableMyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, LoadLibrary("user32.dll"), 0);};//---------------------------------------------------------------------------// FS deinitialisation function//---------------------------------------------------------------------------void FSAPI module_deinit(void){// Release hookUnhookWindowsHookEx(MyHook);};//---------------------------------------------------------------------------// Keyboard callback procedure//---------------------------------------------------------------------------LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {PKBDLLHOOKSTRUCT hookstruct;hookstruct = (PKBDLLHOOKSTRUCT) lParam;// Ignore Q key (VK code 0x51)if(hookstruct->vkCode == 0x51) { if (wParam == WM_KEYDOWN) Q_KeyDown = 1; if (wParam == WM_KEYUP) Q_KeyDown = 0; return 1; }else return CallNextHookEx(NULL, nCode, wParam, lParam);}//---------------------------------------------------------------------------// ************ ADDITIONAL CODE FOR HOOK ENDS HERE ************************//--------------------------------------------------------------------------- The change to the function FLOAT64 FSAPI fuel_needle_cb( PELEMENT_NEEDLE pelement ) is even simpler than before FLOAT64 FSAPI fuel_needle_cb( PELEMENT_NEEDLE pelement ) { FLOAT64 val = pelement->source_var.var_value.n; if (val > GAUGE_MAX_FUEL) val = GAUGE_MAX_FUEL; else if (val < GAUGE_MIN_FUEL) val = GAUGE_MIN_FUEL; //---------------------------------------------------------------------------// ********************* ADDITIONAL CODE BEGINS HERE ************************//---------------------------------------------------------------------------// If hooked key pressed set val = 0 if (Q_KeyDown) { val = 0.0; } //---------------------------------------------------------------------------// ********************** ADDITIONAL CODE ENDS HERE *************************//--------------------------------------------------------------------------- return val; } It's also necessary to add the following line at the top of that file extern unsigned Q_KeyDown; I've tested this using the default C172 on FSX + Acceleration running on XP Professional SP3. One snag is that while FSX is running, the Q-key in any other application is intercepted and so that other applicaton doesn't respond to it either. In principle, this approach should be able to handle multiple keys by adding to the callback function and providing additional variables corresponding to Q_KeyDown. Gerry Howard
December 9, 201015 yr Thanks mgh for the snippet. Will look into it as soon as I can, sounds very interesting! :(
December 10, 201015 yr I hope I've now fixed the snag so that the Q_key is not intercepted in other applications. It now gets the process ID on initialisation which is FS. The callback function now gets the current process ID every time it's called and only intercepts the key if the two process IDs are the same.I've only tested it by having Notepad open at the same time as FSX so any feedback would be welcome. The changes in the snippet are marked by - NEW: //---------------------------------------------------------------------------// ************ ADDITIONAL CODE FOR HOOK BEGINS HERE ***********************//---------------------------------------------------------------------------// Variables for hookHHOOK MyHook;unsigned Q_KeyDown;// Handles of windows - NEWHWND CurrentWindow;HWND InitialWindow;// ID's of processes - NEW DWORD CurrentProcess;DWORD InitialProcess;// Callback function for hookLRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); //---------------------------------------------------------------------------// FS initialisation function//---------------------------------------------------------------------------void FSAPI module_init(void){// Create hook // NOTE: Low level hook needs a handle to a module even though it doesn't// then use it! LoadLibrary("user32.dll") provides one. user32.dll is generally// availableMyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, LoadLibrary("user32.dll"), 0); // Get process ID when hook is set (ie FS) - NEWInitialWindow = GetForegroundWindow();GetWindowThreadProcessId(InitialWindow, &InitialProcess); };//---------------------------------------------------------------------------// FS deinitialisation function//---------------------------------------------------------------------------void FSAPI module_deinit(void){// Release hookUnhookWindowsHookEx(MyHook);};//---------------------------------------------------------------------------// Keyboard callback procedure//---------------------------------------------------------------------------LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {PKBDLLHOOKSTRUCT hookstruct;hookstruct = (PKBDLLHOOKSTRUCT) lParam;// Get process ID of calling process - NEWCurrentWindow = GetForegroundWindow();GetWindowThreadProcessId(CurrentWindow, &CurrentProcess); // Only intercept if from original (FS) process - NEWif (CurrentProcess == InitialProcess) { // Ignore Q key if(hookstruct->vkCode == 0x51) { if (wParam == WM_KEYDOWN) Q_KeyDown = 1; if (wParam == WM_KEYUP) Q_KeyDown = 0; return 1; } else return CallNextHookEx(NULL, nCode, wParam, lParam); } else return CallNextHookEx(NULL, nCode, wParam, lParam); }//---------------------------------------------------------------------------// ************ ADDITIONAL CODE FOR HOOK ENDS HERE ************************//--------------------------------------------------------------------------- Gerry Howard
December 12, 201015 yr Author Commercial Member Hi,I can only address this from an XML-coded gauge perspective :( , but if it can be solved in XML I assume it can be done the same way in a C/C++ coded gauge as well.I suggest you have a look on how I solved a simular problem for a cannon-trigger (single trigger vs. push&hold) using the CarbHeat toggle event.File rcbsc-20.zip here in the library..Based on timing of course, of keyboard key repetition time or set controller button repetition time.As far as I can tell, the only difference between FS9 and FSX wrt. OnEvent coding (= detecting if a certain Event is given, without suppressing the execution of the Event) and OnKey coding (= true "interception" of a specific keystroke), is the following:- In FS9, OnEvent works always once the gauge is loaded.- In FSX, OnEVent works only if the window in which the gauge is defined, has focus (== is visible)- In both FS9 and FSX, OnKey works only if the window in which the gauge is defined, has focus.Where applicable, I bypass this "has focus" constraint by defining a gauge, that uses such OnEvent of OnKey code, in a transparant 2D-panel window that I keep "forced open", using Doug Dawson's WindowStatus gauge to determine the "open/closed" status of a window (with the window-ident as reference).Hope that helps .....Cheers, RobThanks Rob, I'll check that out :Big Grin:I'm wondering if when you 'push and hold' the trigger, is the 'push and hold' value always 'true' in a totally unbroken way? Or is 'true' for, say, a second, then it's false for a fraction of second after 'repeat' runs its course, then it goes back to 'true'.I'm curious because what I need is a 'clean' totally uninterrupted, even for a micro second, value for push to hold.Clear as mud? B. York FS2Crew Web Site / FS2Crew Facebook Page / FS2Crew Discord
Create an account or sign in to comment