Конференция "WinAPI" » Как принять сообщения в класс без окна?
 
  • 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 тоже. *

    Я же говорю - я очень хорошо понимаю задумку, но некоторые вещи что вы делаете (видно по кускам кода) не укладываются в подобную архитектуру.
    Что-то слегка не так, я хочу помочь это исправить.
 
Конференция "WinAPI" » Как принять сообщения в класс без окна?
Есть новые Нет новых   [118679   +72][b:0.001][p:0.001]