Any similar event to WM_PAINT in SDL(2) - sdl

I created very simple program using SDL2 to display window generated from ray tracer image:
auto* wnd = SDL_CreateWindow("Ray Tracer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, s.width, s.height, 0);
while (!quit) {
SDL_WaitEvent(&event);
...
While everything works, if I drag windows outside the screen and move back my windows becomes black. In windows APIs I had WM_PAINT, which would be sent to me in such cases. Is there similar event in SDL2?
Thanks for help!
Source code:
Reference to source code

It is SDL_WindowEvent with event->window.event set to SDL_WINDOWEVENT_EXPOSED.

Related

Why isn't sdl window responding to when I tried to click the minimize button or tried to drag the window?

I initialized and created an SDL window, with the code below. When I run it the window appears but, I can't drag the window and can't minimize it as the minimize button is also not responsive.
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindow("Game", 100, 100, 1020, 768, 0);
SDL_Event e;
bool canRun = true;
while(canRun){
}
return 0;
}
But if I add the code for events inside the while loop then the window becomes responsive to clicks and then I am able to click and drag the window.
SDL_Event e;
bool canRun = true;
while (canRun) {
while (SDL_PollEvent(&e)) {
}
}
How does this event code make the window responsive, even though I haven't added any event for closing, minimizing, or dragging the window?
The window behavior sounds familiar, so I'm assuming you are running on Windows; other platforms probably exhibit similar behavior.
Basically a window will be unresponsive unless it's message loop is run. It needs to process certain messages for e.g. the window sizing to work.
However, when using many UI libraries/frameworks, the application code does not need to handle all the events.
In the SDL case on Windows, SDL_PollEvent() ends up calling WIN_PumpEvents() in src/video/windows/SDL_windowsevents.c.
That has the 'magic' trio of Windows APIs calls to make a window work:
PeekMessage(), TranslateMessage(), and DispatchMEssage().
From DispatchMessage(), the default window procedure WIN_WindowProc() gets called. If you browse it's source code, you can see default handling for many windows messages, which enable the functionality for the window that you can witness without code supplied by yourself.
In cases where the application level needs to be involved, the window procedure function then passes the events to you:
case WM_SHOWWINDOW:
{
if (wParam) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
} else {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
}
}
break;
I did not read the code of SDL_SendWindowEvent(), but I'd guess it will result in you receiving the event from SDL_PollEvent().

SFML draws nothing from another thread, and can SFML coexist with GDI?

I'm writing a SFML test application with MFC. The following code runs inside an infinite loop in another thread started by AfxBeginThread() function. (Because I want to use SFML like it's in a pure WinAPI application)
// SFML Window and View were initialized using CView's HWND
// Use SFML to draw
sf::Color back(255, 255, 0); // a yellow background
_psfwnd->clear(back);
_psfwnd->display();
// Then use MFC GDI functions to draw
CWnd* pwnd;
pwnd = CWnd::FromHandle(_psfwnd->getSystemHandle()); // It seems that the HWND is valid
CPaintDC dc(pwnd);
CRect r(10, 10, 100, 100);
CBrush b(0xFF000000);
dc.FillRect(&r, &b); // draw a black rectangle
The result is a white background with a black rectangle. It seems that SFML draws nothing but MFC does.
Same code above. Now I put it into a MFC command handler (so the above code draws one frame when I click a button once).
This time the window background is yellow and MFC black rectangle is gone.
Now I am quite confused. I have two questions:
Why SFML doesn't draw the first time? It's because of threading, or initialization?
Why MFC doesn't draw when SFML does?
Don't use CPaintDC. It is specialized for use only in a WM_PAINT message handler. You can use CClientDC instead.

Popup window without stealing focus from other fullscreen programs

