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

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

Ownerdraw Button Control и region'ы


Страницы:   1 2

Nick Denry ©   (2005-09-09 15:56:00) 

Народ подскажите , плиз, почему кнопка  (обычный 'Button' class) не  изменяет  свою форму, если установить ей регион? Может имеет смысл ее сабклассировать, чтобы перехватывать какие то ее собщения?


Nick Denry   (2005-09-14 20:04:00) [1]

Во-вторых, вызывается ли UnregisterClass в библиотеке при ее освобождении

да на dll_process_detach

Во-первых, зачем библиотеку освобождать ?

ну я загружаю ее динамически, поэтому по хорошему, ее надо освобождать...

но впринципе, никакой необходимости загружать динамически нет, я просто сделал "по инерции", попробую статическую загрузку.

ПОЧЕМУ ЛЮДИ НИКОГДА НЕ ПИШУТ ДЕТАЛЬНОЕ ОПИСАНИЕ ПРОБЛЕМЫ

(ничего страшного :)
(а может и очень страшно, но я не специально и уж тем более не партизан :)

Я лично предположил, что такая проблема должна быть достаточно известна  
или имеет известное логическое объяснение и

выгрузка библиотеки (после оконного цикла):

While GetMessage(Mesg,0,0,0) do
begin
 TranslateMessage(Mesg);
 DispatchMessage(Mesg);
end;
FreeLibrary(stdCtrlsLib);

end.


дало отсутвие появления исключения.

Если освобождать на WM_DESROY:

то получаю следующее исключение:

---------------------------
Dialog: test.exe - Ошибка приложения
---------------------------
Инструкция по адресу "0x00793db0" обратилась к памяти по адресу "0x00793db0". Память не может быть "read".

"ОК" -- завершение приложения
"Отмена" -- отладка приложения
---------------------------
OK   Отмена  
---------------------------


Игорь Шевченко   (2005-09-14 10:11:00) [2]


> А вот когда я на
> WM_DESTROY:
>           begin
> {             Освобождаю библиотеку}
>             FreeLibrary (controlDll); - то прога вызывает
> исключение, т.к. я так понимаю еще обращается к процедуре
> окна самого контрола, а тут библиотека как бы убирается.
> ..
>
>           end;


Во-первых, зачем библиотеку освобождать ?
Во-вторых, вызывается ли UnregisterClass в библиотеке при ее освобождении
В-третьих,  и самое главное:

ПОЧЕМУ ЛЮДИ НИКОГДА НЕ ПИШУТ ДЕТАЛЬНОЕ ОПИСАНИЕ ПРОБЛЕМЫ, НАПРИМЕР, КАКОЕ ИСКЛЮЧЕНИЕ У НИХ ВОЗНИКАЕТ ? У ОТВЕЧАЮЩИХ ЧАЩЕ ВСЕГО НЕТ ПЕРЕД ГЛАЗАМИ ЭКРАНА АВТОРА ВОПРОСА.

ЕСЛИ КТО ИЗ АВТОРОВ ВОПРОСОВ СЧИТАЕТ СЕБЯ ПАРТИЗАНОМ, ПОПАВШИМ В ГЕСТАПО И БУДЕТ ТЕРПЕТЬ ПЫТКИ, НО НЕ ВЫДАСТ ВОЕННУЮ ТАЙНУ, ЭТО ЕГО, АВТОРА ВОПРОСА, ЛИЧНЫЕ ПРОБЛЕМЫ И ШАНСЫ ЕГО ПОЛУЧИТЬ ПОМОЩЬ РЕЗКО УМЕНЬШАЮТСЯ.

Извиняюсь за крик, наболело.


Nick Denry   (2005-09-13 19:01:00) [3]

на этапе инициализации DLL класс регистрируется

Т.е. мне надо сделать что-то типа функции initCommonControls?

Или достаточно при DLL_PROCESS_ATTACH зарегистрировать этот класс?

И еще, для назначения контролу индивидуальных параметров я использую SetProp/GetProp,

потому что глобальные переменные принимают одинаковые значения для всех контролов (т.е. для последнего, их использующего), а локольные (в процедуре обработки сообщений окна) почему-то не инициализируются - это правильно (а контролов должно быть рпоизвольное количество, само собой разумеется)?

