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

Author Topic: Subclassing RenderWindow in an MFC SDI app?  (Read 2201 times)

0 Members and 1 Guest are viewing this topic.

Rectangle

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Subclassing RenderWindow in an MFC SDI app?
« on: June 27, 2014, 01:19:13 pm »
So, I've created a new MFC single-document app.

In the main CWinAppEx class, I have overloaded the virtual function int Run() to include a more suitable loop for updating & rendering (and if you'd like to see the code, I'll be happy to show it, but I find it irrelevant to the issue at hand... The only important thing to note here is that it works, includes code directly from the original superclass's Run method, and calls the main view's Update and Render functions between each Win32 message pump)...

In my CView class, I have publicly subclassed sf::RenderWindow. I have also used the class wizard to be notified of the WM_CREATE message, during which I use GetSafeHwnd() to grab the view's window handle, which I perform some validation on before passing it to sf::RenderWindow::create (see code below for details)... This all appears to work, and I do indeed get a black screen (or whatever color I specify) during each call to clear and display...

Now comes the strange part... Adding a texture to the view class doesn't appear to render anything. If I don't subclass RenderWindow, and instead create the window as an external window (without passing in the window's handle), the sprite shows on the screen. But anytime I attempt to use the view's HWND, I get a cleared screen of whatever color I specify, but no sprite/texture. Here's some code:

int CSFMLMultiWindowTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
        if (CView::OnCreate(lpCreateStruct) == -1)
                return -1;

        sf::WindowHandle hWnd = GetSafeHwnd();
        if(hWnd == nullptr || !IsWindow(hWnd))
                return -1; // Disallow invalid window handles

        create(hWnd); // Attach this window's handle to the SFML RenderWindow
       
        // This line simply tells the main app to use this class for
        //              Update and Render calls inbetween each Win32 message pump...
        theApp.SetCooperativeObject(this);

        return 0;
}

BOOL CSFMLMultiWindowTestView::Init()
{
        // Either load a texture, or exit the app if it doesn't work out
        m_texture = sf::Texture();
        if(!m_texture.loadFromFile("data/image1.bmp"))
                return FALSE;

        // Use the texture to create a sprite
        m_sprite = sf::Sprite();
        m_sprite.setTexture(m_texture);
        m_sprite.setPosition(0, 0);

        // Just to be 100% sure, force visibility
        ShowWindow(SW_SHOW);
        setVisible(true);

        return TRUE;
}

BOOL CSFMLMultiWindowTestView::Update(double timeElapsed)
{
        if(!m_bInitialized) {
                // We haven't been initialized yet. Do so now, and only once.
                m_bInitialized = Init();
                return m_bInitialized;
        }

        return TRUE;
}

VOID CSFMLMultiWindowTestView::Render()
{
        // Pretty basic render code...
        clear();
        draw(m_sprite); // WHY U NO WORK!?
        display();
}

Again, it works just fine when I allow SFML to create it's own window instead of passing in my window's handle...
So what the hell could cause it not to work with my own HWND? (ノಠ益ಠ)ノ彡┻━┻

Rectangle

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Re: Subclassing RenderWindow in an MFC SDI app?
« Reply #1 on: June 27, 2014, 01:24:31 pm »
Oops, I should probably note that I am using the latest version of SFML (v2.1, as of this post)...
The x86 static-debug versions for MSVC 2012 Ultimate.
« Last Edit: June 27, 2014, 01:27:25 pm by Rectangle »

Rectangle

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Re: Subclassing RenderWindow in an MFC SDI app?
« Reply #2 on: June 28, 2014, 09:07:27 am »
Well, it's incredibly hacky, but following the last few posts in this thread seemed to help a lot.
I honestly believe a better solution either exists, or should exist...
But after compiling the latest build on GitHub, and forcing the following code to run after each WM_SIZE event, it actually renders as expected:

CRect rc;
GetWindowRect(rc);
setSize(sf::Vector2u(rc.Width(), rc.Height()));
sf::View view = getView();
view.reset( sf::FloatRect(0, 0, float(rc.Width() - 1), float(rc.Height() - 1)) );
setView(view);

I can now safely subclass sf::RenderWindow in an MFC doc/view architecture application.
Unfortunately, I am no longer successful in linking to the static libs (due to lots of Code Generation RTL issues), but I'm okay with using the dynamic libs as long as they actually work as expected.