Получить HWND ListBox выбора при разворачивании ComboBox
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.05.09 18:28
Оценка:
Как в момент разворачивания ComboBox заполучить HWND ListBox`а с вариантами выбора?

Задача такая: есть свой ownerdraw-комбобокс, который в UI может располагаться достаточно близко к правому краю окна, и соответственно близко к правому краю экрана, если окно развернуто.
Ширина строк в вариантах выбора достаточно большая, т.е. ListBox значительно шире, чем сам ComboBox в свернутом состоянии (ширина ставится через CB_SETDROPPPEDWIDTH). Ну и соответственно когда список в правой части окна в развернутом состоянии строки не влезают на экран. Хочется как-то подвинуть этот список чтобы он был полностью виден на экране.
Т.е. сделать как в Word`е — в нем при выборе шрифта из списка, если сам список выступает по горизонтали за края экрана Word его немного сдвигает влево или вправо. Получается что Ворд на лету меняет выравнивание списка выбора или по левому краю самого комбобокса или по правому, так чтобы список был полностью виден на экране.
Aml Pages Home
Re: Получить HWND ListBox выбора при разворачивании ComboBox
От: std.denis Россия  
Дата: 21.05.09 20:20
Оценка: 4 (1)
засабклассить выпадающий список и не давать ему уйти за пределы экрана в WM_WINDOWPOSCHANGING ?
поиск по "ComboLBox" выдал вот это
Автор: xmen
Дата: 28.12.08
Re[2]: Получить HWND ListBox выбора при разворачивании Combo
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.05.09 21:38
Оценка:
Здравствуйте, std.denis, Вы писали:

SD>засабклассить выпадающий список и не давать ему уйти за пределы экрана в WM_WINDOWPOSCHANGING ?

SD>поиск по "ComboLBox" выдал вот это
Автор: xmen
Дата: 28.12.08

Сенкс! Но в принципе уже выкрутился через хук...
Aml Pages Home
Re[3]: Получить HWND ListBox выбора при разворачивании Combo
От: Pavel Dvorkin Россия  
Дата: 22.05.09 05:37
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, std.denis, Вы писали:


SD>>засабклассить выпадающий список и не давать ему уйти за пределы экрана в WM_WINDOWPOSCHANGING ?

SD>>поиск по "ComboLBox" выдал вот это
Автор: xmen
Дата: 28.12.08

C>Сенкс! Но в принципе уже выкрутился через хук...


CB_GETCOMBOBOXINFO Message

COMBOBOXINFO Structure

--------------------------------------------------------------------------------

Contains combo box status information.

Syntax

typedef struct tagCOMBOBOXINFO {
DWORD cbSize;
RECT rcItem;
RECT rcButton;
DWORD stateButton;
HWND hwndCombo;
HWND hwndItem;
HWND hwndList;
} COMBOBOXINFO, *PCOMBOBOXINFO, *LPCOMBOBOXINFO;
Members

hwndList
A handle to the drop-down list.
With best regards
Pavel Dvorkin
Re[4]: Получить HWND ListBox выбора при разворачивании Combo
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 09:42
Оценка:
PD>CB_GETCOMBOBOXINFO Message
PD>COMBOBOXINFO Structure
PD>--------------------------------------------------------------------------------
PD>Contains combo box status information.
PD>Syntax
PD>typedef struct tagCOMBOBOXINFO {
PD> DWORD cbSize;
PD> RECT rcItem;
PD> RECT rcButton;
PD> DWORD stateButton;
PD> HWND hwndCombo;
PD> HWND hwndItem;
PD> HWND hwndList;
PD>} COMBOBOXINFO, *PCOMBOBOXINFO, *LPCOMBOBOXINFO;
PD>Members

PD>hwndList

PD>A handle to the drop-down list.
А подвинуть его? А когда ListBox создается? Наверняка ведь поди винда не сходу его создает (я бы откладывал до упора, пока не понадобится)... Мне же надо посмотреть влезает он в экран или нет, и только потом двигать его...
Не-е-е, я конечно через хук на этот же поток выкрутился — но может оно как-то попроще можно. Хук тоже какой-то не идеальный получился (с элементами бубна).
Aml Pages Home
Re[5]: Получить HWND ListBox выбора при разворачивании Combo
От: std.denis Россия  
Дата: 22.05.09 10:04
Оценка:
C>А подвинуть его? А когда ListBox создается? Наверняка ведь поди винда не сходу его создает (я бы откладывал до упора, пока не понадобится)... Мне же надо посмотреть влезает он в экран или нет, и только потом двигать его...
на 100% не уверен, но при создании комбобокса.
Хотя подменить WndProc у списка можно по приходу нотификации о его выпадении.
Re[6]: Получить HWND ListBox выбора при разворачивании Combo
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 10:15
Оценка:
Здравствуйте, std.denis, Вы писали:

