| 2969 | |
| 2970 | |
| 2971 | BOOL CALLBACK EnumChildGetControlList(HWND aWnd, LPARAM lParam) |
| 2972 | { |
| 2973 | control_list_type &cl = *(control_list_type *)lParam; // For performance and convenience. |
| 2974 | |
| 2975 | // cl.fetch_hwnds==true is a new mode in v1.0.43.06+ to help performance of AHK Window Info and other |
| 2976 | // scripts that want to operate directly on the HWNDs. |
| 2977 | if (cl.fetch_hwnds) |
| 2978 | { |
| 2979 | cl.target_array->Append((__int64)(size_t)aWnd); |
| 2980 | } |
| 2981 | else // The mode that fetches ClassNN vs. HWND. |
| 2982 | { |
| 2983 | TCHAR line[WINDOW_CLASS_SIZE + 5]; // +5 to allow room for the sequence number to be appended later below. |
| 2984 | int line_length; |
| 2985 | |
| 2986 | // Note: IsWindowVisible(aWnd) is not checked because although Window Spy does not reveal |
| 2987 | // hidden controls if the mouse happens to be hovering over one, it does include them in its |
| 2988 | // sequence numbering (which is a relieve, since results are probably much more consistent |
| 2989 | // then, esp. for apps that hide and unhide controls in response to actions on other controls). |
| 2990 | if ( !(line_length = GetClassName(aWnd, line, WINDOW_CLASS_SIZE)) ) // Don't include the +5 extra size since that is reserved for seq. number. |
| 2991 | return TRUE; // Probably very rare. Continue enumeration since Window Spy doesn't even check for failure. |
| 2992 | // It has been verified that GetClassName()'s returned length does not count the terminator. |
| 2993 | |
| 2994 | // Check if this class already exists in the class array: |
| 2995 | int class_index; |
| 2996 | for (class_index = 0; class_index < cl.total_classes; ++class_index) |
| 2997 | if (!_tcsicmp(cl.class_name[class_index], line)) // lstrcmpi() is not used: 1) avoids breaking existing scripts; 2) provides consistent behavior across multiple locales. |
| 2998 | break; |
| 2999 | if (class_index < cl.total_classes) // Match found. |
| 3000 | { |
| 3001 | ++cl.class_count[class_index]; // Increment the number of controls of this class that have been found so far. |
| 3002 | if (cl.class_count[class_index] > 99999) // Sanity check; prevents buffer overflow or number truncation in "line". |
| 3003 | return TRUE; // Continue the enumeration. |
| 3004 | } |
| 3005 | else // No match found, so create new entry if there's room. |
| 3006 | { |
| 3007 | if (cl.total_classes == CL_MAX_CLASSES // No pointers left. |
| 3008 | || CL_CLASS_BUF_SIZE - (cl.buf_free_spot - cl.class_buf) - 1 < line_length) // Insuff. room in buf. |
| 3009 | return TRUE; // Very rare. Continue the enumeration so that class names already found can be collected. |
| 3010 | // Otherwise: |
| 3011 | cl.class_name[class_index] = cl.buf_free_spot; // Set this pointer to its place in the buffer. |
| 3012 | _tcscpy(cl.class_name[class_index], line); // Copy the string into this place. |
| 3013 | cl.buf_free_spot += line_length + 1; // +1 because every string in the buf needs its own terminator. |
| 3014 | cl.class_count[class_index] = 1; // Indicate that the quantity of this class so far is 1. |
| 3015 | ++cl.total_classes; |
| 3016 | } |
| 3017 | |
| 3018 | _itot(cl.class_count[class_index], line + line_length, 10); // Append the seq. number to line. |
| 3019 | |
| 3020 | cl.target_array->Append(line); // Append class name+seq. number to the array. |
| 3021 | } |
| 3022 | |
| 3023 | return TRUE; // Continue enumeration through all the windows. |
| 3024 | } |
| 3025 | |
| 3026 | |
| 3027 | |