Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Дочерние контролы дочерних контролов :-) [D7, WinXP]


Страницы:   1 2

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()).

Имхо, класс - наиболее оптимальное решение.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо