![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Дочерние контролы дочерних контролов :-) [D7, WinXP]
gdaujk © (2005-05-28 04:54:00)Я создаю главное окно приложения, а в нём, GroupBox. Далее я создаю элемент управления (напимер кнопку), для которого родительским окном будет не главное окно, а GroupBox. Скажите, как мне теперь обрабатывать сообщения от этой кнопки? Главное окно их вроде не получает. Пробовал создать процедуру обработки событий для GroupBox, но ничего не вышло :-(.
Поможите чем можете и родина вас не забудет :-)
gdaujk (2005-05-30 12:04:00) [1]Итак. После изучения VCL реализации GroupBox понял следующее. Там GroupBox - это кнопка без стиляWS_GROUPBOX, а внешний вид (рамочка, текст) рисуется с помощью UxTheme. При этом дочерние элементы прописовываются нормально.
Попробовал заменить GroupBox в моей задаче на Button (просто убрал стиль WS_GROUPBOX), и дочерняя кнопка прорисовалась на этой кнопке нормально.
Далее с помощью WinSight изучил несколько окошек Explorer'а на предмет взаимного отношения GroupBox и Button. Вывод: GroupBox никогда не используется как родительский для других элементов управления. По-видимому он задумывался только как часть оформления окон...
Ладно, общий принцип создания дочерних контролов мне понятен. Всем спасибо.
Marser (2005-05-29 18:38:00) [2]
> И в чём косяк?
А чёрт его знает... В стилях, возможно...
gdaujk (2005-05-29 05:51:00) [3]Это ишшо не всё:-)
В ситуации именно с GroupBox и Button, последняя прописовывается с черными краями, которые по идее должны быть прозрачными. И в чём косяк?
PS: первоначально родительским окном кнопки я делал TabControl, и всё было прекрасно...
gdaujk (2005-05-29 01:09:00) [4]>Marser [22]
Я к тому и клонил, что бы не писать процедуры для каждой кнопки. И ты как всегда прав! Вариант работает только с CallWindowProc.
Всем принимавшим участие в обсуждении большое СПАСИБО.
Щас оформим следующий вопрос на форум :-)
Marser (2005-05-29 00:40:00) [5]
> gdaujk © (29.05.05 0:26) [20]
Применяя [21], можно обойтись без подмены процедур для Button. Как оказывается, такая подмена нужна в основном для не очень стандартных действий, вроде перерисовки. В остальных случаях всё решается с помощью обработки WM_COMMAND в процедуре родительского окна.
Marser (2005-05-29 00:35:00) [6]Можно использовать WM_COMMAND. Причём, обрабатывать его нужно в оконной процедуре GroupBox. Примерно вот так:
function GroupBProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;
var wmn:word;
wnd:hwnd;
Begin
case msg of
wm_command:begin
wmn:=wparam shr 16;
wnd:=hwnd(lparam);
if (wnd=butwnd)and(wmn=bn_clicked) then
messagebox(0,'Кнопка нажата','BUTTON',mb_ok);
end;
else Result:=DefWindowProc(wnd,msg,wparam,lparam);
{Ввиду того, что я не испытывал этот вариант, могу предположить, что может понадобиться применение приёма, аналогичного предыдущему уже к GroupBox}
end;
End;
gdaujk (2005-05-29 00:26:00) [7]>Marser [16, 17]
Ты прав. Большое спасибо. Наверное и вариант [18] должен пахать.
Но у меня сл. вопрос. Всё-таки если заменять процедуру не у кнопочки, а у GroupBox, то какое сообщение надо отлавливать, что бы узнать о нажатии дочерней кнопки. Мой вариант ответа - WM_PARENTNOTIFY, но при этом прийдётся сопоставлять координаты курсора с координатами кнопочки, а это делать лень :-). Может кто чего получше предложит?
gdaujk (2005-05-29 00:10:00) [8]>Marser [16, 17]
Щас попробуем, хотя интересно, [18] будет работать или нет :-)
gdaujk (2005-05-29 00:07:00) [9]Блин, как всё сложно в VCL :-( Там вроде не подменяют окошечную процедуру после создания TWinControl, а при создании сначала создают некий субкласс - класс BUTTON, только Instance=hInctance и
Stile = BUTTON.Stile and not (CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS) or (CS_VREDRAW or CS_HREDRAW)
А потом регистрируют этот класс и создают окно именно с этим классом. Может также сделать?
Marser (2005-05-28 23:58:00) [10]
> Result:=CallWindowProc( butproc,wnd,msg,wparam,lparam);
Прошу прощения.
Marser (2005-05-28 23:40:00) [11]
> gdaujk © (28.05.05 23:34) [15] [Новое
> сообщение][Ответить]
DefWindowProc здесь не проходит. Тебе следовало бы сначала получить адрес стандартного обработчика
butproc:Pointer;
....
butproc:=pointer(GetWindowLong(mbut,gwl_wndproc));
...
И затем в самом обработчике вместо DefWindowProc вызвать
Result:=CallWindowProc(l,wnd,msg,wparam,lparam);
gdaujk (2005-05-28 23:34:00) [12]Итак. Я заменил поцедуру обработки сообщений кнопочки:
SetWindowLong(Btn, GWL_WNDPROC, Integer(@ButtonFunc)).
И вроде успешно, SetWindowLong <> 0. Но теперь кнопка вообще не прорисовывается ?!
Вот моя окошечная процедура для кнопки:
function ButtonFunc(Wnd: HWND; Msg: Integer; aWParam: WPARAM; aLParam: LPARAM): Integer; stdcall;
begin
case Msg of
WM_LBUTTONUP:
MessageBox(Wnd, 'Left Button Up', '', MB_ICONEXCLAMATION);
end;
Result := DefWindowProc(Wnd, Msg, aWParam, aLParam);
end;
У меня подозрение, что проблемма в DefWindowProc.
-=XP=- (2005-05-28 16:55:00) [13]Начинает уже напоминать VCL-кнопку, но ещё ничего нет
Ну да. Достаточно обойтись неким минимумом. Если прописывать весь функционал - тогда зачем это нужно? - есть VCL. Смысл то в том, чтобы до минимума сократить объем программы, насколько я понимаю. Ну и еще - глубже изучить принципы работы Windows. Друго надобности в таких "изысканиях" не вижу.
Кстати, а такие конструкции на голом TObject точно проходят?
А почему бы им не пройти? "Прикрутить" оконную процедуру - и вперед.
Marser (2005-05-28 16:25:00) [14]
> Типа, не понял. Это о чем?
Начинает уже напоминать VCL-кнопку, но ещё ничего нет. Кстати, а такие конструкции на голом TObject точно проходят?
-=XP=- (2005-05-28 16:23:00) [15]Тогда во-первых такой инкапсуляции маловато будет
Типа, не понял. Это о чем?
во-вторых, почему бы не обрабатывать wm_command или заменить обработчик кнопки
А это уже как автор решит.
В смысле, "Возможны варианты" (С).
Cobalt (2005-05-28 16:19:00) [16]2 gdaujk © (28.05.05 14:19) [5]
Только не "от кнопки", а "для кнопки" :)
SetWindowLong - оконная процедура.
Il Voila!
Marser (2005-05-28 16:18:00) [17]
>TButton - это VCL.
> Автор же предпочитает Pure WinAPI. :-/
Тогда во-первых такой инкапсуляции маловато будет, а во-вторых, почему бы не обрабатывать wm_command или заменить обработчик кнопки?
-=XP=- (2005-05-28 16:15:00) [18]Только не от TObject, а от TButton
Да нет.
TButton - это VCL.
Автор же предпочитает Pure WinAPI. :-/
Так что все же, TObject.
:)
Автору: Посмотрите в сторону KOL и/или FreePascal ;)
Marser (2005-05-28 16:07:00) [19]
> И дополнительно: породить класс от TObject. Объекты
>могут содержать в себе обработчики Windows-сообщений:
>
> TMyButton = class(TObject)
Только не от TObject, а от TButton
-=XP=- (2005-05-28 16:03:00) [20]А вот кнопочка оная получает WM_LBUTTONDOWN / UP. Может мне попробовать приделать оконную процедуру именно к ней? Вариант по-моему не плохой: для всех кнопок в GroupBox'е написать одну процедуру, и обрабатывать в ней WM_LBUTTONDOWN / UP.
Да. Так оптимальнее всего.
И дополнительно: породить класс от TObject. Объекты могут содержать в себе обработчики Windows-сообщений:
TMyButton = class(TObject)
private
procedure WMLButtonDown(var Msg: TMessage); message WM_Lbuttondown;
Посмотрите, как реализована работа с сообщениями в TControl. Особенно обратите внимание, как "прикручиваются" сообщения окна (через Handle) к объекту (TObject.Dispath()).
Имхо, класс - наиболее оптимальное решение.