Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

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


dmk ©   (21.03.17 22:54

У меня есть такой вариант, но он работает только вне класса:

function ClientWindowProc(wnd: HWND; msg: cardinal; wparam, lparam: integer): integer; stdcall;
var
 P: pointer;
 Style: dword;
 ExStyle: dword;

begin
 P := Pointer(GetWindowLong(wnd, GWL_USERDATA));

 case msg of
 WM_NCCALCSIZE:
 begin
   Style := GetWindowLong(wnd, GWL_STYLE);
   ExStyle := GetWindowLong(wnd, GWL_EXSTYLE);

   //Убираем скроллы MDI-окна
   if (Style and (WS_HSCROLL or WS_VSCROLL)) <> 0 then
   begin
     Style := Style and not (WS_HSCROLL or WS_VSCROLL);
     SetWindowLong(wnd, GWL_STYLE, Style);
   end;

   //Убираем выступ в клиентской области MDI-окна
   if (ExStyle and (WS_EX_CLIENTEDGE)) <> 0 then
   begin
     ExStyle := (ExStyle and not WS_EX_CLIENTEDGE);
     SetWindowLong(wnd, GWL_EXSTYLE, ExStyle);
   end;

   Result := S_OK;
 end;//WM_NCCALCSIZE
 end;//case

 Result := CallWindowProc(P, Wnd, Msg, WParam, LParam);
end;

//................................................................................ ......................................

procedure InitClientProc(ClientHandle: integer);
begin
 if (ClientHandle <> 0) then
 begin
   //Данные пользователя могут быть заняты
   if GetWindowLongPtr(ClientHandle, GWL_USERDATA) = 0 then
   begin
     SetWindowLongPtr(ClientHandle, GWL_USERDATA,
       SetWindowLongPtr(ClientHandle, GWL_WNDPROC, NativeUInt(@ClientWindowProc)));
   end;
 end;
end;


dmk ©   (21.03.17 23:17[1]

Мне нужно принимать сообщение от родительского окна в безоконный класс.


dmk ©   (21.03.17 23:18[2]

В гугле полно примеров, но все нерабочие.


dmk ©   (22.03.17 02:13[3]

Делаю так:

type TCallWndProc = function(Wnd: HWND; Msg: cardinal; WParam, LParam: integer): integer of object; stdcall;

//в классе
 FCallWndProc: TCallWndProc;

function TWindow64.ClientWindowProc(wnd: HWND; msg: cardinal; wparam, lparam: integer): integer; stdcall;
var
P: pointer;
Style: dword;
ExStyle: dword;

begin
P := Pointer(GetWindowLong(wnd, GWL_USERDATA));

case msg of
WM_NCCALCSIZE:
begin
  Style := GetWindowLong(wnd, GWL_STYLE);
  ExStyle := GetWindowLong(wnd, GWL_EXSTYLE);

  //Убираем скроллы MDI-окна
  if (Style and (WS_HSCROLL or WS_VSCROLL)) <> 0 then
  begin
    Style := Style and not (WS_HSCROLL or WS_VSCROLL);
    SetWindowLong(wnd, GWL_STYLE, Style);
  end;

  //Убираем выступ в клиентской области MDI-окна
  if (ExStyle and (WS_EX_CLIENTEDGE)) <> 0 then
  begin
    ExStyle := (ExStyle and not WS_EX_CLIENTEDGE);
    SetWindowLong(wnd, GWL_EXSTYLE, ExStyle);
  end;

  Result := S_OK;
end;//WM_NCCALCSIZE
end;//case

Result := CallWindowProc(P, Wnd, Msg, WParam, LParam);
end;

procedure TWindow64.InitClientWndProc(AHandle: integer);
var
 L: NativeInt;

begin
 if (AHandle <> 0) then
 begin
   //Данные пользователя могут быть заняты
   if GetWindowLongPtr(AHandle, GWL_USERDATA) = 0 then
   begin
     FCallWndProc := ClientWndProc;
     L := SetWindowLongPtr(AHandle, GWL_WNDPROC, NativeUInt(@FCallWndProc));
     L := SetWindowLongPtr(AHandle, GWL_USERDATA, L);
   end;
 end;
end;


Проходит один цикл и виснет.
Если не делать частью класса - все в порядке, но переменные класса не видны.
Можно сделать вызов, если ClientWindowProc часть класса?


Leonid Troyanovsky ©   (22.03.17 08:47[4]


> dmk ©   (22.03.17 02:13) [3]

В 32 битные времена этому служил MakeObjectInstance.

--
Regards, LVT.


Игорь Шевченко ©   (22.03.17 10:48[5]

Ты по человечески можешь сказать, что тебе надо ? Существует масса способов решения самых разнообразных задач


dmk ©   (22.03.17 13:15[6]

>Ты по человечески можешь сказать, что тебе надо ?
У меня есть класс графических объектов, которые рисуются в буфере, а потом выводятся на экран. Мне надо им петлю сообщений вставить. Чтобы они WM_MOUSE..... получали. Вроде как компоненты, но окна они не имеют. Можно конечно из базового окна им передавать координаты, но есть недотаток, это можно сделать только между WM_PAINT, а отрисовка по WM_PAINT иногда сильно тормозит (когда их много) и мне надо прервать отрисовку и начать заново. Насколько я знаю сообщения передаются асинхронно и это то что мне надо.


dmk ©   (22.03.17 13:19[7]

>В 32 битные времена этому служил MakeObjectInstance.
Это немного не то. Механизм вызова я подсмотрел, но уверенности нет. Вроде как правильный адрес он в стеке хранит.
Там:
 pop ecx, а потом call farptr идет.

Не хочется лезть в такие дебри без полного осознания,
а информации нет по этому поводу.


NoUser ©   (22.03.17 14:05[8]


> Это немного не то.

И на сколько немного там это не то? ))

 private
   FOldWndProc  : IntPtr;
   FOldUserData : IntPtr;
   procedure InitClientWndProc(AHandle: HWND); // AHandle: integer ?
// function  ClientWindowProc(wnd: HWND; Msg: cardinal; wparam, lparam: integer): integer; stdcall;  // on x64??
   function  ClientWindowProc(Wnd: HWND; Msg: NativeInt ; wParam: NativeUInt; lParam: NativeInt): NativeInt; stdcall;
   class function DumMyWndProc(Wnd: HWND; Msg: NativeInt ; wParam: NativeUInt; lParam: NativeInt): NativeInt; static; stdcall;

procedure TWindow64.InitClientWndProc(AHandle: HWND);
begin
 //Данные пользователя могут быть заняты  // -> печалька
 //
 FOldWndProc := SetWindowLongPtr(AHandle, GWL_WNDPROC, IntPtr(@DummyWndProc));
 FOldUserData :=  SetWindowLongPtr(AHandle, GWL_USERDATA, IntPtr(Self));
end;

class function TWindow64.DumMyWndProc(Wnd: HWND; Msg: NativeInt; wParam: NativeUInt;lParam: NativeInt): NativeInt;
var
Tmp : Pointer;
begin
Tmp := Pointer(GetWindowLongPtr(Wnd, GWL_USERDATA));
if (Tmp <> nil) then                                                          // а вдруг там мышь ?,!
 try                                                                          
  Result := TWindow64(Tmp).ClientWindowProc(Wnd, Msg ,wParam, lParam);
 except end
else Result := DefWindowProc(Wnd, Msg ,wParam, lParam)                        // грустная печальная печалька
end;

function TWindow64.ClientWindowProc(Wnd: HWND; Msg: NativeInt; wParam: NativeUInt; lParam: NativeInt): NativeInt;
begin
// ...

SetWindowLongPtr(Wnd, GWL_USERDATA, IntPtr(FOldUserData));                    // печалька ->

Result := CallWindowProc(Pointer(FOldWndProc), Wnd, Msg, wParam, lParam);     // !

if IntPtr(@DumMyWndProc) <> GetWindowLongPtr(Wnd, GWL_WNDPROC) then           // печальная печалька
  FOldWndProc := SetWindowLongPtr(Wnd, GWL_WNDPROC, IntPtr(@DumMyWndProc));   // ::

FOldUserData := SetWindowLongPtr(Wnd, GWL_USERDATA, IntPtr(Self));            // печалька <-
end;


dmk ©   (22.03.17 15:00[9]

NoUser ©   (22.03.17 14:05) [8]
У меня нет окна. С окном все просто и без проблем.
А без окна GetLastError выдает InvalideDC


dmk ©   (22.03.17 15:08[10]

Windows не дает определить WndProc без окна. Можно только невидимое окно сделать.
Этот вопрос в соседней ветке.
А TWindow64 у меня класс от TObject. Там почти ничего нет. Мне просто нужен цикл сообщений. Делал через TNotifyEvent — такой вариант не подходит.


rrrrr ©   (22.03.17 15:55[11]

аллокейташвнд


dmk ©   (22.03.17 16:32[12]

>аллокейташвнд
Без окна не работает.
HWND создает, но при инсталляции GWL_USERDATA - GetLastError - Invalid DC.
Может на семерке работает, а на 10-ке точно не работает. Все примеры из гугла не рабочие :(


rrrrr ©   (22.03.17 16:36[13]

type
TMyStupidClass = class(TObject)
 fWnd : HWND;
 constructor createIt();
 procedure onMessage(var Message: TMessage);
 property handle : HWND read fWnd;
end;

constructor TMyStupidClass.createIt;
begin
inherited create();
fWnd := AllocateHWnd(onMessage);
end;

procedure TMyStupidClass.onMessage(var Message: TMessage);
begin
form1.Caption := IntToStr(Message.Msg);
end;

procedure TForm1.FormCreate(Sender: TObject);
var stc : TMyStupidClass;
begin
stc := TMyStupidClass.createIt();
PostMessage(stc.handle,WM_USER + 1000, 0,0);
end;


dmk ©   (22.03.17 17:44[14]

rrrrr ©   (22.03.17 16:36) [13]
Мне от системы надо!!! :) WM_MOUSEMOVE
Оно только с окном приходит.
Не выходит каменный цветок.


rrrrr ©   (22.03.17 17:57[15]

Мне нужно принимать сообщение от родительского окна в безоконный класс.

родительское окно - настоящее.
безоконный класс принимать сообщения может.
транслируй!


dmk ©   (22.03.17 18:00[16]

>транслируй!
Уже


rrrrr ©   (22.03.17 18:01[17]

procedure TMyStupidClass.onMessage(var Message: TMessage);
begin
form1.Caption := Format('mouse coords: %d %d',[Message.WParam, Message.LParam]);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
PostMessage(stc.handle, WM_MOUSEMOVE, Y,X);
end;


rrrrr ©   (22.03.17 18:04[18]

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


NoUser ©   (22.03.17 18:25[19]

> dmk ©   (22.03.17 15:00) [9]
> У меня нет окна.

Сочувствую, а как же :

> dmk ©   (22.03.17 02:13) [3]
> Если не делать частью класса - все в порядке, но переменные класса не видны.


> rrrrr ©   (22.03.17 18:04) [18]
!


dmk ©   (22.03.17 18:28[20]

>NoUser ©   (22.03.17 18:25) [19]

Ну зачем извращать. Речь шла об оконной процедуре.


Игорь Шевченко ©   (22.03.17 19:16[21]

dmk ©   (22.03.17 13:15) [6]


> Мне надо им петлю сообщений вставить. Чтобы они WM_MOUSE.
> .... получали. Вроде как компоненты, но окна они не имеют.
>


OpenGL уже изобретен и даже с исходниками. И всякие там GLScene тоже с исходниками. Не понимаю, зачем при таком изобилии готовых решений изобретать велосипеды которые будут ехать медленно и неровно.


dmk ©   (22.03.17 19:50[22]

Игорь, патриотизм штука заразная. Хочу свое ;)


dmk ©   (22.03.17 19:53[23]

А на самом деле класс кроссплатформенный в будущем и привязка к системе и т.д. очень нежелательна. Посему куча ассамблера и соответствующие отступления.


Игорь Шевченко ©   (23.03.17 10:23[24]

dmk ©   (22.03.17 19:50) [22]

Дело не в патриотизме, а в том, что в современном мире исходников столько, что решение почти любой проблемы несколькими способами можно найти в интернетах.


dmk ©   (23.03.17 12:14[25]

Можно и найти и купить - не спорю.
Часто сталкивался с проблемой прекращения поддержки исходников или компонентов.


Игорь Шевченко ©   (23.03.17 12:21[26]

dmk ©   (23.03.17 12:14) [25]

Я не про готовый вариант, а про реализацию идей, методы решения проблем и т.п. Это не надо покупать и опасаться прекращения поддержки.


D7   (28.03.17 21:59[27]

Я не понял. Сообщения может принимать только окно. Изображения выводить можно тоже только на окно. На невидимое окно выводить невозможно. У вас есть окно или нету? Или оно типа чужое?
Делайте ваш кросплатформенный класс, добавляйте в поля TForm1 его экземпляр, вызывайте его методы в нужных событиях. И всё, нет?


D7   (28.03.17 22:39[28]

Поздно увидел другую вашу тему, вам там уже показали что-то подобное тому что я имел ввиду...

Могу лишь посоветовать глянуть как работает AGG. Там кроссплатформенное ядро имеет лёгкие обёртки к разным ОС, в том числе делает окно на WinAPI и рисует на нём и получает управление клавиатуры/мыши.


dmk ©   (29.03.17 01:45[29]

>D7   (28.03.17 21:59) [27]

Окна нет, но есть HWND созданный с помощью AllocateHWND.
Класс от TObject. Рисуется в памяти. Не TCanvas.


D7   (29.03.17 02:46[30]

> Класс от TObject. Рисуется в памяти. Не TCanvas.

Это я как раз сразу понял. Хорошая идея, одобряю, сам когда-то думал про подобное.

> Окна нет, но есть HWND созданный с помощью AllocateHWND.

А вот зачем такие свистопляски с окном - не понимаю.
Я не сталкивался с подобной функцией прежде, прогуглил её - это походу какой-то метод из VCL. Который в итоге создаёт окно при помощи CreateWindowEx().
Уверен что будет удачнее взять "минимальный WindowsAPI-проект" - и вперёд, допиливаем лёгонькую обёртку. Небольшую часть кода можно из TApplication взять.


dmk ©   (29.03.17 02:55[31]

>А вот зачем такие свистопляски с окном - не понимаю.
Для того, чтобы классу без окна сообщения принимать.


D7   (29.03.17 16:56[32]

Что в вашем понимании есть "класс без окна"? Окнами в любом случае владеет только ОС.
А вы говорите что вызываете метод "Forms.AllocateHWnd()" (он же "Classes.AllocateHWnd())"? Ну так вы этим как раз создали окно.
Какого-то системного VCL-класса с какой-то системной VCL-WndProc по-умолчанию. Но я так понял вы вроде хотите как раз избавляться от VCL?

Сделаю к выходным пример как бы предложил делать я, а там посмотрите и решите сами.


dmk ©   (29.03.17 18:35[33]

>Ну так вы этим как раз создали окно.
Это все условности. По правилам Windows окном считается класс с оконной процедурой.
У меня ее нет. Ибо не нужна. Это дочерний объект-неокно.


dmk ©   (29.03.17 20:02[34]

Вот пример дочерних объектов не окон с поведением окон ;)
https://hostingkartinok.com/show-image.php?id=97725fa53a628a8e4b5f2c99ae984ed2

Работают также как и системные. Почти никаких различий.
Рисуются на любом контексте. Пока готово 3 компонета. Тут еще CheckBox не виден.
Скролл бары за 3 дня сделал. Почти как FMX, но не FMX. ПРивязки к WIndows почти нет ;)
Своя базовая бибилотека и никаких системных вызовов кроме BitBlt и сообщений о мышке.
Переносится хоть под линукс, хоть под DOS с небольшой доработкой ввода-вывода.


dmk ©   (29.03.17 20:04[35]

У меня даже шрифты свои. Пока растровые, но все же ;)


dmk ©   (29.03.17 20:07[36]

И никаких оконных функций и прочей мутатени ;)


Игорь Шевченко ©   (29.03.17 21:34[37]


> По правилам Windows окном считается класс с оконной процедурой


Без комментариев.


> И никаких оконных функций и прочей мутатени ;)


Таких фреймворков уже миллионы. Зачем нужен еще один с граблями - я не понимаю.


dmk ©   (29.03.17 22:02[38]

>Без комментариев.
Ну тогда черный квадрат малевича тоже окно :)

>Зачем нужен еще один с граблями - я не понимаю.
Дык свое. У меня софтина на нем пишется. Большая :)
Если намертво к windows привязаться потом тошно переделывать будет,
а слово портирование забыть придется.


D7   (29.03.17 22:11[39]

> По правилам Windows окном считается класс с оконной процедурой.

Это чего это, где же такое написано?
В исходниках ОС может и класс, а со стороны прикладного программиста это - чёрный ящик, имеющий некий ID.

На вашем скриншоте я вижу обычное окно с рамкой.
Да, на его клиентской области выводится своё крутое кросплатфоменное, но через BitBlt() оно выводится на обычное окно. Можете взять Spy++ и проверить.
Кстати можно заменить BitBlt() на StretchDIBits(), слышал мнение что оно чуток эффективнее, хотя сам не проверял не тестировал.

В общем до понедельника сделаю тестовый мини-проект.


dmk ©   (29.03.17 22:17[40]

>На вашем скриншоте я вижу обычное окно с рамкой.
Ну да, только все рисуется и крутится без системных вызовов ;)
А BitBlt - ну тут извините. Windows не дает прямого доступа к видеопамяти.
Короче написал я фигню. Каюсь, грешен был. О великий TForm!!!


D7   (29.03.17 22:24[41]

Нет, вы пишете перспективную штуку, но у вас есть окно какого-то класса и очередь сообщений, не может не быть. Под виндой не может.
Поэтому нужна лёгкая прослойка между ОС/платформой и главным кодом. Для винды своя, для другого другая. А интерфейс главного не меняется.


dmk ©   (29.03.17 22:27[42]

>Поэтому нужна лёгкая прослойка между ОС/платформой и главным кодом.
Абстракция от системы есть.


Игорь Шевченко ©   (29.03.17 22:59[43]


> Дык свое.


Дык надо книжки читать, чтобы свое делать. А не плавать в базовых понятиях.


> Если намертво к windows привязаться потом тошно переделывать
> будет,
> а слово портирование забыть придется.


Ты уже привязался так, что про портирование можно забыть, судя по твоим вопросам.

Иксы на юниксах например совсем по-другому работают, что на маке происходит - честно не знаю, но тоже не так, как на Windows. А на андроиде еще по третьему. Куда ты будешь свои WM_LBUTTONDOW переносить - я не представляю


dmk ©   (29.03.17 23:16[44]

>Игорь Шевченко ©   (29.03.17 22:59) [43]
Вы меня уничтожили :) Просто растерли.


Eraser ©   (30.03.17 07:39[45]


> Почти как FMX, но не FMX. ПРивязки к WIndows почти нет

так и в FMX привязки к windows нет.
https://ru.wikipedia.org/wiki/%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F_%D0%B2%D0%B5%D0%BB%D0%BE%D1%81%D0%B8%D0%BF%D0%B5%D0%B4%D0%B0


Игорь Шевченко ©   (30.03.17 10:19[46]


> Вы меня уничтожили :) Просто растерли.


Не в этом дело. Такие задачи прекрасно решаются в рамках парадигмы Model-View-Controller, где контроллер как раз и занимается обработкой внешних событий. Таким образом решение абстрагируется от конкретных механизмов внешних событий, сосредотачивая всю конкретику в относительно небольших участках кода.
Я ведь не зря начал с того, что примеров уже уйма, посмотреть, как сделано, можно совершенно бесплатно.


dmk ©   (30.03.17 13:10[47]

Так я так и делаю. У меня отдельный класс будет, который будет заниматься вводом-выводом. Просто не успеваю все сделать. Если бы я программистом был ;) А так сижу вечерами пишу, да и то не каждый день. Много изучил, но еще больше не знаю. Учимся пока. Для меня это кажется новшеством, а у других уже есть. Ну велосипед и что? Зато свой.


An a Student   (30.03.17 20:01[48]

Просто вы, кажется, не понимаете что "окно" в Windows - это и не "форма" и не "класс". Да и вообще никакой класс не может "содержать окно", лишь побочно создавать и идентификатор хранить.
Окно - это HWND (ну или псевдоним THandle из VCL), полученное через одну из WinAPI-функций (или даже из VCL-функций/методов).
А связь своего потомка от TObject с неким HWND и с его оконной функцией - не делает ни окно "частью класса", ни наоборот.

По идее же надо передавать указатель на экземпляр объекта своего класса через lParam, нет? А вы тут что-то странное делаете - зачем так странно сабклассить собственное окно?


dmk ©   (30.03.17 23:18[49]

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


An a Student   (31.03.17 00:31[50]

Вот именно. В классе который мы придумываем может быть только индекс/ссылка/смещение не важно что это - HWND. "Окна в классе" в принципе быть не может.

гм... Этот "class function" никогда не видел, это чего такое, типа статического метода? Думал нету в Делфи статических. И у таких не будет первого скрытого параметра "self/this"? Ну дак в случае с WndProc тогда и нету смысла так делать.

Классика - передавать указатель на объект в CreateWindowEx() в lParam и в WM_CREATE записывать его в GWL_USERDATA. Зачем извращаться-то? :)


DVM ©   (01.04.17 22:10[51]


> dmk ©

не забудь еще что без цикла выборки сообщений, работать ничего не будет.


> An a Student   (31.03.17 00:31) [50]


> Этот "class function" никогда не видел, это чего такое,
> типа статического метода? Думал нету в Делфи статических.
>  И у таких не будет первого скрытого параметра "self/this"?
>

Этого недостаточно, все равно будут скрытые параметры. Нужно еще слово  static.


dmk ©   (01.04.17 22:15[52]

>не забудь еще что без цикла выборки сообщений, работать ничего не будет.
Отдельного цикла нет. Просто трансляция из оконной процедуры. Все работает.


DVM ©   (01.04.17 22:20[53]


> dmk ©   (01.04.17 22:15) [52]


> Отдельного цикла нет.

Как это нет? У тебя же родительское окно есть. Есть. Значит и цикл есть.


DVM ©   (01.04.17 22:35[54]

По моему, тут вообще не нужно никаких окон и сообщений.
Нужно ядро, и два контроллера, ввода и вывода. Общение между ними не нуждается в сообщениях. Все общение ядра с внешним миром определяется контроллерами. Контроллер ввода прекрасно может перехватывать сообщения формы и транслировать их в ядро.


dmk ©   (01.04.17 22:57[55]

Это типа узловой связи клиент-сервер?


D7   (03.04.17 03:38[56]

так... В общем что-то я совсем заморочился, наплодил нечто объёмное и сырое. Но общую суть как-то так:

type
 MouseButton = (buttonLeft, buttonRight, buttonMiddle);

function TWindow64WndProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var Window64: TWindow64;
begin
Window64:=TWindow64(GetWindowLong(Wnd, GWL_USERDATA)); // получаем текущий объект!
case Msg of
 WM_CREATE: // сообщение приходит одним из первых и однократно для каждого создаваемого HWND
   begin
   SetWindowLong(Wnd, GWL_USERDATA, Integer(PCreateStruct(lParam).lpCreateParams)); // сохраняем текущий объект так!
   Result:=0;
   end;
 WM_PAINT:
   begin
   Window64.OnMessagePaint(Wnd, wParam);
   Result:=0;
   end;
 WM_LBUTTONDOWN:
   begin
   Window64.OnMouseDown(Smallint(lParam And $FFFF), Smallint(lParam Shr 16), buttonLeft, ... );
   Result:=0;
   end;
 WM_LBUTTONUP:
   begin
   Window64.OnMouseUp(Smallint(lParam And $FFFF), Smallint(lParam Shr 16), buttonLeft, ... );
   Result:=0;
   end;
 WM_RBUTTONDOWN:
   begin
   Window64.OnMouseDown(Smallint(lParam And $FFFF), Smallint(lParam Shr 16), buttonRight, ... );
   Result:=0;
   end;
 WM_RBUTTONUP:
   begin
   Window64.OnMouseUp(Smallint(lParam And $FFFF), Smallint(lParam Shr 16), buttonRight, ... );
   Result:=0;
   end;
 else
   Result:=DefWindowProc(Wnd, Msg, wParam, lParam); // !!!
 end;
end;

procedure TWindow64.OnMessagePaint(Wnd: HWND; wParam: WPARAM);
var DC: HDC; Rect: TRect; PS: TPaintStruct;
begin
if (wParam<>0) then
 DoPaint(HDC(wParam), nil)
else
 if GetUpdateRect(Wnd, Rect, False) then
   begin
   DC:=BeginPaint(Wnd, PS);
   DoPaint(DC, @Rect);
   EndPaint(Wnd, PS);
   end
 else
   { nothing };
end;

procedure TWindow64.DoPaint(DC: HDC; Rect: PRect);
begin
// Делаем BitBlt или StrechDIBits на DC переданный через параметры
end;

procedure TWindow64.OnMouseDown(X: Integer; Y: Integer; Button: MouseButton, ... );
begin
//
end;

procedure TWindow64.OnMouseUp(X: Integer; Y: Integer; Button: MouseButton, ... );
begin
//
end;

constructor TWindow64.Create(AParent: THandle; ABitmap: TBitmap64; R: TRegion);
var Rect: TRect;
begin
...
 FWndClassEx.lpfnWndProc := @TWindow64WndProc; // и всё, больше ничего не надо мутить!
...
 FStyle:=WS_VISIBLE Or WS_OVERLAPPEDWINDOW;
 FStyleEx:=WS_EX_APPWINDOW;
 with Rect do
   begin
   Left:=FClientLeft;
   Top:=FClientTop;
   Right:=Left+FClientWidth;
   Bottom:=Top+FClientHeight;
   AdjustWindowRectEx(Rect, FStyle, False, FStyleEx);
   FHandle:=Windows.CreateWindowEx(
                                                      FStyleEx,
                                                      LPCWSTR(FWndClassEx.lpszClassName),
                                                      'TWindow64',
                                                      FStyle,
                                                      Left,
                                                      Top,
                                                      Right-Left,
                                                      Bottom-Top,
                                                      0, // !!!
                                                      0,
                                                      HInstance,
                                                      Pointer(Self) // и передаём ссылку на текущий объект сюда!
                              );
   end;
...
end;


И не забывайте про всякие *DBLCLK. А зачем нужна какая-то самодельная "трансляция"?
В каждый объект TWindow64 нажатие будет само приходить (если курсор был над ним), даже если оно будет дочернее.

> DVM ©   (01.04.17 22:35) [54]

эм... Я тоже не особо понял, если не сложно, расскажите пожалуйста всем поподробнее об этом? Спасибо!


dmk ©   (03.04.17 05:59[57]

У меня смысл такой, что приходится обходить ограничения Windows на доступ к видеопамяти, т.к. в проекте у меня все рисуется в буфере, то и контролы нужно рисовать в буфере. Поэтому и придумал такой вариант. Зато его можно и в буфер рисовать и на DC рисовать, хотя DC и есть буфер, только у системы.

Проще покзать, чем объяснить. Тут 2 экзешника:
https://cloud.mail.ru/public/bkmv/YUqSxabFZ

TBitmap - там CheckBox в буфере рисуется, а в ic64 скроллы и линейки.
Про смысл не спрашивайте.


D7   (03.04.17 10:38[58]

Под Win7 не стартится, видимо exe-шники только под 64. А старые демки (из соседних тем) уже не доступны, жаль, я бы с радостью посмотрел.

Можно и на OpenGL всё рисовать. Видеопамять, пожалуйста. :)

Непонятно тока что за "трансляция". Если у вас много окон (группа HWND) - то им сообщения сами придут.
А если они не реальные окна - то им не надо создавать HWND и что-то слать, оперировать вручную, вызывать методы если требуется.

Вы можете убрать из кода ваши секретные разработки (рисование на ассемблере и прочее, вообще их по логике в отдельных модулях надо хранить), оставить только базовые классы типа TWindow64, часть которых привязана к Windows, и скинуть куда-то сей урезанный проект?


D7   (03.04.17 10:46[59]

Под моей Win7 имелось ввиду. Попробую найти 64, но в идеале бы было бы чтоб работало и на 32 тоже. *

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


dmk ©   (03.04.17 11:05[60]

>было бы чтоб работало и на 32 тоже
Писать под win32 сей проект неудобно. Там ограничение 4 гб. Делать смешанную адресацию неудобно и получаются медленные процедуры. 32 уже потихоньку уходит в прошлое, хотя и не так быстро как 16 бит.


D7   (03.04.17 11:09[61]

И вы реально можете занять все 4ГБ? У меня вот ни одна программа, даже мощные CAD-системы и крутые игры - не достигают 4ГБ. %))


dmk ©   (03.04.17 11:12[62]

>Непонятно тока что за "трансляция".
Windows не дает без окна доступ к очереди сообщений, поэтому приходится делать привязку к оконной процедуре. Типа врезки трубы в магистраль. Хотя можно изобрести что-то вроде своего контроллера. Если мышь в области, то запускать таймер и делать выборку позиции через winapi.GetCursorPos и клавиши через GetAsyncKeyState. Тогда вообще трансляция не нужна.

А под 32 не переделаю. Смысла нет, да и наоборот я ее переделывал с 32 на 64.


dmk ©   (03.04.17 11:17[63]

>И вы реально можете занять все 4ГБ?
У меня Photoshop64, 3ds max64, Illustrator64 и т.д все используют намного больше 4 гб.
У меня 32 стоит. Фотошо например 20 Гб легко съедает.


D7   (03.04.17 12:02[64]

Не пользую фотошопы - рисовать не умею. Для элементарных обработок вполне хватает XnView/Gimp.
Что ж вы с ними делаете такое?)) У меня модель летательного аппарата со всеми мельчайшими деталями и сложной кинематикой стока не жрёт))
Хотя не тестил скока будет жрать если поставить x64 ОС и такую же версию CAD-системы... Может с этой же моделью сразу же в три раза больше памяти хапнет просто так?

ох... Короче так.
* Делаем класс DMKApplication, который: хранит список "окон" верхнего уровня программы, умеет запускать очередь сообщений, при закрытии всех окон выходит из программы (закрывает).
* Делаем класс DMKWindow, который: является обёрткой над окнами верхнего уровня Windows, умеет создавать и уничтожать окна, получает управление от мыши и клавиатуры, отслеживает изменение своего состояния (позиция, размеры, итп), хранит и обрабатывает список "слоёв", выводит на себя итоговую буфер-картинку.
* Делаем класс DMKLayer, который: является логической единицей выводящей что-либо на битмап, имеет классические методы и события. Возможно абстрактный, с какими-то потомками типа "кнопка", "текст", "чекбокс", etc.
В простейшем случае имеем: один объект DMKApplication, один объект DMKWindow, некоторое количество объектов DMKLayer. Итого в программой будет создано один HWND и при перерисовке будет браться один HDC за раз и тут же освобождаться.
Минимальная привязка к ОС, минимальное потребление системных как их там, максимальная скорость работы, переносимость программы на любую платформу через просто замену реализации нескольких методов DMKApplication и DMKWindow, и всё своё.


Игорь Шевченко ©   (03.04.17 12:13[65]

D7   (03.04.17 11:09) [61]


> И вы реально можете занять все 4ГБ? У меня вот ни одна программа,
>  даже мощные CAD-системы и крутые игры - не достигают 4ГБ.
>  %))


Это говорит о том, что с программами, занимающими больше 4-х Гб ты не знаком. Ну и что ? Займись фотографией, сразу познакомишься :)

dmk ©   (03.04.17 11:05) [60]


> 32 уже потихоньку уходит в прошлое


Бред какой. Программ, которым реально нужен большой объем памяти, максимум 1 процент от всего.


dmk ©   (03.04.17 12:14[66]

>будет браться один HDC за раз и тут же освобождаться.
DC - контекст - это просто битмап. Его не надо постоянно освобождать. Взял DC и пользуй его. Надоело - ReleaseDC. Это просто ссылка. Это нужно было в windows 3.11-95, а после win2000 уже не нужно.
На самом деле все уже работает. Если запустите примеры, то увидите. Только win64 надо.


D7   (03.04.17 12:37[67]

Хех, "занимающими" или "жрущими"?)) Вся папка CAD-программы занимает на диске около 23ГБ.
Фотографией? У вас есть фотка весящая 4ГБ в распакованном виде?)

MSDN указывает делать BeginPaint/EndPaint. Я слушаюсь MSDN, во избежание, как говорится, это их система.
HDC это не битмап, в него может быть выбран битмап, а может и не быть выбран. Как и остальные HGDI объекты.

ну... Я предлагал помочь. Как хотите. Но покачто у вас что-то делается не совсем так. В плане WinAPI.


Игорь Шевченко ©   (03.04.17 14:06[68]

D7   (03.04.17 12:37) [67]


> У вас есть фотка весящая 4ГБ в распакованном виде


Конечно. И не одна. Кроме фоток еще есть базы данных. И не одна. Но это уже оффтопик. Я просто прошу поверить, что нужных 64-х разрядных программ достаточно.


dmk ©   (03.04.17 14:08[69]

>не совсем так. В плане WinAPI.
У меня все в памяти делается, а не в винапи.
Мне от WInApi только несколько сообщений надо.

А за помощь спасибо! Все будет учтено.


dmk ©   (03.04.17 14:12[70]

>У вас есть фотка весящая 4ГБ в распакованном виде?)
Вы просто не сталкивались видимо с такими задачами: БД, Видео, Фото, Полиграфия, Архивы и т.п. У меня архивы несколько сот гигабайт в упакованном виде. Работаю дизайнером. Есть файлы более 4-х Гб. Немного, но есть.


Eraser ©   (03.04.17 19:24[71]


> dmk ©  

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


dmk ©   (03.04.17 23:41[72]

>без окна в современной винде все равно отображать ничего не выйдет
Там в [57] уже все вышло :) Конечно же все отображается в окне.


Eraser ©   (04.04.17 10:41[73]


> dmk ©   (03.04.17 23:41) [72]

все равно не понятно, зачем требовалось, что требовалось и что в итоге получилось.
по-моему усложнение себе жизни.


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо