Graphics library that won't suspend while being dragged?

Windows specific questions.
Post Reply
nobozoz
Posts: 238
Joined: Nov 17, 2005 6:24
Location: Chino Hills, CA, USA

Graphics library that won't suspend while being dragged?

Post by nobozoz »

I am looking for a Windows graphics library for use with fb that has ZERO dependence upon 'fbgfx'. This is because of a bug in fbgfx that I simply cannot "live with" and which isn't a high priority to the fb devs to fix. I'm not a dev and never will be - I just need to find some way to write a graphics window app in fb that doesn't suspend operation whenever the window is clicked and dragged.

Is there anything in the fb arsenal that can completely replace fbgfx?

Thanks,

Jim
bojan.dosen
Posts: 166
Joined: May 14, 2007 12:20
Location: Zagreb, Croatia

Re: fb v0.24 examples problems

Post by bojan.dosen »

Hi,
You don't need to replace fbgfx. This bug can be fixed with custom window procedure and hidden fbgfx window. Custom procedure gets all pixels from fbgfx buffer and draw it back to visible window. When you drag window, it continues to paint itself. And also, you can re-size window as this is not possible with fbgfx window.
Here is an example:

gfx.bi:

Code: Select all

#Include Once "windows.bi"

Dim Shared As HINSTANCE hInst
hInst = GetModuleHandle(NULL)

Type WndParams
   As BITMAPV4HEADER bmi
   As Integer scrw, scrh
End Type

Dim Shared As HWND GraphicsHWND

Function WndProc(hWnd As HWND, msg As UINT, wParam As WPARAM, lParam As LPARAM) As LRESULT
   Dim As WndParams Ptr wndp
   wndp = Cast(WndParams Ptr, GetWindowLong(hWnd, GWL_USERDATA))
   
   Select Case msg
   	Case WM_CREATE
         wndp = Allocate(SizeOf(WndParams))
         SetWindowLong(hWnd, GWL_USERDATA, Cast(Long, wndp))
         
         wndp->scrw = GetSystemMetrics(SM_CXSCREEN)
         wndp->scrh = GetSystemMetrics(SM_CYSCREEN)
         
         With wndp->bmi
            .bV4Size            = Len( BITMAPV4HEADER )
            .bv4width         = wndp->scrw
            .bv4height         = -wndp->scrh
            .bv4planes         = 1
            .bv4bitcount      = 32
            .bv4v4compression   = 0
            .bv4sizeimage      = wndp->scrw*wndp->scrh*4
            .bV4RedMask         = &h0F00
            .bV4GreenMask      = &h00F0
            .bV4BlueMask      = &h000F
            .bV4AlphaMask      = &hF000
         End With
         
         SetTimer(hWnd, 1, 1000/25, 0)
         
   	Case WM_PAINT
         Dim As PAINTSTRUCT ps
         Dim As Integer x, y, w, h
         
         BeginPaint(hWnd, @ps)
            x = ps.rcPaint.left
            y = ps.rcPaint.top
            w = ps.rcPaint.right-x
            h = ps.rcPaint.bottom-y
            
            StretchDIBits(ps.hdc, x, y, w, h, x, y, w, h, ScreenPtr, CPtr(BITMAPINFO Ptr, @wndp->bmi), DIB_RGB_COLORS, SRCCOPY)
         EndPaint(hWnd, @ps)
         
   	Case WM_TIMER
         RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE)
         
   	Case WM_DESTROY
         DeAllocate(wndp)
         PostQuitMessage(NULL)
         End
         
   End Select
   
   Return DefWindowProc(hWnd, msg, wParam, lParam)
End Function

