Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.07.25;
Скачать: CL | DM;

Вниз

Дочерние контролы дочерних контролов :-)   Найти похожие ветки 

 
gdaujk ©   (2005-05-28 04:54) [0]

Я создаю главное окно приложения, а в нём, GroupBox. Далее я создаю элемент управления (напимер кнопку), для которого родительским окном будет не главное окно, а GroupBox. Скажите, как мне теперь обрабатывать сообщения от этой кнопки? Главное окно их вроде не получает. Пробовал создать процедуру обработки событий для GroupBox, но ничего не вышло :-(.

Поможите чем можете и родина вас не забудет :-)


 
-=XP=- ©   (2005-05-28 10:56) [1]

Кнопка (BUTTON) - тоже окно.


 
tesseract   (2005-05-28 11:29) [2]

в Delphi есть RTTI. Благодяря которому можно динамически переназначать методы объектов. В твоём случае примерно так:

MyButtonsArray[MyButtonIndex].OnClick:=MyButtonClickHandlerProc


 
gdaujk ©   (2005-05-28 11:53) [3]

>-=XP=- [1]

То есть ты предлагаешь мне всё-таки писать процедуру обработки событий для GroupBox? Это можно, толко каких событий? Я посмотрел с помощью WinSight"а, GroupBox получает при нажатии кнопочки уйму сообщений. На сколько я понял, в этой уйме главное WM_PARENTNOTIFY, но не несёт информащии об ID/HWND нажатой кнопки.

А вот кнопочка оная получает WM_LBUTTONDOWN / UP. Может мне попробовать приделать оконную процедуру именно к ней? Вариант по-моему не плохой: для всех кнопок в GroupBox"е написать одну процедуру, и обрабатывать в ней WM_LBUTTONDOWN / UP.

Подскажите, в каком направлении двигаться.


 
gdaujk ©   (2005-05-28 12:17) [4]

>tesseract [2]

OnClick у тебя указатель?

Я пишу на API, ни каких OnClick нету. Оконную процедуру, на сколько я понимаю, можно заменить только с помощью SetWindowLong. Это при использовании VCL (TButton) можно просто присвоить свойству OnClick адрес новой процедуры. Но OnClick - это ни как не оконная процедура.

Вообще не в этом вопрос. Вопроса два:
1). У какого контрола заменять процедуру?
2). Какое сообщение обрабатывать?

Или один общий вопрос: как обработать сообщения от кнопки, описанной в вопросе ?


 
gdaujk ©   (2005-05-28 14:19) [5]

Как обработать сообщения от кнопки, описанной в вопросе ?


 
Marser ©   (2005-05-28 15:37) [6]


> gdaujk ©   (28.05.05 14:19) [5] [Новое
>сообщение][Ответить]
> Как обработать сообщения от кнопки, описанной в
> вопросе ?

А почему с GroupBox не вышло?
В крайнем случае можно заменить обработчик.


 
-=XP=- ©   (2005-05-28 16:03) [7]

А вот кнопочка оная получает 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()).

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


 
Marser ©   (2005-05-28 16:07) [8]


> И дополнительно: породить класс от TObject. Объекты
>могут содержать в себе обработчики Windows-сообщений:
>
>  TMyButton = class(TObject)

Только не от TObject, а от TButton


 
-=XP=- ©   (2005-05-28 16:15) [9]

Только не от TObject, а от TButton

Да нет.
TButton - это VCL.
Автор же предпочитает Pure WinAPI. :-/
Так что все же, TObject.

:)

Автору: Посмотрите в сторону KOL и/или FreePascal ;)


 
Marser ©   (2005-05-28 16:18) [10]


>TButton - это VCL.
> Автор же предпочитает Pure WinAPI. :-/

Тогда во-первых такой инкапсуляции маловато будет, а во-вторых, почему бы не обрабатывать wm_command или заменить обработчик кнопки?


 
Cobalt ©   (2005-05-28 16:19) [11]

2 gdaujk ©   (28.05.05 14:19) [5]
Только не "от кнопки", а  "для кнопки" :)
SetWindowLong - оконная процедура.
Il Voila!


 
-=XP=- ©   (2005-05-28 16:23) [12]

Тогда во-первых такой инкапсуляции маловато будет

Типа, не понял. Это о чем?

во-вторых, почему бы не обрабатывать wm_command или заменить обработчик кнопки

А это уже как автор решит.
В смысле, "Возможны варианты" (С).


 
Marser ©   (2005-05-28 16:25) [13]


> Типа, не понял. Это о чем?

Начинает уже напоминать VCL-кнопку, но ещё ничего нет. Кстати, а такие конструкции на голом TObject точно проходят?


 
-=XP=- ©   (2005-05-28 16:55) [14]