Hi so the title describes it pretty well, I'm currently working on a software that will be installed on a POS system now when an event occurs this program needs to create a popup for the cashier to confirm what my concern is that since this is a separate program from the POS if the POS is fullscreen (not windowed) It will steal focus from the POS thus having to wait 2 seconds while window flashes to black fullscreen pos goes down then popup comes up and then having to restore the POS.
I need to be able to get around this problem of POS minimizing and having the cashier's input as well.
Here is what I'm currently attempting.
// Create the window object
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,
ClsName, WndName,
WS_POPUPWINDOW | WS_CAPTION,
200, 120, 200, 320,
NULL, NULL, hInstance, NULL);
// Find out if the window was created
if( !hWnd ) // If the window was not created,
return 0; // stop the application
// Display the window to the user
Sleep(10000); //Used so I can open a fullscreen window to test
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
UpdateWindow(hWnd);
Thank you for your help :)

Float GLUT window on top without titlebar on OSX

I'm creating a simple commandline applicatiation that starts a GLUT window.
I need that GLUT window to be always on top and remove the titlebar.
Basically GLUT does not provide anything for this so i'm looking into other options. On Windows i would do something like:
glutCreateWindow( "dpd" ); //create window with glut
HWND hwnd = FindWindow( "GLUT", "dpd" );
SetWindowPos( hwnd, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOREPOSITION | SWP_NOSIZE ); //set the window always-on-top
But how can i do such a thing on OSX? (C++)
I already use some Carbon code to remove the menubar, but the titlebar is still visible:
SetSystemUIMode(kUIModeAllHidden,KWindowNoTitleBarAttribute);
i'm new to OSX development and out of ideas..
thanks
Ok, i found out that there is now way to make changes / ajustments to a glut window. So i finaly created a workaround: i start glut on one thread, on an other thread i created a fullscreen window with a transparent background and created a dynamic backgroundimage (png) with a viewport with just the size of the GLUT window without the titlebar. Sound kind a ugly but hey, it works, the client does get the result they want within budget :)
If you think there is a better solution for this without creating a manual openGL implementation please let me know!

How do I clear a Direct2D render target to fully transparent

I'm trying to draw semi-transparent rectangles on an invisible HWND. However, clearing the window with ID2D1HwndRenderTarget::Clear just makes the entire window black, so when I draw rectangles on top, they look semi-black.
If I don't Clear() and don't draw, then the window is invisible, as it should be. Clear() is the culprit here; however if I don't use it then painting messes up pretty badly.
Here's the code I'm using in my WindowProc:
case WM_PAINT:
// Begin drawing
pRenderTarget->BeginDraw();
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
// Clear the window
pRenderTarget->Clear();
// Paint the panel and its children
D2DSurface()->StartPainting();
{
D2DSurface()->PaintTraverse(panel);
}
D2DSurface()->FinishPainting();
// Finish drawing
HRESULT hr = plat->pRenderTarget->EndDraw();
Thanks in advance!
Transparency is a problem. The only window that support per-pixel transparency are WS_EX_LAYERED windows. These windows were designed for uses like drag-drop icons, and that leads to problems in every other usage.
Using D2D with WS_EX_LAYERED windows requires that you use a DXGI render target. To EndDraw, you get a DC out of the render target then pass that into the layered window and tell the layered window to update itself. (Try this with a HWNDRenderTarget - it will probably crash the device driver).
I suspect your window appears transparent because it's not drawing at all.
Another gotcha you may run into... if the window is sufficiently transparent, mouse clicks will go through it to the underlying window.
Use ID2D1DCRenderTarget instead of ID2D1HwndRendTarget, then bind the device context (DC) of your window before drawing begins.
Of course, you will need to set the WS_EX_LAYERED for your window and then call SetLayeredWindowAttributes to set the transparent color:
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
Screenshot:
When creating your RenderTarget, you'll have to tell D2D that you want to use alpha (in premultiplied mode) in the pixel format:
HRESULT hr = mD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat( DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED ) ),
D2D1::HwndRenderTargetProperties( mWindow, size ),
&mRenderTarget );
After this, calling Clear() with an alpha value of zero works just fine.