Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Using Win32 and Events  (Read 8782 times)

0 Members and 1 Guest are viewing this topic.

raytracer

  • Newbie
  • *
  • Posts: 3
    • View Profile
Using Win32 and Events
« on: August 27, 2012, 08:05:02 pm »
Today i tried the following tutorial.

Tutorial - Graphics - Integrating to a Win32 interface
http://www.sfml-dev.org/tutorials/1.6/graphics-win32.php

Everything works fine.
But if I try to add events like keyboard Inputs I dont get any events.

   do
   {
      if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
      {
         if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
         {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }
      }   
      else
      {
         //Process SFML Code

         //Process events
         sf::Event Event;
         while (RenderWin.GetEvent(Event))
         {
            if(Event.Type == sf::Event::KeyPressed)
            {
                if(Event.Key.Code == sf::Key::Escape)
               {
                  //Quit
                  return false;
               }
            }
         }
      }
   }while(msg.message != WM_QUIT);


Is it possible to get these Event and use Win32?




 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Using Win32 and Events
« Reply #1 on: August 27, 2012, 10:47:16 pm »
Well it wasn't written in the tutorial, but since it states that one should know about WinAPI you could've figured it out. ;)
Also please make use of the code=cpp tag to highlight your code.

When using the event processing directly with the WinAPI, you can't process events with SFML, or maybe it's possible if you did it diffrently.
One can look at the following two code example as kind of equivilant:
do
{
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
     }
while(msg.message != WM_QUIT);
while(window.isOpen())
{
    sf::Event event;
    while(window.pollEvent(event))
    {
        if(event.type == sf::Event::Closed)
            window.close();
    }
}    
 

More technical, both take the messages/events from a queue and process them, thus if PeekMessage removes them, there's no way pollEvent can get them anymore.

I hope this all made kind of sense. :D

What is your reason to mix WinAPI code with SFML?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Using Win32 and Events
« Reply #2 on: August 27, 2012, 10:55:16 pm »
Quote
When using the event processing directly with the WinAPI, you can't process events with SFML
No, it should work fine. Calling DispatchMessage will pass the event to all the registered event procedures, which includes both SFML's and user's ones. Unless there's something wrong in user's code.

So please show your full code.
Laurent Gomila - SFML developer

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Using Win32 and Events
« Reply #3 on: August 27, 2012, 11:17:43 pm »
No, it should work fine. Calling DispatchMessage will pass the event to all the registered event procedures, which includes both SFML's and user's ones. Unless there's something wrong in user's code.
Okay, well he tries to process the events within the else-block, doesn't that matter either? I'm not very familiar how SFML works behind the curtains. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Using Win32 and Events
« Reply #4 on: August 27, 2012, 11:24:52 pm »
Quote
Okay, well he tries to process the events within the else-block, doesn't that matter either?
No, although it's not efficient it should work. SFML will accumulate events with calls to DispatchEvent, and he will get and process them later when he reaches the GetEvent calls.
Laurent Gomila - SFML developer

raytracer

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Using Win32 and Events
« Reply #5 on: August 28, 2012, 01:49:32 pm »
Thank you for your answers.

Quote
What is your reason to mix WinAPI code with SFML?
I want to use SFML for Joystick Input and Graphics but i need the Window Message Loop to interact with an Serial Port.

Quote
No, it should work fine. Calling DispatchMessage will pass the event to all the registered event procedures, which includes both SFML's and user's ones. Unless there's something wrong in user's code.

So please show your full code.
How do i register my procedure? I think that is the problem.

The full Code of main.cpp:
I created an Standard Win32 Project with Visual Studio and added SFML.

#include "stdafx.h"
#include "AVR_Remote.h"
#include <SFML/Graphics.hpp>

#define MAX_LOADSTRING 100

// Globale Variablen:
HINSTANCE hInst;                                                                // Aktuelle Instanz
TCHAR szTitle[MAX_LOADSTRING];                                  // Titelleistentext
TCHAR szWindowClass[MAX_LOADSTRING];                    // Klassenname des Hauptfensters

//Variabeln für SFML
sf::RenderWindow RenderWin;
sf::Image image;
sf::Sprite sBackground;