и вот еще вопрос, когда я могу выгрузить такую библиотеку безопасно?

У меня сначала было так:

{код приложения (примерно, пишу не из дома), использующего длл, функция WndProc}


...(Глобальные переенные)

var
  controlDll: THandle;
  graphButton : HWND;

WM_CREATE:
         begin
         
          controlDll := LoadLibrary('libname.dll');
          graphButton := CreateWindow('antGraphBtnClass', ...);
          SetProp(graphButton, 'image_up', hBitmap_handle);
          {ну и т.д.}
         end;

А вот когда я на
WM_DESTROY:
          begin
{             Освобождаю библиотеку}
            FreeLibrary (controlDll); - то прога вызывает исключение, т.к. я так понимаю еще обращается к процедуре окна самого контрола, а тут библиотека как бы убирается...

          end;

так вот когда ее можно нормально освободить - после цикла

while GetMessage ???


Игорь Шевченко   (2005-09-13 14:37:00) [4]

Nick Denry ©   (13.09.05 13:42) [21]


> Требуется компонент (не в дельфийском понятии этого слова
> :),


Это называется Control. Делай и воздастся тебе.


> Я не знаю, насколько использовние контролов (о, слово наконец-то
> вспомнил!) со стилем CS_GLOBALCLASS оправданно и безопасно....


И оправдано и безопасно. Располагается он в DLL, также, как и Common Controls, на этапе инициализации DLL класс регистрируется.

Nick Denry ©   (13.09.05 13:53) [22]


> Win32Check((FButtonRgn <> 0) and (SetWindowRgn (FButton,
> FButtonRgn, true) <> 0));


if not ((FButtonRgn <> 0) and (SetWindowRgn (FButton,
> FButtonRgn, true) <> 0)) then
 raise Exception.Create (SysErrorMessage(GetLastError));

одно и то же.


Nick Denry   (2005-09-13 13:53:00) [5]

Игорь, а что такое
Win32Check((FButtonRgn <> 0) and (SetWindowRgn (FButton, FButtonRgn, true) <> 0));

Я первый раз такую конструкцию вижу...


Nick Denry   (2005-09-13 13:42:00) [6]

Требуется компонент (не в дельфийском понятии этого слова :),

кнопка, имеющая след. параметры:

Графическа кнопка произвольной формы (задется маской), имеет четыре (т.е. три состояния, на каждое из которых отрисовывается своя картинка) -

1. Кнопка отжата (1ая картинка)
2. Кнопка нажата (2ая картика)
3. Мышь над (сотсюда суперклассинг, сообщние WM_MOUSEOVER, 3я картинка)

Так же при нажатии/отжатии/наведении кнопка менят цвет надписи, на 3 заданных.

+ Возможность назначить Шрифт, которым будет отрисовывться текст на кнопке.

Кнопка должна быть расположенна в множстве диалогов программы (в ресурсах, отсюда и CS_GLOBALclASS) и не должн быть размазанна по всму коду (т.е. код кнопки в проекте должен встречаться один раз (т.е. вроде как Dll)- в остльных модулях только создание, уничтожение и назначение свойств (я сделал через SetProp/GeProp).

Вопрос один и то наверное не существенный - сделать это а базе виндовой кнопки или как я - на баз обычного окна - имитирующего поведение кнопки.

Я не знаю, насколько использовние контролов (о, слово наконец-то вспомнил!) со стилем CS_GLOBALCLASS оправданно и безопасно....


Игорь Шевченко   (2005-09-13 13:20:00) [7]

Nick Denry ©   (13.09.05 13:03) [19]


> Я вот только теперь чего думаю, обратно на кнопки перейти
>


А я не знаю, что тебе требуется. Как назначить регион окну кнопки, вроде разобрались, причем тут саб/суперклассинг, я не совсем понимаю.


Nick Denry   (2005-09-13 13:03:00) [8]

2Игорь Шевченко ©   (13.09.05 10:13) [17]

Ага, вот теперь можно кричать, размахивать руками и говорить, я так и знал, я так и думал... :)

Я вот только теперь чего думаю, обратно на кнопки перейти и свой контрол выкинуть нафиг или не мучаться с суперклассированием?