C>>А подвинуть его? А когда ListBox создается? Наверняка ведь поди винда не сходу его создает (я бы откладывал до упора, пока не понадобится)... Мне же надо посмотреть влезает он в экран или нет, и только потом двигать его...

SD>на 100% не уверен, но при создании комбобокса.
Та тут такое дело — что хех! А фиг его знает... Я бы откладывал создание, он сходу не нужен. Память-то можно теперь и не экономить (но когда ComboBox проектился-то!?! А как говорится "время потраченное на оптимизацию работы с памятью всегда оправдывает свои затраты"), но вот нагрузка лишняя на проц при создании точно ни к чему! Мало ли... Может у меня этих комбобоксов 20 тысяч штук на экран!?!
SD>Хотя подменить WndProc у списка можно по приходу нотификации о его выпадении.
Вот я и мучаюсь:
1) По уму сабклассинг красивше хука, смотрим только за контролом и никуда более не лезем.
2) С другой стороны: незабвенный код HCBT_ACTIVATE мне так и не пришел между прочим в хук... Хотя хук ставился в CBN_DROPDOWN. Поэтому в какой момент лезть к HWND ComboLBox не до конца понятно.
3) Солнце-то всходит, так что по идее....
Но с другой стороны... программисты мы или где? Разве не обязаны мы "чинить" абсолютно нормально работающую штуку, до тех пор пока она все-таки не сломается (и тут можно воскликнуть: "наконец-то займем нормальным делом!" )
Aml Pages Home
Re[7]: Получить HWND ListBox выбора при разворачивании Combo
От: std.denis Россия  
Дата: 22.05.09 10:49
Оценка:
EnumWindows показал, что у меня сейчас имеется 75 инстанции "ComboLBox". Так что вполне вероятно, что они плодятся таки при создании комбика.
Есть способ проверить экспериментальным путем — создать "20 тысяч штук" и посмотреть что покажет EnumWindows.
К тому же, если CB_GETCOMBOBOXINFO выдает вполне конкретное значение в поле hwndList, то я думаю на него можно надеяться — можно попробовать получить этот HWND сразу после создания.
Re[8]: Получить HWND ListBox выбора при разворачивании Combo
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 11:04
Оценка:
Здравствуйте, std.denis, Вы писали:

SD>EnumWindows показал, что у меня сейчас имеется 75 инстанции "ComboLBox". Так что вполне вероятно, что они плодятся таки при создании комбика.

Где гарантия что точно также в NT\98 например?
SD>Есть способ проверить экспериментальным путем — создать "20 тысяч штук" и посмотреть что покажет EnumWindows.
Не-е-е, это не наш метод! Сегодня Билли их создает сразу при создании ComboBox, завтра иначе, вчера в целях экономии еще как-то. Не! Закладываться настолько на внутренную имплементацию Винды неохота...
SD>К тому же, если CB_GETCOMBOBOXINFO выдает вполне конкретное значение в поле hwndList, то я думаю на него можно надеяться — можно попробовать получить этот HWND сразу после создания.
Да! Согласен, за этот совет спасибо! Я в принципе так и сделал, что сначала пытаемся получить hwndList через CB_GETCOMBOBOXINFO и только если CB_GETCOMBOBOXINFO ничего не дает, тогда начинаются бубны с хуком. Тут еще вопрос когда размеры ComboLBox выставляются!?! Я бы ставил в последний момент, т.е. где-то в районе CBN_DROPDOWN — просто инфы у Винды что да куда в этот момент явно больше (опять же в той же CBN_DROPDOWN можно маленько с CB_SETDROPPEDWIDTH пошуровать — размеры изменятся).
Aml Pages Home
Re[9]: Получить HWND ListBox выбора при разворачивании Combo
От: std.denis Россия  
Дата: 22.05.09 11:30
Оценка:
Честно говоря не пойму глубину проблемы:
1. после создания комбика попробовать получить хэндл его ComboLBox и если есть, то засабклассить
2. при CBN_DROPDOWN опять получаем хэндл и если он еще не засабклассен(*), то делаем это
3. в сабкласс-WndProc ждем WM_WINDOWPOSCHANGING и корректируем позицию на свое усмотрение
Вроде все вполне реализуемо и выглядит жизнеспособно

(*) Проверять можно либо сравнением адресов WNDPROC (не безопасно), или через SetProp/GetProp
Re[10]: Получить HWND ListBox выбора при разворачивании Comb
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 12:09
Оценка:
Здравствуйте, std.denis, Вы писали:

SD>Честно говоря не пойму глубину проблемы:

SD>1. после создания комбика попробовать получить хэндл его ComboLBox и если есть, то засабклассить
SD>2. при CBN_DROPDOWN опять получаем хэндл и если он еще не засабклассен(*), то делаем это