// Vorwärtsdeklarationen der in diesem Codemodul enthaltenen Funktionen:
ATOM                            MyRegisterClass(HINSTANCE hInstance);
HWND                            InitInstance(HINSTANCE, int);
LRESULT CALLBACK        WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK        About(HWND, UINT, WPARAM, LPARAM);
bool                            InitSFML(HWND hWnd, HINSTANCE hInstance);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);

        // TODO: Hier Code einfügen.
        MSG msg;
        HACCEL hAccelTable;
        HWND hWnd;

        // Globale Zeichenfolgen initialisieren
        LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadString(hInstance, IDC_AVR_REMOTE, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);

        // Anwendungsinitialisierung ausführen:
        hWnd = InitInstance(hInstance, nCmdShow);
        if(!hWnd)
        {
                return FALSE;
        }

        hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_AVR_REMOTE));

        if(!InitSFML(hWnd, hInstance))
                return FALSE;

        // Hauptnachrichtenschleife:
        do
        {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                        if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
                        {
                                TranslateMessage(&msg);
                                DispatchMessage(&msg);
                        }
                }      
                else
                {
                        //Process SFML Code

                        //Process events
                        sf::Event Event;
                        while (RenderWin.GetEvent(Event))
                        {
                                if(Event.Type == sf::Event::KeyPressed)
                                {
                                    if(Event.Key.Code == sf::Key::Escape)
                                        {
                                                //Quit
                                                return false;
                                        }
                                }
                        }
                       
                        RenderWin.Clear();

                        RenderWin.Draw(sBackground);
               
                        RenderWin.Display();


                }
        }while(msg.message != WM_QUIT);

        return (int) msg.wParam;
}



//
//  FUNKTION: MyRegisterClass()
//
//  ZWECK: Registriert die Fensterklasse.
//
//  KOMMENTARE:
//
//    Sie müssen die Funktion verwenden,  wenn Sie möchten, dass der Code
//    mit Win32-Systemen kompatibel ist, bevor die RegisterClassEx-Funktion
//    zu Windows 95 hinzugefügt wurde. Der Aufruf der Funktion ist wichtig,
//    damit die kleinen Symbole, die mit der Anwendung verknüpft sind,
//    richtig formatiert werden.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
        WNDCLASSEX wcex;

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style                      = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc        = WndProc;
        wcex.cbClsExtra         = 0;
        wcex.cbWndExtra         = 0;
        wcex.hInstance          = hInstance;
        wcex.hIcon                      = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_AVR_REMOTE));
        wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+2);
        wcex.lpszMenuName       = MAKEINTRESOURCE(IDC_AVR_REMOTE);
        wcex.lpszClassName      = szWindowClass;
        wcex.hIconSm            = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

        return RegisterClassEx(&wcex);
}

//
//   FUNKTION: InitInstance(HINSTANCE, int)
//
//   ZWECK: Speichert das Instanzenhandle und erstellt das Hauptfenster.
//
//   KOMMENTARE:
//
//        In dieser Funktion wird das Instanzenhandle in einer globalen Variablen gespeichert, und das
//        Hauptprogrammfenster wird erstellt und angezeigt.
//
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern

        RECT size;
        size.top = 0;
        size.bottom = 800;
        size.left = 0;
        size.right = 1200;
        AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, true);

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT, 0, size.right-size.left, size.bottom-size.top, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return 0;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return hWnd;
}

//
//  FUNKTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  ZWECK:  Verarbeitet Meldungen vom Hauptfenster.
//
//  WM_COMMAND  - Verarbeiten des Anwendungsmenüs
//  WM_PAINT    - Zeichnen des Hauptfensters
//  WM_DESTROY  - Beenden-Meldung anzeigen und zurückgeben
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;

        switch (message)
        {
        case WM_COMMAND:
                wmId    = LOWORD(wParam);
                wmEvent = HIWORD(wParam);
                // Menüauswahl bearbeiten:
                switch (wmId)
                {
                case IDM_ABOUT:
                        DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                        break;
                case IDM_EXIT:
                        DestroyWindow(hWnd);
                        break;
                default:
                        return DefWindowProc(hWnd, message, wParam, lParam);
                }
                break;
        case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);
                // TODO: Hier den Zeichnungscode hinzufügen.
                EndPaint(hWnd, &ps);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
}

// Meldungshandler für Infofeld.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
                return (INT_PTR)TRUE;

        case WM_COMMAND:
                if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
                {
                        EndDialog(hDlg, LOWORD(wParam));
                        return (INT_PTR)TRUE;
                }
                break;
        }
        return (INT_PTR)FALSE;
}

bool InitSFML(HWND hWnd, HINSTANCE hInstance)
{
    // Create an SFML View
    HWND View = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 0,  0, 1200, 800, hWnd, NULL, hInstance, NULL);
    RenderWin.Create(View, sf::WindowSettings(24,8,4));

        // Load Background for the Window
    if(!image.LoadFromFile("image1.png"))
        return false;

        sBackground.SetImage(image);
        sBackground.SetPosition(0,0);

        return true;
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Using Win32 and Events
« Reply #6 on: August 28, 2012, 04:25:56 pm »
Quote
How do i register my procedure?
This way:
wcex.lpfnWndProc        = WndProc;

I think your problem is that your SFML view is a "STATIC" child of the main window. Therefore it can't receive keyboard input.

Although static controls are child windows, they cannot be selected. Therefore, they cannot receive the keyboard focus and cannot have a keyboard interface.

You should practice more with Win32 code before trying to do complicated things with it :)
Laurent Gomila - SFML developer

raytracer

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Using Win32 and Events
« Reply #7 on: August 28, 2012, 08:28:41 pm »
Yeah ist working :-)

Thank you for the hint with the static child window.
That was the problem.





 

anything