Начинает уже напоминать VCL-кнопку, но ещё ничего нет
Ну да. Достаточно обойтись неким минимумом. Если прописывать весь функционал - тогда зачем это нужно? - есть VCL. Смысл то в том, чтобы до минимума сократить объем программы, насколько я понимаю. Ну и еще - глубже изучить принципы работы Windows. Друго надобности в таких "изысканиях" не вижу.

Кстати, а такие конструкции на голом TObject точно проходят?
А почему бы им не пройти? "Прикрутить" оконную процедуру - и вперед.


 
gdaujk ©   (2005-05-28 23:34) [15]

Итак. Я заменил поцедуру обработки сообщений кнопочки:
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.


 
Marser ©   (2005-05-28 23:40) [16]


> gdaujk ©   (28.05.05 23:34) [15] [Новое
> сообщение][Ответить]

DefWindowProc здесь не проходит. Тебе следовало бы сначала получить адрес стандартного обработчика
butproc:Pointer;
....
butproc:=pointer(GetWindowLong(mbut,gwl_wndproc));
...
И затем в самом обработчике вместо DefWindowProc вызвать
Result:=CallWindowProc(l,wnd,msg,wparam,lparam);


 
Marser ©   (2005-05-28 23:58) [17]


> Result:=CallWindowProc(butproc,wnd,msg,wparam,lparam);

Прошу прощения.


 
gdaujk ©   (2005-05-29 00:07) [18]

Блин, как всё сложно в 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)

А потом регистрируют этот класс и создают окно именно с этим классом. Может также сделать?


 
gdaujk ©   (2005-05-29 00:10) [19]

>Marser [16, 17]

Щас попробуем, хотя интересно, [18] будет работать или нет :-)


 
gdaujk ©   (2005-05-29 00:26) [20]

>Marser [16, 17]

Ты прав. Большое спасибо. Наверное и вариант [18] должен пахать.

Но у меня сл. вопрос. Всё-таки если заменять процедуру не у кнопочки, а у GroupBox, то какое сообщение надо отлавливать, что бы узнать о нажатии дочерней кнопки. Мой вариант ответа - WM_PARENTNOTIFY, но при этом прийдётся сопоставлять координаты курсора с координатами кнопочки, а это делать лень :-). Может кто чего получше предложит?


 
Marser ©   (2005-05-29 00:35) [21]

Можно использовать 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;


 
Marser ©   (2005-05-29 00:40) [22]


> gdaujk ©   (29.05.05 0:26) [20]

Применяя [21], можно обойтись без подмены процедур для Button. Как оказывается, такая подмена нужна в основном для не очень стандартных действий, вроде перерисовки. В остальных случаях всё решается с помощью обработки WM_COMMAND в процедуре родительского окна.


 
gdaujk ©   (2005-05-29 01:09) [23]

>Marser [22]

Я к тому и клонил, что бы не писать процедуры для каждой кнопки. И ты как всегда прав! Вариант работает только с CallWindowProc.

Всем принимавшим участие в обсуждении большое СПАСИБО.

Щас оформим следующий вопрос на форум :-)


 
gdaujk ©   (2005-05-29 05:51) [24]

Это ишшо не всё:-)

В ситуации именно с GroupBox и Button, последняя прописовывается с черными краями, которые по идее должны быть прозрачными. И в чём косяк?

PS: первоначально родительским окном кнопки я делал TabControl, и всё было прекрасно...


 
Marser ©   (2005-05-29 18:38) [25]


> И в чём косяк?

А чёрт его знает... В стилях, возможно...


 
gdaujk ©   (2005-05-30 12:04) [26]

Итак. После изучения VCL реализации GroupBox понял следующее. Там GroupBox - это кнопка без стиля WS_GROUPBOX, а внешний вид (рамочка, текст) рисуется с помощью UxTheme. При этом дочерние элементы прописовываются нормально.

Попробовал заменить GroupBox в моей задаче на Button (просто убрал стиль WS_GROUPBOX), и дочерняя кнопка прорисовалась на этой кнопке нормально.

Далее с помощью WinSight изучил несколько окошек Explorer"а на предмет взаимного отношения GroupBox и Button. Вывод: GroupBox никогда не используется как родительский для других элементов управления. По-видимому он задумывался только как часть оформления окон...

Ладно, общий принцип создания дочерних контролов мне понятен.  Всем спасибо.



Страницы: 1 вся ветка

Текущий архив: 2005.07.25;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.044 c
4-1117192528
RedStranger
2005-05-27 15:15
2005.07.25
Как послать e-mail?


9-1113467814
parovoZZ
2005-04-14 12:36
2005.07.25
Техника QuadTree


14-1120449316
ROOT
2005-07-04 07:55
2005.07.25
Какую выбрать компанию?


3-1118394819
Andy Nortsov
2005-06-10 13:13
2005.07.25
Как правильно работать с ADO+ODBC+FireBird+Delphi?


14-1120503313
vecna
2005-07-04 22:55
2005.07.25
виртуальные com-порты