Поиск:

Ответ в темуСоздание новой темы Создание опроса
> выделение текста в ComboBox после пперемешения 
V
    Опции темы
Cheloveck
Дата 24.4.2009, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Такая вот проблемка возникла. Создаю комбобокс, помещаю в него строки. Затем мне нужно его переместить методом MoveWindow, после чего текст в комбобоксе выделяется.
Код

       //..........

    combobox->Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
         WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS, CRect(10, 10, 150, 30), this, 0);
    combobox->AddString(_T("one"));
    combobox->SetCurSel(0);
    combobox->MoveWindow(CRect(20, 20, 160, 40));

       //...........


и вот, что, примерно, у меня получается в итоге
user posted image

может кто-то сталкивался с подобным? как убрать выделение? пробовал снимать выделение сразу после перемещение - всё ужасно мерцает. 


--------------------
user posted image
PM Jabber   Вверх
Andrey44
Дата 24.4.2009, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Цитата(Cheloveck @  24.4.2009,  15:29 Найти цитируемый пост)
Код
combobox->SetCurSel(0);

Ты-же сам выделяешь айтем

Добавлено через 54 секунды
Или попробуй сразу после перемещения снимать фокус с комбобокса


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Cheloveck
Дата 24.4.2009, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Andrey44, SetCurSel не выделяет, а устанавливает тест из списка. Фокус снимать пробовал - не помогает, да и нет на нём фокуса.

И, кстати, если MoveWindow убрать, то всё отлично.

Это сообщение отредактировал(а) Cheloveck - 24.4.2009, 15:41


--------------------
user posted image
PM Jabber   Вверх
Albor
Дата 24.4.2009, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 7
Всего: 9



По-моему со стилем DROPDOWN выбранный итем всегда выделен. Попробуй другой стиль (DROPLIST кажется)
PM MAIL ICQ   Вверх
Cheloveck
Дата 24.4.2009, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата

По-моему со стилем DROPDOWN выбранный итем всегда выделен. Попробуй другой стиль (DROPLIST кажется) 

Не   DROPLIST, а DROPDOWNLIST, но в них разница лишь в том, что второй создаёт ридонли комбобокс, а первый - редактируемый, выделяемость тут не при чём.


--------------------
user posted image
PM Jabber   Вверх
Albor
Дата 25.4.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 7
Всего: 9



Цитата(Cheloveck @  24.4.2009,  19:12 Найти цитируемый пост)
Не   DROPLIST, а DROPDOWNLIST, но в них разница лишь в том, что второй создаёт ридонли комбобокс, а первый - редактируемый, выделяемость тут не при чём.

Да, это так. Я когда-то боролся с этим делом, сейчас поднял свой проект, там я использовал Ownerdraw Fixed комбобокс, выделение появляется только при получении фокуса - меня это устроило. 

PM MAIL ICQ   Вверх
Andrey44
Дата 27.4.2009, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Cheloveck, используй не MoveWindow, а ::SetWindowPos с флагом SWP_NOACTIVATE.
Потому-что MoveWindow использует именно ::SetWindowPos но не известно с какими флагами.


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Cheloveck
Дата 27.4.2009, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Andrey44, не помогло, эффект тот же :-(


--------------------
user posted image
PM Jabber   Вверх
voov
Дата 27.4.2009, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



Cheloveck, у комбобокса есть метод SetEditSel
PM MAIL   Вверх
Earnest
Дата 27.4.2009, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Не может быть, чтобы убирание фокуса с комбобокса не убирало выделения. Значит, фокус неправильно убрал. Когда окно в фокусе - обязательно будет выделен элемент. Если у тебя Drop List можно только вместо выделения всего элемента поставить каретку.


--------------------
...
PM   Вверх
Cheloveck
Дата 28.4.2009, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата

Не может быть, чтобы убирание фокуса с комбобокса не убирало выделения. Значит, фокус неправильно убрал. Когда окно в фокусе - обязательно будет выделен элемент.

Код

    combobox->Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
         WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS, CRect(10, 10, 150, 30), this, 0);
    combobox->AddString(_T("one"));
    combobox->SetCurSel(0);
    combobox->MoveWindow(CRect(20, 20, 160, 40));
    CWnd *button = GetDlgItem(IDOK);
    if(!button)
        exit(0);
    button->SetFocus();

результат смотри выше.


voov, метод SetEditSel это не то. да и не получится у меня снимать выделение после перемещения каждый раз. У меня комбобокс перемещается когда меняется размер формы, поэтому перерисовка очень частая и если снимать каждый раз выделение, то получается жуткая картина.


--------------------
user posted image
PM Jabber   Вверх
voov
Дата 28.4.2009, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



а если SetCurSel заменить на SetWindowText?

PM MAIL   Вверх
Earnest
Дата 29.4.2009, 06:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Cheloveck @  28.4.2009,  16:40 Найти цитируемый пост)
результат смотри выше.

