Remove Window Flicker

Just starting out? Need help? Post your questions and find answers here.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Remove Window Flicker

Post by netmaestro »

I removed the GrabImage and the ImageGadget altogether and it still wobbles:

Code: Select all

Procedure MoveWindow(void)
  Repeat
    If GetAsyncKeyState_(#VK_LBUTTON)&32768
      xpos = WindowX(0)
      ypos = WindowY(0)
      hDCin = CreateCompatibleDC_(0)
      SelectObject_(hDCin, ImageID(1))
      hDCout = StartDrawing(WindowOutput(0))
        BitBlt_(hDCout, 0, 0, 200, 200, hDCin, xpos, ypos ,#SRCCOPY)
      StopDrawing()
      DeleteDC_(hDCin)
    EndIf
    Delay(1)
    
  ForEver
EndProcedure

Procedure OpenWindowMagnify() 
  If OpenWindow(0, 0, 0, 200, 200, "Magnify", #PB_Window_ScreenCentered|#PB_Window_BorderLess)
    ;   SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
    ;   SetLayeredWindowAttributes_(WindowID(0), 0, #Null, #LWA_COLORKEY)
    StickyWindow(0, 1)
    Region = CreateEllipticRgn_(0, 0, 200, 200)
    SetWindowRgn_(WindowID(0), Region, #True)
    DeleteObject_(Region)
  EndIf
EndProcedure

UseJPEGImageDecoder()
LoadImage(1, "C:\test.jpg")
OpenWindowMagnify()
GrabImage(1, 2, WindowX(0), WindowY(0), 200, 200)
hDCin = CreateCompatibleDC_(0)
SelectObject_(hDCin, ImageID(1))
hDCout = StartDrawing(WindowOutput(0))
  BitBlt_(hDCout, 0, 0, 200, 200, hDCin, WindowX(0), WindowY(0) ,#SRCCOPY)
StopDrawing()
DeleteDC_(hDCin)
CreateThread(@MoveWindow(),0)

Repeat
  Select WaitWindowEvent()
      
    Case #WM_LBUTTONDOWN 
      SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, #Null) 
      
    Case #WM_LBUTTONDBLCLK
      CloseWindow(0)
      FreeImage(1)
      End
      
  EndSelect
ForEver
BERESHEIT
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Remove Window Flicker

Post by breeze4me »

Try this one, it seems to be no wobbles on my computer. (Win 7 x86, PB 4.61)


Edit: On Win7 x64(virtual machine), there is a wobble. With the classic theme of Windows, no wobble.
Edit2: the code modified.

Code: Select all

Prototype ptDwmIsCompositionEnabled(*pfEnabled)
Prototype ptDwmFlush()
Global DwmIsCompositionEnabled.ptDwmIsCompositionEnabled
Global DwmFlush.ptDwmFlush

If OSVersion() >= #PB_OS_Windows_Vista
  If OpenLibrary(0, "Dwmapi.dll")
    DwmIsCompositionEnabled = GetFunction(0, "DwmIsCompositionEnabled")
    DwmFlush = GetFunction(0, "DwmFlush")
  EndIf
EndIf

Global quit

#OldWndProc = "myoldwprc"

Global StartWinX, StartWinY, PrevMouseX, PrevMouseY, LDown

Procedure DrawImg(x, y)
  Protected Result
  If StartDrawing(WindowOutput(0))
    newImage = GrabImage(1, #PB_Any, x + 200, y + 200, 200, 200)
    If newImage
      DrawImage(ImageID(newImage), 0, 0)
      SetGadgetState(0, ImageID(newImage))
      FreeImage(newImage)
    EndIf
    StopDrawing()
  EndIf
  If DwmFlush And DwmIsCompositionEnabled
    DwmIsCompositionEnabled(@Result)
    If Result
      DwmFlush()
    EndIf
  EndIf
EndProcedure

Procedure WindowProc(hWnd, uMsg, wParam, lParam)
  Protected old = GetProp_(hWnd, #OldWndProc)
  
  Select uMsg
    Case #WM_ERASEBKGND
      ProcedureReturn 0
      
    Case #WM_PAINT
      DrawImg(WindowX(0), WindowY(0))
      
    Case #WM_LBUTTONDOWN
      LDown = 1
      StartWinX = WindowX(0)
      StartWinY = WindowY(0)
      
      GetCursorPos_(p.POINT)
      PrevMouseX = p\x
      PrevMouseY = p\y
      
    Case #WM_LBUTTONUP
      LDown = 0
      
    Case #WM_LBUTTONDBLCLK
      quit = 1
      
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, #OldWndProc)
      
  EndSelect
  
  ProcedureReturn CallWindowProc_(old, hWnd, uMsg, wParam, lParam)
EndProcedure

Procedure OpenWindowMagnify() 
  If OpenWindow(0, 0, 0, 200, 200, "Magnify", #PB_Window_ScreenCentered|#PB_Window_BorderLess)
   ;SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
   ;SetLayeredWindowAttributes_(WindowID(0), 0, #Null, #LWA_COLORKEY)
    StickyWindow(0, 1)
    Region = CreateEllipticRgn_(0, 0, 200, 200)
    SetWindowRgn_(WindowID(0), Region, #True)
    DeleteObject_(Region)
    SetProp_(WindowID(0), #OldWndProc, SetWindowLongPtr_(WindowID(0), #GWLP_WNDPROC, @WindowProc()))
  EndIf
EndProcedure

OpenWindow(1, 700, 0, 200, 200,  "", #PB_Window_BorderLess)
ImageGadget(0, 0, 0, 200, 200, 0)

UseJPEGImageDecoder()

If LoadImage(2, "c:\test.jpg")
  If CreateImage(1, ImageWidth(2) + 200, ImageHeight(2) + 200)
    StartDrawing(ImageOutput(1))
    DrawImage(ImageID(2), 200, 200)
    StopDrawing()
  EndIf
  FreeImage(2)
EndIf


OpenWindowMagnify()


Repeat
  ;event = WaitWindowEvent()
  event = WaitWindowEvent(1)
  
  If LDown
    GetCursorPos_(p.POINT)
    SetWindowPos_(WindowID(0), 0, StartWinX + p\x - PrevMouseX, StartWinY + p\y - PrevMouseY, 200, 200, #SWP_NOZORDER | #SWP_NOCOPYBITS)
  EndIf
  
Until quit = 1 Or event = #PB_Event_CloseWindow Or GetAsyncKeyState_(#VK_ESCAPE) & $8001

CloseWindow(0)
FreeImage(1)
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Remove Window Flicker

Post by IdeasVacuum »

using CopyImage after the GrabImage
Not surprised that failed, destined to make the issue worst I think. The idea was to avoid GrabImage() being in the loop.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Remove Window Flicker

Post by IdeasVacuum »

breeze4me
Edit2: the code modified.
Way Hey! That one works perfectly on my XP 32bit PC (Theme on too).
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
JHPJHP
Addict
Addict
Posts: 2253
Joined: Sat Oct 09, 2010 3:47 am

Re: Remove Window Flicker

Post by JHPJHP »

IdeasVacuum - I think at that point I was prepared to try anything.

netmaestro - you pretty much concluded that it's not a PB thing - thank you.

breeze4me - what planet are you from? I can understand the steps it took to substitute SendMessage for GetCursorPos and SetWindowPos, but the Dwm commands?.. seriously nice job.

IdeasVacuum
netmaestro
breeze4me

I can only say thank you so many times (before I'm considered a nut!) - but I'll test fate one more time.

Thank you all,
Last edited by JHPJHP on Tue Dec 23, 2014 9:33 am, edited 1 time in total.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
JHPJHP
Addict
Addict
Posts: 2253
Joined: Sat Oct 09, 2010 3:47 am

Re: Remove Window Flicker

Post by JHPJHP »

Hi again,

Moved around some of netmaestro & breeze4me's code to tweek the results, tried a few variations, kept one (rem'd out), but adding a constraint (CallBack) in placement of the Repeat/Forever Loop (thread) diminished results - slightly.

With the few added functions the effect is a cursor magnifying glass (only clearer if dealing with resized images) - exactly what I was after.

Thanks again guys,

Code: Select all

Prototype ptDwmIsCompositionEnabled(*pfEnabled)
Prototype ptDwmFlush()
Global DwmIsCompositionEnabled.ptDwmIsCompositionEnabled
Global DwmFlush.ptDwmFlush
Global DwmResult, hDCin, glassSize

Procedure OpenWindowMagnify() 
  If OpenWindow(0, 0, 0, glassSize, glassSize, "Magnify", #PB_Window_ScreenCentered | #PB_Window_BorderLess)
    StickyWindow(0, 1)
    winRegion = CreateEllipticRgn_(0, 0, glassSize, glassSize)
    SetWindowRgn_(WindowID(0), winRegion, #True)
    DeleteObject_(winRegion)
  EndIf
EndProcedure

Procedure DrawImg()
  hDCout = StartDrawing(WindowOutput(0))
    BitBlt_(hDCout, 0, 0, glassSize, glassSize, hDCin, WindowX(0), WindowY(0), #SRCCOPY)
  StopDrawing()
EndProcedure

Procedure MoveWindow(void)
  Repeat
    GetCursorPos_(p.POINT)
    xpos = p\x - (glassSize / 2)
    ypos = p\y - (glassSize) / 2)
    SetWindowPos_(WindowID(0), 0, xpos, ypos, glassSize, glassSize, #SWP_NOZORDER | #SWP_NOCOPYBITS)
    DrawImg()
    
    If DwmResult : DwmFlush() : EndIf
    
  ForEver
EndProcedure

; Procedure MoveWindow(hWnd, uMsg, wParam, lParam)
  ; Result = #PB_ProcessPureBasicEvents
  ; 
  ; Select uMsg
    ; Case #WM_SETCURSOR, #WM_PAINT, #WM_MOVING
      ; GetCursorPos_(p.POINT)
      ; xpos = p\x - (glassSize / 2)
      ; ypos = p\y - (glassSize) / 2)
      ; SetWindowPos_(WindowID(0), 0, xpos, ypos, glassSize, glassSize, #SWP_NOZORDER | #SWP_NOCOPYBITS)
      ; DrawImg()
      ; 
      ; If DwmResult : DwmFlush() : EndIf
      ; 
  ; EndSelect
  ; ProcedureReturn Result
; EndProcedure

If OSVersion() >= #PB_OS_Windows_Vista
  If OpenLibrary(0, "Dwmapi.dll")
    DwmIsCompositionEnabled = GetFunction(0, "DwmIsCompositionEnabled")
    DwmFlush = GetFunction(0, "DwmFlush")
    
    If DwmFlush And DwmIsCompositionEnabled : DwmIsCompositionEnabled(@DwmResult) : EndIf
    
  EndIf
EndIf
UseJPEGImageDecoder()
LoadImage(1, "C:\test.jpg")
glassSize = 200
OpenWindowMagnify()
ShowCursor_(0)
hDCin = CreateCompatibleDC_(0)
SelectObject_(hDCin, ImageID(1))
DrawImg()

If DwmResult : DwmFlush() : EndIf

CreateThread(@MoveWindow(), 0)
;SetWindowCallback(@MoveWindow())

Repeat
  Select WaitWindowEvent() 
    Case #WM_LBUTTONDBLCLK
      DeleteDC_(hDCin)
      ShowCursor_(1)
      CloseWindow(0)
      FreeImage(1)
      Break
  EndSelect
ForEver
Last edited by JHPJHP on Thu Jun 07, 2012 8:11 pm, edited 2 times in total.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Remove Window Flicker

Post by RASHAD »

Tested with Win 7 x64

Code: Select all

Global quit

#OldWndProc = "myoldwprc"

Global StartWinX, StartWinY, PrevMouseX, PrevMouseY, LDown

Procedure DrawImg(x, y)
  Protected Result
  If StartDrawing(WindowOutput(0))
    newImage = GrabImage(1, #PB_Any, x + 200, y + 200, 200, 200)
    If newImage
      DrawImage(ImageID(newImage), 0, 0)
      FreeImage(newImage)
    EndIf
    StopDrawing()
  EndIf
EndProcedure

Procedure WindowProc(hWnd, uMsg, wParam, lParam)
  Protected old = GetProp_(hWnd, #OldWndProc)
  
  Select uMsg
    Case #WM_ERASEBKGND
      ProcedureReturn 0
      
    Case #WM_PAINT
      DrawImg(WindowX(0), WindowY(0))
      
    Case #WM_LBUTTONDOWN
      LDown = 1
      StartWinX = WindowX(0)
      StartWinY = WindowY(0)
      
      GetCursorPos_(p.POINT)
      PrevMouseX = p\x
      PrevMouseY = p\y
      
    Case #WM_LBUTTONUP
      LDown = 0
      
    Case #WM_LBUTTONDBLCLK
      quit = 1
      
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, #OldWndProc)
      
  EndSelect
  
  ProcedureReturn CallWindowProc_(old, hWnd, uMsg, wParam, lParam)
EndProcedure

Procedure OpenWindowMagnify() 
  If OpenWindow(0, 0, 0, 200, 200, "Magnify", #PB_Window_ScreenCentered|#PB_Window_BorderLess)
    StickyWindow(0, 1)
    Region = CreateEllipticRgn_(0, 0, 200, 200)
    SetWindowRgn_(WindowID(0), Region, #True)
    DeleteObject_(Region)
    SetProp_(WindowID(0), #OldWndProc, SetWindowLongPtr_(WindowID(0), #GWLP_WNDPROC, @WindowProc()))
  EndIf
EndProcedure



If OSVersion() >= #PB_OS_Windows_Vista
  OpenLibrary(0, "dwmapi.dll")
  *comp=GetFunction(0,"DwmEnableComposition")
  CallFunctionFast(*comp,0)
EndIf

UseJPEGImageDecoder()

If LoadImage(2, "g:\1234_619647.jpg")
  If CreateImage(1, ImageWidth(2) + 200, ImageHeight(2) + 200)
    StartDrawing(ImageOutput(1))
    DrawImage(ImageID(2), 200, 200)
    StopDrawing()
  EndIf
  FreeImage(2)
EndIf


OpenWindowMagnify()


Repeat
  event = WaitWindowEvent(1)
  
  If LDown
    GetCursorPos_(p.POINT)
    SetWindowPos_(WindowID(0), 0, StartWinX + p\x - PrevMouseX, StartWinY + p\y - PrevMouseY, 200, 200, #SWP_NOZORDER | #SWP_NOCOPYBITS)
  EndIf
  
Until quit = 1 Or event = #PB_Event_CloseWindow Or GetAsyncKeyState_(#VK_ESCAPE) & $8001

If IsLibrary(0)
    CloseLibrary(0)
EndIf 
CloseWindow(0)
FreeImage(1)

Edit : Code updated for Win XP & Win 7 ,Not tested with Vista but it should work as expected
Last edited by RASHAD on Fri Jun 08, 2012 12:25 am, edited 1 time in total.
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Remove Window Flicker

Post by IdeasVacuum »

Hi JHPJHP

On WinXP 32bit, I see no wobble with your code but there is a definite flicker.

Rashad's code looks to be Win7 only, I have not tried it but usually you can bank on Rashad to pull a rabbit out of the hat 8)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
JHPJHP
Addict
Addict
Posts: 2253
Joined: Sat Oct 09, 2010 3:47 am

Re: Remove Window Flicker

Post by JHPJHP »

Thanks IdeasVacuum, at home I'm only on Windows 7 - 64 bit, but I'm going to create a VMWare XP - SP3 box to test with.

RASHAD - like the addition... Code to change the color scheme will definitely come in handy.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
JHPJHP
Addict
Addict
Posts: 2253
Joined: Sat Oct 09, 2010 3:47 am

Re: Remove Window Flicker

Post by JHPJHP »

Hi,

As I continued to write the application I was working on, where a small part was the Magnifier (which this thread is all about) - I kept revisiting the flicker issue. Even with all the fantastic help that I received - the flicker remained; greatly reduced because of the help, but still noticable.

Funny enough I went back to one of my first solutions / observations - by adding the following two lines of code - the flicker disappeared:

Code: Select all

SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(0), 0, #Null, #LWA_COLORKEY)
But setting the window to layered / transparent - wasn't a usable option so I quickly moved on...

Rethinking things (after numerous failed solutions - on my part) why couldn't I use it - just change the transparent color to one that would never occur (at least within this context):

Code: Select all

SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(0), RGB(124, 109, 146), #Null, #LWA_COLORKEY)
Maybe I'm jumping the gun, but in every test so far - no flicker - thought I'd share:

NB*: If this thread is of interest to you, and can help in any way - don't just rely on this last post - some really relevant code form some great scripters (which this example draws from) occurs earlier in the thread, and may be of more use.

Code: Select all

Prototype ptDwmIsCompositionEnabled(*pfEnabled)
Prototype ptDwmFlush()
Global DwmIsCompositionEnabled.ptDwmIsCompositionEnabled
Global DwmFlush.ptDwmFlush
Global DwmResult, hDCin, glassSize

Procedure OpenWindowMagnify() 
  If OpenWindow(0, 0, 0, glassSize, glassSize, "Magnify", #PB_Window_ScreenCentered | #PB_Window_BorderLess)
    SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
    SetLayeredWindowAttributes_(WindowID(0), RGB(124, 109, 146), #Null, #LWA_COLORKEY)
    StickyWindow(0, 1)
    winRegion = CreateEllipticRgn_(0, 0, glassSize, glassSize)
    SetWindowRgn_(WindowID(0), winRegion, #TRUE)
    DeleteObject_(winRegion)
  EndIf
EndProcedure

Procedure DrawImg()
  hDCout = StartDrawing(WindowOutput(0))
    BitBlt_(hDCout, 0, 0, glassSize, glassSize, hDCin, WindowX(0), WindowY(0), #SRCCOPY)
  StopDrawing()
EndProcedure

Procedure MoveWindow(void)
  Repeat
    GetCursorPos_(p.POINT)
    xpos = p\x - (glassSize / 2)
    ypos = p\y - (glassSize / 2)
    SetWindowPos_(WindowID(0), 0, xpos, ypos, glassSize, glassSize, #SWP_NOZORDER | #SWP_NOCOPYBITS)
    DrawImg()
    
    If DwmResult : DwmFlush() : EndIf
    
  ForEver
EndProcedure

If OSVersion() >= #PB_OS_Windows_Vista
  If OpenLibrary(0, "Dwmapi.dll")
    DwmIsCompositionEnabled = GetFunction(0, "DwmIsCompositionEnabled")
    DwmFlush = GetFunction(0, "DwmFlush")
    
    If DwmFlush And DwmIsCompositionEnabled : DwmIsCompositionEnabled(@DwmResult) : EndIf
    
  EndIf
EndIf
UseJPEGImageDecoder()
LoadImage(1, "C:\test.jpg")
glassSize = 200
OpenWindowMagnify()
ShowCursor_(0)
hDCin = CreateCompatibleDC_(0)
SelectObject_(hDCin, ImageID(1))
DrawImg()

If DwmResult : DwmFlush() : EndIf

CreateThread(@MoveWindow(), 0)

Repeat
  Select WaitWindowEvent() 
    Case #WM_LBUTTONDBLCLK
      DeleteDC_(hDCin)
      ShowCursor_(1)
      CloseWindow(0)
      FreeImage(1)
      Break
  EndSelect
ForEver

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Post Reply