LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Use Toggle Button to Simulate Holding Ctrl

Solved!
Go to solution

Hi,

 

I've seen somebody asked something very similar before but nobody seemed to know the solution.

 

I was wondering if it's possible to use a toggle button to simulate holding the Ctrl key, the idea being that the user could then zoom in on a rectangle of their choosing on a plot without having to hold the button themselves. I know you can use the FakeKeystroke function to simulate pressing the key however is there a way that this can be held?

 

Thanks

0 Kudos
Message 1 of 16
(5,528 Views)

Hi,

In the following link you find what you want:

http://zone.ni.com/reference/en-XX/help/370051K-01/cvi/cvifakekeystroke/

 

0 Kudos
Message 2 of 16
(5,518 Views)

Thanks, I did have a read of that earlier but only found it useful for simulating a key press rather than holding it down.

0 Kudos
Message 3 of 16
(5,514 Views)

Hi,

you can use this code snippet to assign the desired key value and assign the value of the control ToggleButton:

 

switch (event)

{

case EVENT_COMMIT:
FakeKeystroke (VAL_MENUKEY_MODIFIER | 'A');

SetCtrlAttribute (panelHandle, PANEL_TOGGLEBUTTON, ATTR_CTRL_VAL, 1);

break;

}

 

 

0 Kudos
Message 4 of 16
(5,500 Views)

Thanks but I think that still doesn't quite do what I'm after. Essentially what I'm looking for is for the Ctrl button to be held so that when the user clicks on a graph they can zoom to a rectangular area that they select. The toggle button should basically replace the need to hold the Ctrl key.

 

I'm ok with all the zooming settings etc and I'm also using GetCtrlVal from the toggle button so that I can use the case of it being equal to 1 to perform an action. Using FakeKeystroke(VAL_MENUKEY_MODIFIER) seems to only perform the action of pressing the key whereas I need it to remain pressed as long as the toggle switch is engaged.

 

Cheers

0 Kudos
Message 5 of 16
(5,489 Views)

you can use a simple while loop whose condition is the value of ToggleButton and it does the job properly if I understood what you want.

0 Kudos
Message 6 of 16
(5,486 Views)

Thanks for the reply again, yea I thought a while loop would work as well, however from trying it, it just makes the thing crash!

 

Here is my code for the Zoom toggle button:

 

int CVICALLBACK Zoom (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
 {
  case EVENT_COMMIT:
   GetCtrlVal(panelHandle, PANEL_ZOOM, &zoomonoff);
   
   while (zoomonoff == 1)
   {
   FakeKeystroke(VAL_MENUKEY_MODIFIER);
   }
   
   break;
  case EVENT_RIGHT_CLICK:

   break;
 }
 return 0;
}

 

It's possible I've done something stupid in the code, let me know if you can see anything!

0 Kudos
Message 7 of 16
(5,483 Views)

while (event==EVENT_COMMIT)

{

************************

}

0 Kudos
Message 8 of 16
(5,476 Views)

cottonb,

 

This is a bit tricky, but I think I have something that may work for you. Faking the keystroke is really only good for generating single key presses. As you found, holding the key is completely different. Unfortunately, we do not have a function that does this on its own, so what we have to do is actually modify the keyboard state. There are two functions that we can use to achieve this getKeyboardState and setKeyboardState. We can get the current keyboard state, then modify the control key to a pressed state, then set the new keyboard state. We will do this in the callback for the EVENT_LEFT_CLICK, but we will then need to generate another mouse click so that we have a new mouse event with the control key pressed. This second event gets caught by user callback as a doubleclick because it happens so close to the original click, so this is actually a convenient location to restore the old keyboard state. This is necessary so that the control key is not active for other controls and we don't want to assume that the control key is not pressed when the toggle button is disabled. Here is the code I used to achieve this. Please let me know if you have any questions.

 

char oldKeyState[256] = {0};
char newKeyState[256] = {0};

int CVICALLBACK zoom (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	HWND hwnd;
	int toggleButton = 0;
	switch (event)
	{
		case EVENT_LEFT_CLICK:
			
			//get current state of keyboard
			GetKeyboardState(oldKeyState);
			//get state of toggle button
			GetCtrlVal(panelHandle, PANEL_TOGGLEBUTTON, &toggleButton);
			
			if(toggleButton)
			{
				//create new copy of keystate
				memcpy(newKeyState, oldKeyState, 1);
				
				//set control key active. 
				newKeyState[VK_CONTROL] = 128;
				SetKeyboardState(newKeyState);
				
				//generate left mouse button event that will now have the control key active
				SetActiveCtrl (panelHandle, PANEL_GRAPH);
				GetPanelAttribute (panelHandle, ATTR_SYSTEM_WINDOW_HANDLE, (intptr_t*)&hwnd);
				SendMessage(hwnd, WM_LBUTTONDOWN, 0, 0);
			}
			
			break;
		case EVENT_LEFT_DOUBLE_CLICK:
			
			//generated mouse event will be caught as a double click. restore old keyboard state
			SetKeyboardState(oldKeyState);
			
			break;
	}
	return 0;
}

 

National Instruments
0 Kudos
Message 9 of 16
(5,466 Views)
Solution
Accepted by topic author cottonb

Forgot one thing. You need to handle the case of when you have a real EVENT_DOUBLE_CLICK. In this situation you don't want to reset the keyboardState. Here is the modified code.

 

char oldKeyState[256] = {0};
char newKeyState[256] = {0};
int isFakeDouble = 0;

int CVICALLBACK zoom (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	HWND hwnd;
	int toggleButton = 0;
	switch (event)
	{
		case EVENT_LEFT_CLICK:
			
			//get current state of keyboard
			GetKeyboardState(oldKeyState);
			//get state of toggle button
			GetCtrlVal(panelHandle, PANEL_TOGGLEBUTTON, &toggleButton);
			
			if(toggleButton)
			{
				//create new copy of keystate
				memcpy(newKeyState, oldKeyState, 1);
				
				//set control key active. 
				newKeyState[VK_CONTROL] = 128;
				SetKeyboardState(newKeyState);
				
				//generate left mouse button event that will now have the control key active
				SetActiveCtrl (panelHandle, PANEL_GRAPH);
				GetPanelAttribute (panelHandle, ATTR_SYSTEM_WINDOW_HANDLE, (intptr_t*)&hwnd);
				isFakeDouble = 1;
				SendMessage(hwnd, WM_LBUTTONDOWN, 0, 0);
				isFakeDouble = 0;
			}
			
			break;
		case EVENT_LEFT_DOUBLE_CLICK:
			
			//generated mouse event will be caught as a double click. restore old keyboard state
			if(isFakeDouble)
				SetKeyboardState(oldKeyState);
			
			break;
	}
	return 0;
}

 

National Instruments
Message 10 of 16
(5,454 Views)