Вообще-то этот кусок кода ни о чем не говорит. Контекст-то неизвестен.
Например, если этот код находится в функции OnInitDialog, и ты возвращаешь TRUE, можешь хоть обставиться фокусами, все равно фокус будет на другом контроле... Или если кнопка OK недоступна, можешь хоть 10 раз на нее фокус ставить.
Но это так, к слову. Проверить-то просто. Табом перейди на следующий контрол и посмотри, во-первых, кто это будет, а во-вторых, не исчезнет ли выделение. 
Далее, если до перемещения комбобокс был не в фокусе, то нужно выяснить, почему на него фокус ставится. Тебе уже предлагали использовать SetWindowPos, и есть сомнения, что сделал это коррекстно.
В любом случае, можно словить SetFocus на комбе и посмотреть что в стеке - откуда он приходит-то.
А попытки тыкать пальцем в небо и искать какие-то эзотерические рецепты - заведомо бесполезны.


--------------------
...
PM   Вверх
Cheloveck
Дата 29.4.2009, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата

а если SetCurSel заменить на SetWindowText?

Тогда я не буду знать какой айтем выбран и программа допишет в файл строку, которая там уже есть.

Цитата

Тебе уже предлагали использовать SetWindowPos, и есть сомнения, что сделал это коррекстно.

У меня в этом сомнений нет, я не только сделал, что советовали, но и прочитал MSDN и сделал ещё много вариантов. Ладно буду дебажить.

Добавлено через 3 минуты и 10 секунд
Цитата

Вообще-то этот кусок кода ни о чем не говорит. Контекст-то неизвестен.

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


--------------------
user posted image
PM Jabber   Вверх
Earnest
Дата 29.4.2009, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Чего я не понимаю - это как сохраняется выделение при отсутствии фокуса...
Мне на стандарных комбобоксах добиться такого эффекта не удалось...


--------------------
...
PM   Вверх
Cheloveck
Дата 29.4.2009, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Код

class CTestMFCDlg : public CDialog
{
// Construction
public:
    virtual ~CTestMFCDlg();
    CTestMFCDlg(CWnd* pParent = NULL);    // standard constructor

// ...........................

    DECLARE_MESSAGE_MAP()
private:
    CComboBox *combobox;
    CComboBox *combobox2;
};

Код

CTestMFCDlg::CTestMFCDlg(CWnd* pParent)
    : CDialog(CTestMFCDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    combobox = new CComboBox;
    combobox2 = new CComboBox;
}


CTestMFCDlg::~CTestMFCDlg()
{
    delete combobox;
    delete combobox2;
}

BOOL CTestMFCDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    SetIcon(m_hIcon, TRUE);    
    SetIcon(m_hIcon, FALSE);

    combobox->Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
         WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS, CRect(10, 10, 150, 30), this, 0);

    combobox2->Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
         WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS, CRect(10, 150, 150, 180), this, 0);

    combobox->AddString(_T("one"));
    combobox->SetCurSel(0);

    combobox2->AddString(_T("two"));
    combobox2->SetCurSel(0);

    combobox->MoveWindow(CRect(20, 20, 160, 40));
    combobox2->MoveWindow(CRect(120, 120, 250, 140));

    return TRUE;
}


user posted image

Я сам вполне понимаю глупость ситуации. Но не может быть два фокуса!!!

Это сообщение отредактировал(а) Cheloveck - 29.4.2009, 16:26


--------------------
user posted image
PM Jabber   Вверх
Cheloveck
Дата 30.4.2009, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Не, ну это уже перебор....

Код

#include "windows.h"

LRESULT CALLBACK WndProc(HWND hWnd,UINT Message, UINT wParam, LONG lParam)
{
    switch(Message)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, Message, wParam, lParam);
}


int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE  hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    WNDCLASSEX wcp = { sizeof(WNDCLASSEX) };
    wcp.lpfnWndProc = WndProc;
    wcp.hInstance = hInstance;
    wcp.hCursor = LoadCursor(NULL,IDC_ARROW);
    wcp.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    wcp.lpszClassName = L"Window";
    RegisterClassEx(&wcp);

    HWND hWndMainForm = CreateWindowEx(0, L"Window",L"Window", WS_OVERLAPPEDWINDOW, 
        300, 150, 500, 400, NULL, NULL, hInstance, NULL);

    HWND combobox = CreateWindowEx(0, L"COMBOBOX", NULL, CBS_DROPDOWN | WS_CHILD | WS_VISIBLE, 
        10, 10, 100, 40, hWndMainForm, NULL, hInstance, NULL);

    SendMessage(combobox, CB_ADDSTRING, 3, (LPARAM)L"one");
    SendMessage(combobox, CB_SETCURSEL, 0, 0);

    ShowWindow(hWndMainForm, nShowCmd);
    UpdateWindow(hWndMainForm);
    SetWindowPos(combobox, HWND_BOTTOM, 60, 20, 100, 40, SWP_NOACTIVATE | SWP_NOZORDER);

    MSG msg;
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
} 


Опять всё то же... Я тут подумал, а если фокус помещается на комбобокс при перемещении, а потом уходит дальше, а выделение остаётся?
Может есть какой-то флаг при создании комбобокса (или даже главного окна), чтобы текстовые поля без фокуса не выделялись?

Это сообщение отредактировал(а) Cheloveck - 30.4.2009, 13:34


--------------------
user posted image
PM Jabber   Вверх
voov
Дата 30.4.2009, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



Cheloveck, елси поменять местами вызовы SetCurSel и MoveWindow, то выделения нет. 
Код

    combobox->MoveWindow(CRect(20, 160, 160, 180));

    combobox->AddString(_T("one"));
    combobox->SetCurSel(0);

такое решение устроит?
PM MAIL   Вверх
voov
Дата 30.4.2009, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



елси использовать стиль CBS_DROPDOWNLIST вместо CBS_DROPDOWN, тоже помогает

Добавлено через 3 минуты и 11 секунд
и вот еще такой код не оставляет выделения:
Код

    combobox->AddString(_T("one"));
    combobox->SetCurSel(0);

    combobox2->AddString(_T("two"));
    combobox2->SetCurSel(0);

    combobox->MoveWindow(CRect(20, 160, 160, 180));
    combobox->SetFocus();
    combobox2->MoveWindow(CRect(120, 120, 250, 140));
    combobox2->SetFocus();

PM MAIL   Вверх
Cheloveck
Дата 5.5.2009, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата

такое решение устроит? 

Нет, не устроит, ибо мне надо перемещать после добавления и выбора строки.
Цитата

елси использовать стиль CBS_DROPDOWNLIST вместо CBS_DROPDOWN, тоже помогает

Мне нужно редактируемое поле.
Цитата

CBS_DROPDOWNLIST   Similar to CBS_DROPDOWN, except that the edit control is replaced by a static-text item that displays the current selection in the list box.

Ясно сказано, что текстовое поле заменяется статиком. Хотя в результате моей Spy-атаки на Explorer, я выяснил, что Microsoft всё же использует CBS_DROPDOWNLIST, вероятно проводя какие-то манипуляции по замене статика эдитом.

Фокус убирать я тоже пробовал, НО, мне нужно перемещать контролы при изменении размера окна. И если постоянно снимать фокус - то выделение мерцает.

//==========================================================================

Очень интересные результаты показало исследование сообщений, при изменении размера комбобокса, точнее эдита в нём:
Код

<00001> 002802AA S WM_WINDOWPOSCHANGING lpwp:0015F764
<00002> 002802AA R WM_WINDOWPOSCHANGING
<00003> 002802AA S WM_GETTEXTLENGTH
<00004> 002802AA R WM_GETTEXTLENGTH cch:3
<00005> 002802AA S WM_GETTEXT cchTextMax:8 lpszText:0015EE8C
<00006> 002802AA R WM_GETTEXT cchCopied:3 lpszText:0015EE8C ("o")
<00007> 002802AA S WM_SETTEXT lpsz:0015F6D8 ("one")
<00008> 002802AA R WM_SETTEXT fSucceeded:True
<00009> 002802AA S EM_SETSEL nStart:0 nEnd:2147483647
<00010> 002802AA R EM_SETSEL
<00011> 002802AA P WM_PAINT hdc:00000000
<00012> 002802AA S WM_NCPAINT hrgn:00000001
<00013> 002802AA R WM_NCPAINT
<00014> 002802AA S WM_ERASEBKGND hdc:0101091F
<00015> 002802AA R WM_ERASEBKGND fErased:True

То есть, выделение устанавливается не так, как было прочитано, а EM_SETSEL nStart:0 nEnd:2147483647.

Тем не менее решение найдено!!! Не оптимальное, но в моём случае достаточное.

Код

class ComboBox : public CComboBox
{
    DECLARE_MESSAGE_MAP();
public:
    virtual void OnSize(UINT nTipe, int cx, int cy);
};

BEGIN_MESSAGE_MAP(ComboBox, CComboBox)
    ON_WM_SIZE()
END_MESSAGE_MAP()

void ComboBox::OnSize(UINT nTipe, int cx, int cy)
{
    DWORD sel = GetEditSel();
    CComboBox::OnSize(nTipe, cx, cy);
    SetEditSel(HIWORD(sel), LOWORD(sel));
}


Плюс к этому при изменении размеров я ввёл таймер, который производит перемещение контролов каждые 100 миллисекунд (собственно как в Qt). Мерцания не видно, выделение текста сохраняется, что и требовалось.

P.S. тема закрыта.

Это сообщение отредактировал(а) Cheloveck - 5.5.2009, 16:08


--------------------
user posted image
PM Jabber   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0642 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.