Игорь Шевченко   (2005-09-13 10:14:00) [9]

Удалено модератором
Примечание: Дубль


Игорь Шевченко   (2005-09-13 10:13:00) [10]

Nick Denry ©   (13.09.05 00:21) [15]


> Ну теперь собственно говоря между WS_POPUP +   Windows.SetParent(Button,
> Handle); и WS_CHILD;


Все решается очень просто, при создании окна кнопки добавь ей стиль WS_CLIPSIBLINGS.

Вот такой пример работает:

procedure TForm1.Button1Click(Sender: TObject);
var
 ButtonRect: TRect;
begin
 FButton := CreateWindowEx(0, 'BUTTON','_OK_',
   WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGSor BS_PUSHBUTTON,
   10, 10, 70, 25, Handle, 0, HInstance, nil);
 Windows.GetWindowRect(FButton, ButtonRect);
 OffsetRect(ButtonRect, -ButtonRect.Left, -ButtonRect.Top);
 FButtonRgn := CreateEllipticRgnIndirect (ButtonRect);
 Win32Check((FButtonRgn <> 0) and (SetWindowRgn (FButton, FButtonRgn, true) <> 0));
end;


Без этого стиля придется каждый раз при перерисовке вызывать функции InvalidateRect у родительского окна и UpdateWindow у дочернего.

А ларчик открывается просто: создаешь обычную кнопку и winapi'шную кнопку, смотришь Spy++, чем окна отличаются.


Nick Denry   (2005-09-13 00:23:00) [11]

правда я с испугу свой контрол реализовал в Dll и CS_GLOBALCLASS :)

Впринципе, получилось даже интереснесней - поддержка 4 состояний и PNG :)


Nick Denry   (2005-09-13 00:21:00) [12]

Ну теперь собственно говоря между WS_POPUP +   Windows.SetParent(Button, Handle); и WS_CHILD;


Турист   (2005-09-10 12:37:00) [13]

>Nick Denry ©   (10.09.05 12:01) [13]
>интресно, в чем все-таки разница? :)
Между чем ?


Nick Denry   (2005-09-10 12:01:00) [14]

Да, последний вариант действительно работает...

интресно, в чем все-таки разница? :)


Турист   (2005-09-09 23:59:00) [15]

Наверно, это все-таки неправильно


procedure TForm1.Button2Click(Sender: TObject);
var
 Button: Hwnd;
begin
 Button := CreateWindow('BUTTON','_OK_', WS_POPUP,
                        10, 10, 70, 25, 0, 0, HInstance, nil);
 SetWindowRgn(Button, CreateEllipticRgn(0, 0, 70, 25), False);
 Windows.SetParent(Button, Handle);
 ShowWindow(Button, SW_SHOW)
end;


Nick Denry   (2005-09-09 22:09:00) [16]

Да , но с виндовой кнопкой почему-то не работает


y-soft   (2005-09-09 20:08:00) [17]

>Nick Denry ©   (09.09.05 19:22) [9]

Все рисуется и обрабатывается (пример из книги Марко Канту, Тим Гуч с Джоном Ф. Лэм "Delphi. Руководство разработчика"):

http://y-soft.comsignal.ru/Delphi/DDHROUND_PAS.HTM


Nick Denry   (2005-09-09 19:22:00) [18]

Отсечения воспроизведения все равно не происходит.

Мне кажется, что

===
int SetWindowRgn(
   HWND hWnd,
   HRGN hRgn,
   BOOL bRedraw // window redraw flag
  );
----
Remarks

If the bRedraw parameter is TRUE, the system sends the WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window.
====

у кнопок на 2 этих сообщения какая-то нестандартная обработка...


Игорь Шевченко   (2005-09-09 18:32:00) [19]

Nick Denry ©   (09.09.05 18:30) [7]


> Т.е. ты хочешь сказать, что регион должен создаваться как
>


Вообще-то да :)


Nick Denry   (2005-09-09 18:30:00) [20]

Т.е. ты хочешь сказать, что регион должен создаваться как

btnRgn := CreateEllipticRgn(0,0,20,15);

?


Страницы:   1 2

Наверх

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