Как в чем глубина? Ну нафиг мне все сабклассенные ComboLBox разом? Мне же не нужен полный перехват процедуры!
Мне только сдвинуть его в момент разворота надо и ОК, остальное пускай сама делает.

Потом: писано это всё на MFC, и через класс наследник от CComboBox, если я засабклассю все экземпляры комбобоксов в проекте (а их может быть от 0 до дофига в момент Икс), то необходимо звать старенькую оконную процедуру через CallWindowProc. Причем звать ее из функции НЕ класса (ну или static-функции). А чтобы оконную процедуру звать, нужно знать ее адрес, и следовательно где-то его хранить.
И где? На уровне класса нельзя, т.к. мне надо обращаться к ней из той же static-класса, соответственно она вообще где-то сбоку должна быть.
А для чего всё это!?! Для того чтобы только подвинуть ComboLBox мне достаточно в любой момент времени сабклассить (ну или уж хучить) только один ComboBox, т.к. второй не может быть развернут в этот же момент (в пределах GUI-потока).

Тогда при моем варианте, (вешается на лету хук, малехо подвигали туда-сюда, и сняли хук. По сути можно тоже сделать и через сабклассинг) избавляемся от
а) кучи лишних сабклассов, которые в 99 из 100 нифига не делают, а ждут свой WM_WINDOWPOSCHANGING (ну да это ладно, фиг с ним).
б) избавляемся от необходимости где-то хранить данные с адресами обычной WNDPROC для каждого HWND. А вот это уже действительно плюс, т.к. напортачить со структурой что-то вроде map<HWND,WNDPROC> можно как два пальца об асфальт.

SD>3. в сабкласс-WndProc ждем WM_WINDOWPOSCHANGING и корректируем позицию на свое усмотрение

SD>Вроде все вполне реализуемо и выглядит жизнеспособно

SD>(*) Проверять можно либо сравнением адресов WNDPROC (не безопасно), или через SetProp/GetProp

Ну разве что так
Но все равно не нужно более одного сабклассенного ComboLBox в момент времени Икс (в пределах потока конечно).
PS: поковырял еще: все таки размер ComboLBox меняет именно после CBN_DROPDOWN, а не где-то раньше. Ну собственно что и было ожидаемо.
В общем, думаю что по любому надо делать через динамику хук\сабкласс поставили, погоняли немного ComboLBox по экрану, и сняли — вопрос только сабкласс или хук.
Хук тут разве что предпочтительнее для старых ОС: CB_GETCOMBOBOXINFO вообще поддерживается XP и старше, а GetComboBoxInfo не поддерживается в древних NT. А в хук hwnd ComboLBox по любому придет, не мытьем, так катаньем.
Но с другой стороны в хук тем же самым не мытьем, так катаньем много чего может придти, любая ошибка может вынурнуть вообще черт знает где...
Aml Pages Home
Re[11]: Получить HWND ListBox выбора при разворачивании Comb
От: kero Россия  
Дата: 22.05.09 13:14
Оценка:
Здравствуйте, Carc, Вы писали:

C>б) избавляемся от необходимости где-то хранить данные с адресами обычной WNDPROC для каждого HWND.


GWL_USERDATA, например

---
В дополнение к указанному выше примеру
Автор: xmen
Дата: 28.12.08
— вот здесь
Автор: kero
Дата: 05.08.07
ComboLBox в утилитке используется еще активнее, в частности — работает самостоятельным монитором окон (по кнопке "M/").
По всему, пашиным хозяевам позарез нужна война в Европе
(уверены — к ним не залетит, в предыдущих двух не залетало жеж)
Автор: kero
Дата: 21.07.14
Re[12]: Получить HWND ListBox выбора при разворачивании Comb
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 13:28
Оценка:
Здравствуйте, kero, Вы писали:

K>Здравствуйте, Carc, Вы писали:


C>>б) избавляемся от необходимости где-то хранить данные с адресами обычной WNDPROC для каждого HWND.


K>GWL_USERDATA, например

Не кошерно! Там может быть и что-то иное положенное коллегами. Лишние танцы с бубнами. Вот все-таки когда такой конфликт выйдет, поймать это будет не так-то просто. В смысле поймать-то может и несложно, но вот сообразить откуда ноги растут можно далеко не сразу.
В общем, переписал все через сабклассинг на лету. Если в двух словах, то на CBN_DROPDOWN вынимается HWND выпадающего списка, сабклассится, на первом WM_WINDOWPOSCHANGED список передвигается, и сабкласс тут же снимается.
Полет нормальный.

K>---

