09-15-2011 07:55 AM
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
Solved! Go to Solution.
09-15-2011 09:50 AM
Hi,
In the following link you find what you want:
http://zone.ni.com/reference/en-XX/help/370051K-01/cvi/cvifakekeystroke/
09-15-2011 09:55 AM
Thanks, I did have a read of that earlier but only found it useful for simulating a key press rather than holding it down.
09-16-2011 02:37 AM
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;
}
09-16-2011 05:37 AM
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
09-16-2011 06:07 AM
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.
09-16-2011 06:21 AM
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!
09-16-2011 07:31 AM
while (event==EVENT_COMMIT)
{
************************
}
09-16-2011 11:17 AM
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;
}
09-16-2011 04:04 PM
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;
}