Sub WinMain(wndSize As UInteger)
   Dim As MSG         uMsg
   Dim As WNDCLASS   wcls
   
   With wcls
      .style         = CS_HREDRAW Or CS_VREDRAW
      .lpfnWndProc   = Cast(WNDPROC, @WndProc)
      .hInstance      = hInst
      .hIcon         = LoadIcon(NULL, IDI_APPLICATION)
      .hCursor         = LoadCursor(NULL, IDC_ARROW)
      .hbrBackground   = GetStockObject(WHITE_BRUSH)
      .lpszMenuName   = NULL
      .lpszClassName   = StrPtr("GfxClass")
   End With
   
   If RegisterClass(@wcls) = FALSE Then
      MessageBox(NULL, "Failed to register GfxClass!", "Error!", MB_OK Or MB_ICONERROR)
      End
   EndIf
   
   ScreenRes GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 32,, -1
   GraphicsHWND = CreateWindowEx(NULL, "GfxClass", "GFX Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, LoWord(wndSize), HiWord(wndSize), NULL, NULL, hInst, NULL)
   
   ShowWindow(GraphicsHWND, SW_NORMAL)
   UpdateWindow(GraphicsHWND)
   
   While GetMessage(@uMsg, NULL, NULL, NULL) <> FALSE
      TranslateMessage(@uMsg)
      DispatchMessage(@uMsg)
   Wend
End Sub

Sub ScreenCreate(w As Integer, h As Integer)
   ThreadCreate(@WinMain, MAKELPARAM(w, h))
   Sleep 100, 1
End Sub

Function ScreenWidth(w As Integer = 0) As Integer
   Dim As RECT rc
   
   If w > 0 Then
      GetWindowRect(GraphicsHWND, @rc)
      MoveWindow(GraphicsHWND, rc.left, rc.top, w, rc.bottom-rc.top, FALSE)
   EndIf
   
   GetClientRect(GraphicsHWND, @rc)
   Return rc.right
End Function

Function ScreenHeight(h As Integer = 0) As Integer
   Dim As RECT rc
   
   If h > 0 Then
      GetWindowRect(GraphicsHWND, @rc)
      MoveWindow(GraphicsHWND, rc.left, rc.top, rc.bottom-rc.top, h, FALSE)
   EndIf
   
   GetClientRect(GraphicsHWND, @rc)
   Return rc.bottom
End Function
Example.bas:

Code: Select all

#Include "gfx.bi"

ScreenCreate(800, 600)

Dim As Integer x1, y1, x2, y2
Randomize Timer

Color RGB(0, 0, 0), RGB(255, 255, 255)
Cls
Line (100, 100)-(600, 600), RGB(255, 0, 0), BF

Do
   x1 = Rnd(1)*ScreenWidth()
   y1 = Rnd(1)*ScreenHeight()
   x2 = Rnd(1)*ScreenWidth()
   y2 = Rnd(1)*ScreenHeight()
   
   Line(x1, y1)-(x2, y2)
   Sleep 1000/25
Loop
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fb v0.24 examples problems

Post by fxm »

A small remark about gfx.bi:
To avoid warnings due to the bad-type arguments passed to ThreadCreate:
... (100) warning 3(1): Passing different pointer types, at parameter 1 of THREADCREATE()
... (100) warning 1(1): Passing scalar as pointer, at parameter 2 of THREADCREATE()
We can now use easily Threadcall (from version 0.24.0):
ThreadCreate(@WinMain, MAKELPARAM(w, h))
Threadcall WinMain(MAKELPARAM(w, h))
nobozoz
Posts: 238
Joined: Nov 17, 2005 6:24
Location: Chino Hills, CA, USA

Re: fb v0.24 examples problems

Post by nobozoz »

Looking good so far.

The next thing is to replace InKey() and/or MultiKey() which no longer seem to work as before. I suspect I will be using WM_KEYDOWN trapping or some other Windows mechanism - we'll see.

Any suggestions before I get too far along would be appreciated. I need to allow the user to interact randomly, but transparently as the window is rapidly repainted. The application is basically a real-time numerical instrument display with a strip chart plot.

Thank you,

Jim
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: fb v0.24 examples problems

Post by MichaelW »

Under Windows I think multikey calls GetKeyboardState. There are other choices, all involving a relatively large amount of overhead, and the optimal choice probably depends on how many different keys you need to monitor.

Code: Select all

''=============================================================================
#include "counter.bas"
''=============================================================================

''---------------------------------------------------
'' Increase our priority to minimize interruptions.
''---------------------------------------------------

''-------------------------------------------------------
'' These values not recommended for single core systems.
''-------------------------------------------------------

'#define PP REALTIME_PRIORITY_CLASS
'#define TP THREAD_PRIORITY_TIME_CRITICAL

''---------------------------------------------------------------------
'' These values for safety on my single-core P3 with MSE, etc running.
''---------------------------------------------------------------------

#define PP HIGH_PRIORITY_CLASS
#define TP THREAD_PRIORITY_NORMAL

''=============================================================================

dim as any ptr p = allocate(256)
dim as short r

SetProcessAffinityMask( GetCurrentProcess(), 1)

sleep 5000

for i as integer = 1 to 4

    counter_begin( 1000000, PP, TP )
    counter_end()
    print counter_cycles;" cycles"

    counter_begin( 1000000, PP, TP )
        r = GetAsyncKeyState( VK_X )
    counter_end()
    print counter_cycles;" cycles"

    counter_begin( 1000000, PP, TP )
        r = GetKeyState( VK_X )
    counter_end()
    print counter_cycles;" cycles"

    counter_begin( 1000000, PP, TP )
        GetKeyboardState( p )
    counter_end()
    print counter_cycles;" cycles"
    print

next

sleep
Running on a P3:

Code: Select all

 0 cycles
 602 cycles
 520 cycles
 5976 cycles

 0 cycles
 601 cycles
 520 cycles
 5975 cycles

 0 cycles
 602 cycles
 519 cycles
 5973 cycles

 0 cycles
 601 cycles
 521 cycles
 5972 cycles
I did not try to time this, but I suspect that a WM_KEYDOWN/UP handler would also involve a relatively large amount of overhead.

The newer cycle-count macros are here.
nobozoz
Posts: 238
Joined: Nov 17, 2005 6:24
Location: Chino Hills, CA, USA

Re: Graphics library that won't suspend while being dragged?

Post by nobozoz »

fxm-

I tried your suggestion for gfx.bi,
'-------------------------------------------------------------------
We can now use easily Threadcall (from version 0.24.0):
ThreadCreate(@WinMain, MAKELPARAM(w, h))
Threadcall WinMain(MAKELPARAM(w, h))
'-------------------------------------------------------------------
... but when I did, I got this response from fbc -
'-------------------------------------------------------------------
G:\fb.24\fbc -s console -v -mt -w pedantic -t 2048 -lang fb "gfx2-test.bas"
FreeBASIC Compiler - Version 0.24.0 (08-19-2012) for win32
Copyright (C) 2004-2012 The FreeBASIC development team.
standalone, objinfo (libbfd 217)
compiling: gfx2-test.bas -o gfx2-test.asm (main module)
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(16) warning 15(0): No explicit BYREF or BYVAL, at parameter 1 (hWnd) of WndProc()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(16) warning 15(0): No explicit BYREF or BYVAL, at parameter 2 (msg) of WndProc()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(16) warning 15(0): No explicit BYREF or BYVAL, at parameter 3 (wParam) of WndProc()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(16) warning 15(0): No explicit BYREF or BYVAL, at parameter 4 (lParam) of WndProc()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(70) warning 15(0): No explicit BYREF or BYVAL, at parameter 1 (wndSize) of WinMain()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(102) warning 15(0): No explicit BYREF or BYVAL, at parameter 1 (w) of ScreenCreate()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(102) warning 15(0): No explicit BYREF or BYVAL, at parameter 2 (h) of ScreenCreate()
G:\fb.24\fbgfx_on_windows-fix\gfx.bi(109) warning 15(0): No explicit BYREF or BYVAL, at parameter 1 (w) of ScreenWidth()

Aborting due to runtime error 12 ("segmentation violation" signal)
'-------------------------------------------------------------------
The original gfx.bi compiled and linked without any complaint other than the 'warnings'. Did I miss something?

Thanks,
Jim
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Graphics library that won't suspend while being dragged?

Post by fxm »

Yes, you are right.
I tested it and it works only with fbc 0.25.0 (not with fbc 0.24.0)!

changelog.txt (fbc 0.25.0):
Version 0.25.0:
[fixed]
- internal error in ThreadCall parser, potentially causing compiler crashes or miscompilation


Remark:
With fbc 0.24.0, you can suppress the pointer warning message by modifying these two lines:
Sub WinMain(wndSize As UInteger)
Sub WinMain(wndSize As Any Ptr)

ThreadCreate(@WinMain, MAKELPARAM(w, h))
ThreadCreate(@WinMain, Cast(Any Ptr, MAKELPARAM(w, h)))
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Graphics library that won't suspend while being dragged?

Post by counting_pine »

I think the parameters all scalars (as opposed to Strings or user-defined types), so you can get rid of the BYVAL/BYREF messages by putting Byval before each parameter name in the sub/function headers.
Or by removing '-w pedantic' from the compiler command line. Although the pedantic warnings can be useful at times.
Post Reply