Конференция "Игры" » Как изменить поля класса в WndProc? [Delphi, Windows]
 
  • Б (22.07.09 19:38) [0]
    Пишу игровой движок.
    У класса движка есть несколько полей, которые должны изменяться при получении того или иного сообщения. Но т.к. WndProc вне классовая процедура, то поля класса в нём не изменишь.
    Как поместить туда, эти самые поля?
    Не хотелось бы пользоваться глобальными переменными, а потом уже через них присваивать значения полям класса. (Но пока так)
  • @!!ex © (22.07.09 20:08) [1]
    Запиши в данные окна указатель на класс, а в WndProc получай эти данные через HWND
  • @!!ex © (22.07.09 20:09) [2]
    Лично я использую
    GWL_USERDATA
    SetWindowLong
    GetWindowLong
  • Б (23.07.09 17:24) [3]

    > @!!ex ©   (22.07.09 20:09) [2]


    Что-то не понял, как с их помощью, это сделать.
  • @!!ex © (23.07.09 19:23) [4]
    Разжую:
    ПРи создании окна делаем:
    SetWindowLong(Wnd,GWL_USERDATA,Class);

    В WndProc:
    Class = TClass(GetWindowLong(Wnd,GWL_USERDATA));

    Что здесь может быть непонятного? ]:->
  • Б (23.07.09 19:57) [5]

    Var
      Engine: TEngine;
      WndGlob: HWND;                               // Глобальный.

    . . . . .

       WM_CREATE:
       begin
         Engine:= TEngien.Create;
         Engine:= TEngine(GetWindowLong(WndGlob, GWL_USERDATA));
         Result:= 0;
         Exit;
       end;

       WM_LBUTTONDOWN:                          
       begin
          Engine.FTest:= True;                        // <---  AV.
          Result:= 0;
       end;

       WM_RBUTTONDOWN:                          
       begin
         Engine.FTest:= False;                       // <---  AV.
         Result:= 0;
       end;

    . . . . .

      Engine.CreateWindow;
      SetWindowLong(WndGlob, GWL_USERDATA, Longint(Engine));
     

  • Сергей М. © (23.07.09 20:10) [6]

    > Б   (23.07.09 19:57) [5]


    Ахинея какая-то ..
  • @!!ex © (23.07.09 20:44) [7]
    > [5] Б   (23.07.09 19:57)
    > Engine:= TEngien.Create;
    >     Engine:= TEngine(GetWindowLong(WndGlob, GWL_USERDATA)
    > );

    Это бред.
  • Б (23.07.09 20:49) [8]
    Engine:= TEngien.Create - это лишне.

    Так как надо?
    Всё, как ты сказал.
  • @!!ex © (23.07.09 20:58) [9]
      WM_LBUTTONDOWN:                          
      begin
         Engine.FTest:= True;                        // <---  AV.
         Result:= 0;
      end;

      WM_RBUTTONDOWN:                          
      begin
        Engine.FTest:= False;                       // <---  AV.
        Result:= 0;
      end;


    Engine не инициализирован. Естественно AV.
  • Б (23.07.09 21:26) [10]

    > Engine не инициализирован. Естественно AV.

    Ну почему же? Инициализирован.
    С SetWindowLong, GetWindowLong - всё правильно?


    Program Test;
     . . . . .
    Var
     Engine: TEngine;
    begin
     Engine:= TEngine.Create;  
     . . . . .
       
     Engine.Run;

    End;
     
     Procedure TEngine.Run;
     begin
        CreateWindow. . .;                                   // Создаём окно.
        SetWindowLong(WndGlob, GWL_USERDATA, Longint(Engine)); // Как ты советовал.
       
        (* Инициализация Direct3D, Sub-систем *)

        Processing;              // Вход в главный цикл.
        Cleanup;                  // Освобождение ресурсов.
      End;

  • @!!ex © (24.07.09 00:02) [11]
    > [10] Б   (23.07.09 21:26)

    А код WndProc покажи целиком.
  • Б (24.07.09 00:12) [12]

    Function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin

     Case (Msg) of
       WM_CREATE:
       begin
         Result:= 0;

         Engine:= TEngine(GetWindowLong(WndGlob, GWL_USERDATA));

         Exit;
       end;

       WM_DESTROY:                                
       begin
         PostQuitMessage(0);                        
         Result:= 0;
       end;

       WM_LBUTTONDOWN:                          
       begin
          Engine.FTest:= True;                        
          Result:= 0;
       end;

       WM_RBUTTONDOWN:                          
       begin
          Engine.FTest:= False;                            
          Result:= 0;
       end;

       (*
         
          + другие...

       *)


       else
         Result:= DefWindowProc(hWnd, Msg, wParam, lParam);
     end;
    End;


  • @!!ex © (24.07.09 00:29) [13]
    Ниче не понимаю...
    Короче как у меня сделано:

    void osal::cWnd::CreateWnd(int Width,int Height, bool Fullscreen, int PixelDepth, std::string Title)
    {
    ...
    m_Wnd = CreateWindowExA(dwExStyle,
         ClassName,
         Title.c_str(),      
                           dwStyle,        
                           0, 0,          
                           Width, Height,  
                           0,              
                           0,              
                           m_Instance,    
                           NULL);
    SetWindowLong(m_Wnd,GWL_USERDATA,(int)this);
    ...
    }
    ;

    LRESULT CALLBACK outsideWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    return ((osal::cWnd*)GetWindowLong(hWnd,GWL_USERDATA))->WndProc(message, wParam,lParam);
    }
    ;

  • Б (24.07.09 11:28) [14]
    Сделал так:


    Function TEngine.DoWndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM;
     lParam: LPARAM): LRESULT;
    begin
     Case Msg of
       WM_DESTROY:
       begin
         PostQuitMessage(0);                        // Разрушаем окно.
         Result:= 0;
       end;

       WM_LBUTTONDOWN:
       begin
         FTest:= True;                    // Тестируем поля.
         Result:= 0;
       end;

       WM_RBUTTONDOWN:
       begin
         FTest:= False;                  // Тестируем поля.    
         Result:= 0;
       end;
       
       (* + Целая куча других сообщений  *)

       else
         Result:= DefWindowProc(hWnd, Msg, wParam, lParam);
     end
    End;

    Function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin
     Result:= Engine.DoWndProc(hwnd, msg, wParam, lParam);        // Engine - получается глобальным.
    End;

  • @!!ex © (24.07.09 11:30) [15]
    Function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin
    Result:= Engine.DoWndProc(hwnd, msg, wParam, lParam);        // Engine - получается глобальным.
    End;



    Это не то, о чем говорилось в первом сообщении.
    Это не классовая обертка. Engine может быть только один. И он к тому же глобальная переменная...
  • Б (24.07.09 11:56) [16]

    > Б   (22.07.09 19:38)
    > Не хотелось бы пользоваться глобальными переменными,
    > а потом уже через них присваивать значения полям класса.


    Вот такие глобальные переменные имелись ввиду.
    Конечно Engine - один, программист не участвует в его создании.
    Через Set/Get-WindowLong - от глобальных тоже не отвязатся.
  • @!!ex © (24.07.09 13:23) [17]
    > [16] Б   (24.07.09 11:56)
    > Через Set/Get-WindowLong - от глобальных тоже не отвязатся.

    Это еще почему??
  • @!!ex © (24.07.09 13:24) [18]
    P.S.
    Это не вопрос, а способ сказать что вы не правы.
    Собственно код в [13] работает без глобальных переменных в принципе.
 
Конференция "Игры" » Как изменить поля класса в WndProc? [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.005]