| 9198 | |
| 9199 | |
| 9200 | void GuiType::Event(GuiIndexType aControlIndex, UINT aNotifyCode, USHORT aGuiEvent, UINT_PTR aEventInfo) |
| 9201 | // Caller should pass GUI_EVENT_NONE (zero) for aGuiEvent if it wants us to determine aGuiEvent based on the |
| 9202 | // type of control and the incoming aNotifyCode. |
| 9203 | // This function handles events within a GUI window that caused one of its controls to change in a meaningful |
| 9204 | // way, or that is an event that could trigger an external action, such as clicking a button or icon. |
| 9205 | { |
| 9206 | if (aControlIndex >= mControlCount) // Caller probably already checked, but just to be safe. |
| 9207 | return; |
| 9208 | GuiControlType &control = *mControl[aControlIndex]; |
| 9209 | if (!control.events.Count()) // But don't check IsMonitoring(aGuiEvent) yet, because aGuiEvent may be undetermined. |
| 9210 | return; // No event handlers associated with this control, so no action. |
| 9211 | if (control.attrib & GUI_CONTROL_ATTRIB_SUPPRESS_EVENTS) |
| 9212 | return; |
| 9213 | |
| 9214 | // Update: The below is now checked by MsgSleep() at the time the launch actually would occur because |
| 9215 | // g_nThreads will be more accurate/timely then: |
| 9216 | // If this control already has a thread running in its label, don't create a new thread to avoid |
| 9217 | // problems of buried threads, or a stack of suspended threads that might be resumed later |
| 9218 | // at an unexpected time. Users of timer subs that take a long time to run should be aware, as |
| 9219 | // documented in the help file, that long interruptions are then possible. |
| 9220 | //if (g_nThreads >= g_MaxThreadsTotal || (aControl->attrib & GUI_CONTROL_ATTRIB_HANDLER_IS_RUNNING)) |
| 9221 | // continue |
| 9222 | |
| 9223 | if (aGuiEvent == GUI_EVENT_WM_COMMAND) // Called by WM_COMMAND. |
| 9224 | { |
| 9225 | if (control.events.IsMonitoring(aNotifyCode, GUI_EVENTKIND_COMMAND)) |
| 9226 | { |
| 9227 | POST_AHK_GUI_ACTION(mHwnd, aControlIndex, aGuiEvent, aNotifyCode); |
| 9228 | // Do the rest as well, just in case this command corresponds to an event. |
| 9229 | } |
| 9230 | aGuiEvent = GUI_EVENT_NONE; // Determine the actual event below. |
| 9231 | } |
| 9232 | |
| 9233 | if (aGuiEvent == GUI_EVENT_NONE) // Caller wants us to determine aGuiEvent based on control type and aNotifyCode. |
| 9234 | { |
| 9235 | switch(control.type) |
| 9236 | { |
| 9237 | case GUI_CONTROL_BUTTON: |
| 9238 | case GUI_CONTROL_CHECKBOX: |
| 9239 | case GUI_CONTROL_RADIO: |
| 9240 | switch (aNotifyCode) |
| 9241 | { |
| 9242 | case BN_CLICKED: // Must explicitly list this case since the default label below does a return. |
| 9243 | // Fix for v1.0.24: The below excludes from consideration messages from radios that are |
| 9244 | // being unchecked. This prevents a radio group's g-label from being fired twice when the |
| 9245 | // user navigates to a new radio via the arrow keys. It also filters out the BN_CLICKED that |
| 9246 | // occurs when the user tabs over to a radio group that lacks a selected button. This new |
| 9247 | // behavior seems like it would be desirable most of the time. |
| 9248 | if (control.type == GUI_CONTROL_RADIO && SendMessage(control.hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED) |
| 9249 | return; |
| 9250 | aGuiEvent = GUI_EVENT_CLICK; |
| 9251 | break; |
| 9252 | // All three of these require BS_NOTIFY: |
| 9253 | case BN_DBLCLK: aGuiEvent = GUI_EVENT_DBLCLK; break; |
| 9254 | case BN_SETFOCUS: aGuiEvent = GUI_EVENT_FOCUS; break; |
| 9255 | case BN_KILLFOCUS: aGuiEvent = GUI_EVENT_LOSEFOCUS; break; |
| 9256 | default: |
| 9257 | return; |
no test coverage detected