Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.07.25;
Скачать: [xml.tar.bz2];

Вниз

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

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.07.25;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.01 c
14-1120151731
kaif
2005-06-30 21:15
2005.07.25
Должен ли гурман жарить на тефлоне?


1-1120566147
K
2005-07-05 16:22
2005.07.25
Смежный компонент TreeView и ListView


1-1120950529
Serrh
2005-07-10 03:08
2005.07.25
Модули (Uses)


6-1113413845
Дельфин
2005-04-13 21:37
2005.07.25
Интернетовский IP-адрес


1-1120460209
maktub
2005-07-04 10:56
2005.07.25
Преобразование форматов форм





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский