MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / ControlGetComboBox

Method ControlGetComboBox

source/script_gui.cpp:1671–1747  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1669
1670
1671ResultType GuiType::ControlGetComboBox(ResultToken &aResultToken, GuiControlType &aControl, ValueModeType aMode)
1672{
1673 LRESULT index = SendMessage(aControl.hwnd, CB_GETCURSEL, 0, 0); // Get index of currently selected item.
1674
1675 // Problem #1:
1676 // It seems that any text put into a ComboBox's edit field by typing/pasting or via Ctrl.Text
1677 // always resets the current index to -1, even if that text exactly matches an existing item.
1678
1679 // Problem #2:
1680 // CB_GETCURSEL sometimes returns an index which doesn't match what's in the Edit control.
1681 // This typically happens as a result of typing/pasting while the drop-down window is visible
1682 // and then canceling the dropdown without making a selection.
1683 // Note that when the CBN_SELENDCANCEL notification is received, CB_GETCURSEL correctly returns -1,
1684 // but at some point after that the control restores the index to a possibly incorrect value. This
1685 // appears to happen in other programs as well, and has been confirmed on Windows 10 and earlier.
1686
1687 int edit_length = GetWindowTextLength(aControl.hwnd); // Zero is valid (the control may be empty).
1688 // For simplicity and in case the text is very large, use tmalloc() unconditionally
1689 // even though the text is probably very small. This allocation may be returned below.
1690 LPTSTR edit_text = tmalloc(edit_length + 1);
1691 if (!edit_text)
1692 _o_throw_oom;
1693 edit_length = GetWindowText(aControl.hwnd, edit_text, edit_length + 1);
1694 if (index != CB_ERR)
1695 {
1696 // The control returned a valid index, so verify that it matches the edit text.
1697 // If a search beginning at the indicated item does not return that item, it must
1698 // not be a match. This approach avoids retrieving the item's text, which reduces
1699 // code size. Performance hasn't been measured, but at a guess, is probably better
1700 // when the item matches (as it would 99.9% of the time), and worse in other cases.
1701 if (!edit_length)
1702 {
1703 // A different approach is needed in this case since CB_FINDSTRINGEXACT can't
1704 // search for an empty string. This preserves the ability to detect selection
1705 // of a specific empty list item, though for simplicity, clearing the edit text
1706 // will not match up to an empty list item.
1707 if (0 != SendMessage(aControl.hwnd, CB_GETLBTEXTLEN, (WPARAM)index, 0))
1708 index = CB_ERR;
1709 }
1710 else
1711 {
1712 if (index != SendMessage(aControl.hwnd, CB_FINDSTRINGEXACT, index - 1, (LPARAM)edit_text))
1713 index = CB_ERR;
1714 }
1715 }
1716 if (index == CB_ERR)
1717 {
1718 // Check if the Edit field contains text that exactly matches one of the items in the drop-list.
1719 // If it does, that item's position should be retrieved in AltSubmit mode (even for non-AltSubmit
1720 // mode, this should be done because the case of the item in the drop-list is usually preferable
1721 // to any varying case the user may have manually typed).
1722 index = SendMessage(aControl.hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)edit_text); // It's not case sensitive.
1723 if (index == CB_ERR && aMode != Value_Mode) // Text or Submit mode.
1724 {
1725 // edit_text does not match any of the list items, so just return the text.
1726 aResultToken.AcceptMem(edit_text, edit_length);
1727 return OK;
1728 }

Callers

nothing calls this directly

Calls 2

TokenSetResultFunction · 0.85
AcceptMemMethod · 0.80

Tested by

no test coverage detected