Welcome, Guest
Username: Password: Remember me
This public forum is meant for questions and discussions about Visual FoxPro
  • Page:
  • 1

TOPIC:

CapsLock(), InsMode() , NumLock() 11 Apr 2021 13:22 #17995

  • Karl-Heinz
  • Karl-Heinz's Avatar
  • Topic Author


  • Posts: 774
  • Guys,

    i'm looking at the mentioned VFP functions. The help description doesn' t give an answer, but after looking at some VFP sites it seems that these funcs change the global input state, and not the input state of the calling thread only. Is that correct ?

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 11 Apr 2021 17:55 #17997

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Karl-Heinz, the functions CAPSLOCK() and NUMLOCK() set the global state. As for the INSMODE() function, I assume "yes," also, but I'm not quite sure of that.

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 11 Apr 2021 22:26 #17998

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Hi Antonio,

    The insert mode is a special beast. Notepad ignores the setting and Winword seems to have its own on/off insert implementation. But it works in a VO/X# window if the edit control uses the OVERWRITE_ONKEY setting.

    The attached file is a XIDE viaef. When you look at the Keyboard.prg you'll see that most of the code is encapsulated in the internal class win32, and that GetKeyState() and SendInput() is used to toggle the Capslock, Insert or Num key. Currently there are two unused structures (winHardwareInput and winMouseInput ) included. i'll deactvate or remove them later. As long as the XIDE checkbox '[x] Define debug' is checked you can see in the console when a switch occurs. Later on, i'll also remove the '#ifdef DEBUG ... #endif' code.

    Don't be surprised how you have to leave the console window :-) , otherwise its not possible to run the app as a exe. I noticed that a simple 'wait' instead of the 'do while .. enddo' automatically quits the exe. This does not happen if all InsMode() calls are deactivated .... very strange.

    Give it a try and let me know how it goes.

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Last edit: by Karl-Heinz.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 08:32 #18000

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz
    I think the only relevant thread for these values is the UI Thread. So this should be set globally.
    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 10:05 #18007

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz,
    Is there a reason why you coded this to the Win32 API and did not use Control.isKeyLocked from System.Windows.Forms ?

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 13:43 #18010

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • robert wrote: Karl-Heinz,
    Is there a reason why you coded this to the Win32 API and did not use Control.isKeyLocked from System.Windows.Forms ?

    Robert

    because of the System.Windows.Forms dependency, so from my understanding that doesn t help in a console app ? i also looked at this option:

    USING System.Windows.Input
    
    // required Dll references:  Windowsbase , PresentationCore
    
    FUNCTION KeysTest() AS VOID 
    	
     // System.Windows.Input.xxx
    
     ? Keyboard.IsKeyToggled(Key.NumLock) 
     ? Keyboard.IsKeyToggled(Key.CapsLock)
     ? Keyboard.IsKeyToggled(Key.Insert)
     ? 
      
    RETURN
    

    When i get the time i'll take a closer look at the available options. Do you agree that both, windows form and console apps should be supported ?

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 13:51 #18011

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl Heinz,
    This is the (C#) code inside Control.IsKeyLocked
    public static bool IsKeyLocked(Keys keyVal)
    {
    	if (keyVal == Keys.Insert || keyVal == Keys.NumLock || keyVal == Keys.Capital || keyVal == Keys.Scroll)
    	{
    		int keyState = UnsafeNativeMethods.GetKeyState((int)keyVal);
    		if (keyVal == Keys.Insert || keyVal == Keys.Capital)
    		{
    			return (keyState & 1) != 0;
    		}
    		return (keyState & 0x8001) != 0;
    	}
    	throw new NotSupportedException(SR.GetString("ControlIsKeyLockedNumCapsScrollLockKeysSupportedOnly"));
    }

    I think it does exactly what you did to read the state. But it does NOT change the state.
    Maybe this code can be used to set the state:
    stackoverflow.com/questions/13623245/how...ff-the-caps-lock-key
    This does not need all the extra structures.

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 18:22 #18017

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Hi Robert,

    i'm aware of the keybd_event() function and it gives the same results as SendInput(). However, it is recommended to use SendInput() instead.

    docs.microsoft.com/en-us/windows/win32/a...-winuser-keybd_event

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 12 Apr 2021 20:18 #18018

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz,

    Ok, I see. In that case you may want to consider to replace the InputUnion in the winInput structure with just the winKeyboardInput structure, since you are not using the MouseInput and the HardwareInput. That will make the code a bit smaller and easier to understand.
    Of course you will have to a few dummy items to the structure because the MouseInput structure is larger (I think you would have to use 2 dummy LONG or DWORD items to get the same size).

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 13 Apr 2021 20:27 #18020

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Hi Robert;

    the modified class now looks like
    INTERNAL CLASS Win32  
    
    	CONST INTERNAL KEYEVENTF_KEYUP := 2 AS INT
    	CONST INTERNAL VK_INSERT := 45 AS INT
    	CONST INTERNAL VK_NUMLOCK := 144 AS INT
    	CONST INTERNAL VK_CAPITAL := 20 AS INT 
        	CONST INTERNAL TYPE_KEYBOARD := 1 AS INT
        
    		
    	[DllImport("user32.dll", SetLastError := TRUE)] ;
    	INTERNAL STATIC METHOD SendInput(nInputs AS DWORD , pInputs AS winInput[], cbSize AS LONG ) AS DWORD
    
    	[DllImport("user32.dll", SetLastError := TRUE)] ;
    	INTERNAL STATIC METHOD GetKeyState(nVirtkey AS INT) AS SHORTINT
    		
    	[StructLayout(LayoutKind.Sequential)];	
    	INTERNAL STRUCTURE winKeyboardInput2
    		INTERNAL wVk AS WORD 
    		INTERNAL wScan AS WORD
    		INTERNAL dwFlags AS DWORD
    		INTERNAL time AS DWORD
    		INTERNAL dwExtraInfo AS IntPtr
    		INTERNAL Dummy1 AS DWORD  // <-----
    		INTERNAL Dummy2 AS DWORD  // <-----		
    	END STRUCTURE 		
    
    	
    	[StructLayout(LayoutKind.Sequential)] ;
    	INTERNAL STRUCTURE winInput
    		INTERNAL Type AS DWORD
    		INTERNAL Input AS winKeyboardInput2 
    	END STRUCTURE 
    
    END CLASS 
    

    What's still missing are the names i should use:
    - name of the modified winKeyboardInput structure ? - currently winKeyboardInput2
    - name of the 2 new members ? - currently dummy1 and dummy2

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 14 Apr 2021 07:03 #18023

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Hi Robert,

    i finally added "XS" to the names of the two new members and the two modified structures. i think that signals that not the original structure declarations are used.

    INTERNAL CLASS Win32  
    
    	CONST INTERNAL KEYEVENTF_KEYUP := 2 AS INT
    	CONST INTERNAL VK_INSERT := 45 AS INT
    	CONST INTERNAL VK_NUMLOCK := 144 AS INT
    	CONST INTERNAL VK_CAPITAL := 20 AS INT 
        CONST INTERNAL TYPE_KEYBOARD := 1 AS INT
        
    		
    	[DllImport("user32.dll", SetLastError := TRUE)] ;
    	INTERNAL STATIC METHOD SendInput(nInputs AS DWORD , pInputs AS winInputXS[], cbSize AS LONG ) AS DWORD
    
    	[DllImport("user32.dll", SetLastError := TRUE)] ;
    	INTERNAL STATIC METHOD GetKeyState(nVirtkey AS INT) AS SHORTINT
    		
    	[StructLayout(LayoutKind.Sequential)];	
    	INTERNAL STRUCTURE winKeyboardInputXS
    		INTERNAL wVk AS WORD 
    		INTERNAL wScan AS WORD
    		INTERNAL dwFlags AS DWORD
    		INTERNAL time AS DWORD
    		INTERNAL dwExtraInfo AS IntPtr
    		INTERNAL Unused1XS AS DWORD
    		INTERNAL UnUsed2XS AS DWORD		
    	END STRUCTURE 		
    
    	
    	[StructLayout(LayoutKind.Sequential)] ;
    	INTERNAL STRUCTURE winInputXS
    		INTERNAL Type AS DWORD
    		INTERNAL Input AS winKeyboardInputXS 
    	END STRUCTURE 
    
    END CLASS 
    

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 14 Apr 2021 09:02 #18026

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz ,
    The naming is OK. Since these are internal structures there is very little change of naming conflicts anyway.
    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 14 Apr 2021 21:52 #18039

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Guys,

    in the attachment you find the latest VFPKeyboard.viaef
    ,
    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 15 Apr 2021 12:19 #18042

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz,

    I'll include this in the upcoming 2.8 release

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    CapsLock(), InsMode() , NumLock() 06 May 2021 15:56 #18351

    • Karl-Heinz
    • Karl-Heinz's Avatar
    • Topic Author


  • Posts: 774
  • Guys,

    Attached is a app that handles the insert key via a keyboard hook. To round things up, i implemented a local (app only) and a global keyboard hook. A global hook doesn't make much sense in this particular case, so it's added just to show the different behavior.

    The name of the attached app is still VFPKeyboard.viaef, but because i added a VO window with a sle to test the insert key, the app requires now the VO dialect.

    In the Start() method you can decide whether you want to install a local (app only) or a global keyboard hook. Just change the content of the logic var 'lUseGlobalHook' in the start() method. If a global hook is installed, switch to another app and press the insert key. When you look at the terminal window, you will see now a message that the insert key state has changed. This does not happen if a local (app only) keyboard hook is installed.

    BTW. I doubt that it's always possible to detect correctly at startup the current insert key state.

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Last edit: by Karl-Heinz.
    • Page:
    • 1