Respond to clicking any control on a window

Some built in Igor control types, such as ValDisplay controls, cannot be set to call an action procedure when a user clicks on the control. I wanted to use the nice built in LED-like functionality of the ValDisplay control but wanted the control to function as a button. In order to do this, I needed to write a function that could be used as a window hook and which responded to a mouse button click and determined if the click was over one of the ValDisplay controls on my panel.

To use this snippet, paste the code below into an Igor procedure window. Make sure to modify the section in the first function that says
<do something here to respond to the click if you wish>

You'll need to set the first function to be a named window hook for any window you want to use this technique in. To do that, from a function or the command line execute something like this:
  SetWindow kwTopWin,hook(windowClick)=RespondToWindowClick


For more information about the parameters used in these functions and additional functionality read the code comments at the top of each function.


//**
// This is the window hook function.  All windows that should be handled by this
// function need to have this function set as a named window hook for the window.
// For example:
// SetWindow kwTopWin,hook(windowClick)=RespondToWindowClick
//
// Note:  The variable names used may imply that the control has to be an actual
// button, however that is not the case.  Any type of control can be used.  To handle
// clicks on only certain types of controls, modify the "buttonFound = FindControl(s, buttonPressed)"
// line.  See the comments above the FindControl() function for more information.
//
// Note:  As written this function can only handle actual Igor control types (Buttons, SetVariables, etc.).
// However, it would be relatively easy to modify the code to handle something like a graph annotation.
//*
Function RespondToWindowClick(s)
    STRUCT WMWinHookStruct &s
   
    switch (s.eventCode)
        Case 3:     // mouse down
            String buttonPressed = ""
            Variable buttonFound
            buttonFound = FindControl(s, buttonPressed)
            // Change the color and frame of the button to make
            // it looked like it has been toggled.
            if (buttonFound)
                <do something here to respond to the click if you wish>
                return 1
            endif
            break
    EndSwitch
    return 0
End

//**
// Determines if the mouse cursor is currently over a control
// and provides the name of the control.
//
// @param s
//  This is an instance of the WMWinHookStruct structure which
//  is the structured that is passed to a named window hook function.
// @param controlName
//  Name of control the the mouse cursor is currently over.  This is
//  the output parameter of this function.
// @param controlType
//  [OPTIONAL]  If provided, only controls of this type will be considered.
//  For a list of types and their meanings, look at the ControlInfo
//  command help and look at the V_flag parameter set for each control type.
//  By default, the type of a control is ignored.
// @param excludedState
//  [OPTIONAL] If non-zero, controls will be considered from consideration
//  if they are disabled and/or hidden.  Use the following values to exclude
//  controls in the following states:
//      Value           State
//      1               Hidden
//      2               Disabled (but visible)
//      3               Hidden OR Disabled (but visible)
//  By default, the disable state of a control is ignored.
//
// @return
//  If a control was found meeting the criteria specified in the parameters,
//  the function will return 1.  If no control is found, 0 will be returned.
//*
Function FindControl(s, controlName, [controlType, excludedState])
    STRUCT WMWinHookStruct &s
    String &controlName
    Variable controlType
    Variable excludedState

    Variable controlFound
    controlName = ""
       
    if (ParamIsDefault(controlType))
        // Match all types of controls
        controlType = 0
    endif
   
    String controlList = ControlNameList(s.winName, ";", "*")
    Variable numControls = ItemsInList(controlList, ";")
    String currentControlName
    Variable n
    For (n=0; n<numControls; n+=1)
        currentControlName = StringFromList(n, controlList, ";")
        ControlInfo/W=$(s.winName) $(currentControlName)
       
        // Exclude this control if only controls of a certain type should
        // be considered.
        if (controlType != 0 && controlType != V_flag)
            continue
        endif
       
        // Possibly exclude this control if it is hidden or disabled
        if (V_disable != 0)
            if (V_disable & excludedState)
                continue
            endif
        endif
       
        // Determine if this control was clicked on.
        Variable controlClicked
        controlClicked = DoesCursorOverlap(s, V_height, V_width, V_top, V_left)
        if (controlClicked)
            controlName = currentControlName
            controlFound = 1
        endif
    EndFor
   
    return controlFound
End

//**
// Determines if the current mouse position falls within a certain boundary.
//
// @param s
//  This is an instance of the WMWinHookStruct structure which
//  is the structured that is passed to a named window hook function.
// @param V_height
//  Height of target area, in pixels.
// @param V_width
//  Width of target area, in pixels.
// @param V_top
//  Top of target area, in pixels.
// @param V_left
//  Left of target area, in pixels.
//
// @return
//  If the mouse cursor overlaps the target area, 1 is returned.  Otherwise, 0 is returned.
//*
Function DoesCursorOverlap(s, V_height, V_width, V_top, V_left)
    STRUCT WMWinHookStruct &s
    Variable V_height
    Variable V_width
    Variable V_top
    Variable V_left
   
    // Check vertical location
    if (s.mouseLoc.v >= V_top && s.mouseLoc.v <= V_top + V_height)
        // Check horizontal location
        if (s.mouseLoc.h >= V_left && s.mouseLoc.h <= V_left + V_width)
            return 1
        endif
    endif
    return 0   
End

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More