I'm working on some UI controls, and while I was looking for how to query the blinking time for the caret (text cursor in textboxes, GetCaretBlinkTime()
), I discovered that programs can create a caret and let windows handle the blinking. So I wanted to try it but I can't seem to make it work when the windows is updated often.
The docs says that I need to hide the caret whenever I draw outside of a paint message, and restore it after drawing. After a few tests, I found that I need to hide the caret before SwapBuffers()
and restore it after. That works, as long as there aren't a lot of messages/frame update. When there are a lot of updates (constant frame rate, or mouse_move messages) then the caret is barely ever visible.
Does anybody knows how to make that works ? Should I avoid that API ?
Here is a reproduction example.
/* cl main.c -Fequick.exe -nologo -Zi -Od -link -subsystem:windows user32.lib OpenGL32.lib GDI32.lib */ #include <stdio.h> #include <windows.h> #include <gl/gl.h> int running = 1; LRESULT CALLBACK window_proc( HWND window, UINT message, WPARAM wParam, LPARAM lParam ) { LRESULT result = 0; switch ( message ) { case WM_DESTROY : case WM_CLOSE : { running = 0; } break; default : { result = DefWindowProcW( window, message, wParam, lParam ); } break; } return result; } int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow ) { WNDCLASSW window_class = { 0 }; window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; window_class.lpfnWndProc = window_proc; window_class.hInstance = hInstance; window_class.lpszClassName = L"simple_window"; RegisterClassW( &window_class ); HWND handle = CreateWindowExW( 0, window_class.lpszClassName, L"Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, window_class.hInstance, 0 ); PIXELFORMATDESCRIPTOR pixel_format_descriptor = { sizeof( PIXELFORMATDESCRIPTOR ), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; HDC device_context = GetDC( handle ); int pixel_format = ChoosePixelFormat( device_context, &pixel_format_descriptor ); SetPixelFormat( device_context, pixel_format, &pixel_format_descriptor ); HGLRC render_context = wglCreateContext( device_context ); wglMakeCurrent( device_context, render_context ); ShowWindow( handle, SW_SHOW ); CreateCaret( handle, 0, 30, 30 ); SetCaretPos( 30, 30 ); ShowCaret( handle ); MSG message; while ( running && GetMessageW( &message, 0, 0, 0 ) ) { TranslateMessage( &message ); DispatchMessageW( &message ); while ( PeekMessageW( &message, 0, 0, 0, PM_REMOVE ) ) { TranslateMessage( &message ); DispatchMessageW( &message ); } glClearColor( 0, 0, 0, 1 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glBegin( GL_POLYGON ); glColor4f( 1, 0, 0, 1 ); glVertex2f( -0.5f, -0.5f ); glColor4f( 0, 1, 0, 1 ); glVertex2f( 0.5f, -0.5f ); glColor4f( 0, 0, 1, 1 ); glVertex2f( 0.0f, 0.5f ); glEnd( ); glFlush( ); HideCaret( handle ); SwapBuffers( device_context ); ShowCaret( handle ); } return 0; }