2014-08-29 2 views
1

У меня есть текстовое поле в моей форме окна, для которой у меня настроена автозаполнение. Я приношу предложения динамически, поскольку пользователь вводит их из веб-сервиса. Это делается фоновым работником.Windows Forms - Открыть список предложений программно после установки источника автозаполнения

После установки источника автозаполнения, как я могу программным образом открыть предложения этого текстового поля? (Что-то вроде собственности у нас есть для Комбобокса - DroppeDown)

ответ

1

варианты:

  1. использовать Hacky решения
  2. использовать чистые C# автозаполнение управления (например, написать свой собственный или использовать чужой)
  3. switch to combobox

Вы можете найти № 2 и № 3 самостоятельно. Я считаю, что №2 - лучший вариант. Однако прочитайте, если вы хотите сделать # 1:

Чистое решение по тому, что вы просите, не существует. Мое понимание автозаполнения заключается в том, что это COM-объект, возможно, изначально построенный для Internet Explorer (поскольку в окне Spy ++ есть заголовок «Internet Explorer» в его иерархии). Во всяком случае, автозаполнение перехватывает события WndProc из элемента управления редактирования. Он заполняет и отображает список, когда он получает уведомления о событиях, таких как KEY_DOWN.

Например, предположим, что у вас есть автозаполнение с хотя бы одним словом, начинающимся с буквы «А». Вы можете заставить автозаполнение появляться, отправив сообщение POST в TextBox:

//host.Text = "A"; // does not work 
PostMessage(textbox.Handle, WM_KEYDOWN, VK_A, 0); // works (see SendKey method below) 

[DllImport("user32.dll")] 
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); 


// only works once the Handle has been assigned 
public void Show() { 
    ShowWindow(Handle, SW_SHOWNOACTIVATE); 
} 

// e.g. VK_A = 0x41, VK_SPACE = 20; 
public void SendKey(int VK_KEY) { 
    PostMessage(Host.Handle, 0x100, VK_KEY, 0); 
    System.Threading.Tasks.Task.Run((Action) delegate { 
     Thread.Sleep(10); // small delay required 
     Host.BeginInvoke((Action) delegate { 
      Show(); 
     }); 
    }); 
} 

Насколько я знаю, это не представляется возможным непосредственно контролировать содержание в автозаполнении. Тем не менее, в другом потоке stackoverflow (не удается найти его сейчас) ответ заключался в том, чтобы префикс каждого слова пробел, чтобы все они использовали общий префикс, а затем обрезали значение впоследствии.

Вы также можете заставить автозаполнение появляться без ввода чего-либо, но, к сожалению, оно будет пустым. Например:

const int SW_SHOWNOACTIVATE = 4; 
IntPtr p = ...; // handle to Autocomplete window 
int width = 400; 
int height = 200; 
SetWindowPos(p, IntPtr.Zero, -5, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
ShowWindow(p, SW_SHOWNOACTIVATE); 

Вы можете узнать, как получить ссылку ручки здесь: Combo box drop down width on suggest

Даже когда у вас есть ручки, нет никакой прямой или косвенной ссылки на его владеющий контроль редактирования. В приведенной выше гиперссылке единственный способ определить элемент управления редактированием - это прослушивать первый раз, когда отображается автозаполнение, а затем проверять каждый элемент управления, чтобы увидеть, какой элемент управления находится на экране.

+0

Ничего себе. Появляется настолько хакерским для такого простого случая использования. Попробуй. – NLV

+0

Я был уверен, что «PostMessage» работает, но похоже, что я что-то изменил в своем коде, и теперь он не работает. В любом случае, если он не работает, вы можете выполнить 'control.Focus(); SendKeys.Send (""); ' – Loathing

+0

Кажется, что небольшая задержка, за которой следует' Show(), может решить проблему. Добавлен код, который работает для меня с помощью 'PostMessage'. – Loathing