Форум: "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