K>В дополнение к указанному выше примеру
Автор: xmen
Дата: 28.12.08
— вот здесь
Автор: kero
Дата: 05.08.07
ComboLBox в утилитке используется еще активнее, в частности — работает самостоятельным монитором окон (по кнопке "M/").

Не уловил к чему этот пример в данном контексте?
Aml Pages Home
Re[13]: Получить HWND ListBox выбора при разворачивании Comb
От: kero Россия  
Дата: 22.05.09 13:42
Оценка:
Здравствуйте, Carc, Вы писали:

K>>GWL_USERDATA, например

C>Не кошерно! Там может быть и что-то иное положенное коллегами.

Хм, я полагал — речь о вашей проге...
А насчет кошерности/некошерности — с этим к MS. Скажем, MessageBox (по крайней мере в XP) приходит к нам с уже занятой USERDATA.

K>> ComboLBox в утилитке используется еще активнее, в частности — работает самостоятельным монитором окон (по кнопке "M/").

C>Не уловил к чему этот пример в данном контексте?

Мне показалось, что у вас как-то не складывается с ComboLBox. Наверное — читал слишком по дмагонали ?
По всему, пашиным хозяевам позарез нужна война в Европе
(уверены — к ним не залетит, в предыдущих двух не залетало жеж)
Автор: kero
Дата: 21.07.14
Re[14]: Получить HWND ListBox выбора при разворачивании Comb
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 13:51
Оценка:
Здравствуйте, kero, Вы писали:

K>Здравствуйте, Carc, Вы писали:


K>>>GWL_USERDATA, например

C>>Не кошерно! Там может быть и что-то иное положенное коллегами.

K>Хм, я полагал — речь о вашей проге...

Та не! Все ок! Код мой, но этих комбоксов уже переписано немерянно, надо уж сделать так чтобы потом спокойно юзать повторно, и не париться с хитростями имплементациями... Собсна все началось с того, что в этот раз (ей-богу, последний, как и вчерашняя поправленная бага )понадобился комбобокс который может рисовать каждый айтем своим шрифтом с разными размерами.
K>А насчет кошерности/некошерности — с этим к MS. Скажем, MessageBox (по крайней мере в XP) приходит к нам с уже занятой USERDATA.
Ну так, а я про что!?! А тут мы! Да с API-функцией, да наперевес, да напролом! Вай как клёва получится!

K>>> ComboLBox в утилитке используется еще активнее, в частности — работает самостоятельным монитором окон (по кнопке "M/").

C>>Не уловил к чему этот пример в данном контексте?

K>Мне показалось, что у вас как-то не складывается с ComboLBox. Наверное — читал слишком по дмагонали ?

Ну в принципе GWL_USERDATA конечно штука знатная, но она хороша (имхо) для многопоточности.! А у меня там только один GUI-поток, остальные по идее не должны туда лезть — дык чего ж такую заначку как GWL_USERDATA на мелочи разменивать!?!
Aml Pages Home
Re[11]: Получить HWND ListBox выбора при разворачивании Comb
От: std.denis Россия  
Дата: 22.05.09 20:16
Оценка:
C>Потом: писано это всё на MFC, и через класс наследник от CComboBox, если я засабклассю все экземпляры комбобоксов в проекте (а их может быть от 0 до дофига в момент Икс), то необходимо звать старенькую оконную процедуру через CallWindowProc. Причем звать ее из функции НЕ класса (ну или static-функции). А чтобы оконную процедуру звать, нужно знать ее адрес, и следовательно где-то его хранить.
C>И где? На уровне класса нельзя, т.к. мне надо обращаться к ней из той же static-класса, соответственно она вообще где-то сбоку должна быть.
Я таки не понял, а чем же SetProp/GetProp в качестве хранилища адреса старого WndProc не подходят?
Re[12]: Получить HWND ListBox выбора при разворачивании Comb
От: Carc Россия http://www.amlpages.com/home.php
Дата: 22.05.09 21:00
Оценка:
Здравствуйте, std.denis, Вы писали:

C>>Потом: писано это всё на MFC, и через класс наследник от CComboBox, если я засабклассю все экземпляры комбобоксов в проекте (а их может быть от 0 до дофига в момент Икс), то необходимо звать старенькую оконную процедуру через CallWindowProc. Причем звать ее из функции НЕ класса (ну или static-функции). А чтобы оконную процедуру звать, нужно знать ее адрес, и следовательно где-то его хранить.

C>>И где? На уровне класса нельзя, т.к. мне надо обращаться к ней из той же static-класса, соответственно она вообще где-то сбоку должна быть.
SD>Я таки не понял, а чем же SetProp/GetProp в качестве хранилища адреса старого WndProc не подходят?
А нафига ее где-то хранить в окне если она (старая WNDPROC) одна и всегда одна, и только одна? В любой момент времени?
Aml Pages Home
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.