Page 1 of 2
Flickering when MDI child move [Resolved]
Posted: Tue Oct 31, 2017 3:45 pm
by Kwai chang caine
Hello at all
I try to move a child window
always at the same distance from the bottom of the windows
But i have a flickering, the chlid windows appears two times, and i don't understand why
I can't use
#PB_MDI_AutoSize when i create the MDI, it's the reason why i must resize the MDI in the callback
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
Global IdChild
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_SIZE And hWnd = WindowID(#FenetrePrincipale)
ResizeGadget(#MdiGadget, 0, 0, WindowWidth(#FenetrePrincipale), WindowHeight(#FenetrePrincipale))
ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - (WindowY(IdChild, #PB_Window_InnerCoordinate) + 19), #PB_Ignore, #PB_Ignore)
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
ShowWindow_(WindowID(IdChild), #SW_SHOWMINIMIZED)
ResizeWindow(IdChild, 100, 100, #PB_Ignore, #PB_Ignore)
UseGadgetList(WindowID(#FenetrePrincipale))
SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Have a good day
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 4:31 pm
by infratec
The problem is, that WindowY() returns toggling values. Looks like a bug.
I'll try something.
Bernd
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 4:37 pm
by Julian
I came to the same conclusion, here's a working version, I hope its what you wanted:
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
;MACROS from http://forums.purebasic.com/english/viewtopic.php?p=439919&sid=8e97d5aba0e4678f3e64140ee1846d83#p439919
Macro LOWORD(dwValue) : dwValue & $FFFF : EndMacro;
Macro HIWORD(dwValue) : dwValue >> 16 : EndMacro;
Macro MAKELPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;
Macro MAKEWPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;
Global IdChild
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_SIZE And hWnd = WindowID(#FenetrePrincipale)
w = LOWORD(lparam)
h = HIWORD(lparam)
ResizeGadget(#MdiGadget, 0, 0, WindowWidth(#FenetrePrincipale), WindowHeight(#FenetrePrincipale))
;ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - (WindowY(IdChild, #PB_Window_InnerCoordinate) + 19), #PB_Ignore, #PB_Ignore)
Debug "WindowY(IdChild, #PB_Window_InnerCoordinate)=" + WindowY(IdChild, #PB_Window_InnerCoordinate)
ResizeWindow(IdChild, #PB_Ignore, h - WindowHeight(IdChild) - 19, #PB_Ignore, #PB_Ignore)
ProcedureReturn 0
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
ShowWindow_(WindowID(IdChild), #SW_SHOWMINIMIZED)
ResizeWindow(IdChild, 100, 100, #PB_Ignore, #PB_Ignore)
UseGadgetList(WindowID(#FenetrePrincipale))
SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 4:53 pm
by Kwai chang caine
Thanks at you two for your quick answer
@JULIAN
I have try your code and unfortunaltely, the child window, is not at the same distance of the bottom of the window when i resize #FenetrePrincipale, it sticked at the bottom
Me i search to have always the same distance between the bottom of the child window and the bottom of the GadgetMdi

Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 5:11 pm
by infratec
My dirty dirty hack:
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
Global IdChild
Structure WindowHelpStructure
x.i
y.i
bottom.i
EndStructure
Define ChildWindow.WindowHelpStructure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
Auto = 2
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
SetWindowState(IdChild, #PB_Window_Minimize)
ResizeWindow(IdChild, 100, 100, #PB_Ignore, #PB_Ignore)
ChildWindow\x = 100
ChildWindow\y = 100
ChildWindow\bottom = GadgetHeight(#MdiGadget) - 100 - 19
UseGadgetList(WindowID(#FenetrePrincipale))
;SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Select EventWindow()
Case #FenetrePrincipale
Select Event
Case #PB_Event_SizeWindow
ResizeGadget(#MdiGadget, 0, 0, WindowWidth(#FenetrePrincipale), WindowHeight(#FenetrePrincipale))
Debug "ResizeWindowMain"
;ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - ChildWindow\y, #PB_Ignore, #PB_Ignore)
PostEvent(#PB_Event_SizeWindow, IdChild, 0)
EndSelect
Case IdChild
Select Event
Case #PB_Event_SizeWindow
Debug "ChildResize " + Str(ChildWindow\y)
Auto + 1
ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - ChildWindow\bottom, #PB_Ignore, #PB_Ignore)
Case #PB_Event_MoveWindow
If Auto = 0
Debug "ChildMove"
ChildWindow\x = WindowX(IdChild, #PB_Window_InnerCoordinate)
ChildWindow\y = WindowY(IdChild, #PB_Window_InnerCoordinate) - WindowY(#FenetrePrincipale, #PB_Window_InnerCoordinate)
ChildWindow\bottom = GadgetHeight(#MdiGadget) - ChildWindow\y + 19
Debug ChildWindow\y
Debug ChildWindow\bottom
Else
Auto - 1
EndIf
EndSelect
EndSelect
Until Event=#PB_Event_CloseWindow
Bernd
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 5:21 pm
by Kwai chang caine
Thanks a lot INFRATEC it's exactely this effect i search to have
But here, the child window follow the MDI, only when i finish to resizing, not in the same time, is it normal ?

Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 6:24 pm
by Julian
Sorry, I didnt understand what you wanted, here you go.
You can trim it down to size, there's a lot of debug/testing in there. The problem is that you need to remember the old position as you dont know how far to keep it away from the new size of the window.
The +6 is probably due to border size, you can find
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
;MACROS from http://forums.purebasic.com/english/viewtopic.php?p=439919&sid=8e97d5aba0e4678f3e64140ee1846d83#p439919
Macro LOWORD(dwValue) : dwValue & $FFFF : EndMacro;
Macro HIWORD(dwValue) : dwValue >> 16 : EndMacro;
Macro MAKELPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;
Macro MAKEWPARAM( loWord, hiWord) : (hiWord << 16 | loWord) : EndMacro;
Global IdChild
Global Old_ParentWindowRect.RECT, Old_ParentClientRect.RECT
Global Old_ChildWindowRect.RECT, Old_ChildClientRect.RECT
Procedure CalcDiff(*new.RECT, *old.RECT, *out.RECT)
*out\left = *new\left - *old\left
*out\right = *new\right - *old\right
*out\top = *new\top - *old\top
*out\bottom = *new\bottom - *old\bottom
EndProcedure
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_SIZING And hWnd = WindowID(#FenetrePrincipale)
GetWindowRect_(WindowID(#FenetrePrincipale), Old_ParentWindowRect)
GetClientRect_(WindowID(#FenetrePrincipale), Old_ParentClientRect)
;Debug "Old_ParentWindowRect l=" + Old_ParentWindowRect\left + " t=" + Old_ParentWindowRect\top + " r=" + Old_ParentWindowRect\right + " b=" + Old_ParentWindowRect\bottom
;Debug "Old_ParentClientRect l=" + Old_ParentClientRect\left + " t=" + Old_ParentClientRect\top + " h=" + Old_ParentClientRect\right + " h=" + Old_ParentClientRect\bottom
GetWindowRect_(WindowID(IdChild), Old_ChildWindowRect)
GetClientRect_(WindowID(IdChild), Old_ChildClientRect)
;Debug "ChildWindowRect l=" + Old_ChildWindowRect\left + " t=" + Old_ChildWindowRect\top + " r=" + Old_ChildWindowRect\right + " b=" + Old_ChildWindowRect\bottom
;Debug "ChildClientRect l=" + Old_ChildClientRect\left + " t=" + Old_ChildClientRect\top + " w=" + Old_ChildClientRect\right + " h=" + Old_ChildClientRect\bottom
EndIf
If uMsg = #WM_SIZE And hWnd = WindowID(#FenetrePrincipale)
w = LOWORD(lparam)
h = HIWORD(lparam)
WindowRect.RECT
;
; GetWindowRect_(WindowID(IdChild), WindowRect)
; Debug "l=" + WindowRect\left + " t=" + WindowRect\top + " r=" + WindowRect\right + " b=" + WindowRect\bottom
; GetClientRect_(WindowID(IdChild), WindowRect)
; Debug "l=" + WindowRect\left + " t=" + WindowRect\top + " w=" + WindowRect\right + " h=" + WindowRect\bottom
;
ParentWindowRect.RECT
ParentClientRect.RECT
GetWindowRect_(WindowID(#FenetrePrincipale), ParentWindowRect)
GetClientRect_(WindowID(#FenetrePrincipale), ParentClientRect)
Debug "AFTER ParentWindowRect l=" + ParentWindowRect\left + " t=" + ParentWindowRect\top + " r=" + ParentWindowRect\right + " b=" + ParentWindowRect\bottom
Debug "AFTER ParentClientRect l=" + ParentClientRect\left + " t=" + ParentClientRect\top + " h=" + ParentClientRect\right + " h=" + ParentClientRect\bottom
ChildWindowRect.RECT
ChildClientRect.RECT
GetWindowRect_(WindowID(IdChild), ChildWindowRect)
GetClientRect_(WindowID(IdChild), ChildClientRect)
Debug "ChildWindowRect l=" + ChildWindowRect\left + " t=" + ChildWindowRect\top + " r=" + ChildWindowRect\right + " b=" + ChildWindowRect\bottom
Debug "ChildClientRect l=" + ChildClientRect\left + " t=" + ChildClientRect\top + " w=" + ChildClientRect\right + " h=" + ChildClientRect\bottom
ParentWindowMovement.RECT
ParentClientMovement.RECT
CalcDiff(ParentWindowRect, Old_ParentWindowRect, ParentWindowMovement)
CalcDiff(ParentClientRect, Old_ParentClientRect, ParentClientMovement)
Debug "ParentWindowMovement l=" + ParentWindowMovement\left + " t=" + ParentWindowMovement\top + " r=" + ParentWindowMovement\right + " b=" + ParentWindowMovement\bottom
ChildWindowMovement.RECT
ChildClientMovement.RECT
CalcDiff(ChildWindowRect, Old_ChildWindowRect, ChildWindowMovement)
CalcDiff(ChildClientRect, Old_ChildClientRect, ChildClientMovement)
Debug "ChildWindowMovement l=" + ChildWindowMovement\left + " t=" + ChildWindowMovement\top + " r=" + ChildWindowMovement\right + " b=" + ChildWindowMovement\bottom
ResizeGadget(#MdiGadget, 0, 0, WindowWidth(#FenetrePrincipale), WindowHeight(#FenetrePrincipale))
ChildNewTop = ((ChildWindowRect\top - ParentWindowRect\top) + ParentWindowMovement\bottom) - ((ChildWindowRect\bottom - ChildWindowRect\top) - ChildClientRect\bottom) + 6
;FromTop = ChildWindowRect\top - ParentWindowRect\top
Debug "ChildNewTop=" + ChildNewTop
;Debug "FromTop=" + FromTop
;ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - (WindowY(IdChild, #PB_Window_InnerCoordinate) + 19), #PB_Ignore, #PB_Ignore)
;Debug "WindowY(IdChild, #PB_Window_InnerCoordinate)=" + WindowY(IdChild, #PB_Window_InnerCoordinate)
ResizeWindow(IdChild, #PB_Ignore, ChildNewTop, #PB_Ignore, #PB_Ignore)
ProcedureReturn 0
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
ShowWindow_(WindowID(IdChild), #SW_SHOWMINIMIZED)
ResizeWindow(IdChild, 100, 100, #PB_Ignore, #PB_Ignore)
UseGadgetList(WindowID(#FenetrePrincipale))
SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 6:53 pm
by Kwai chang caine
Thanks again, but this time the child window disapear when i resize the window
Sorry, I didnt understand what you wanted, here you go.
A little drawing is better than too much talk
I open the window, for exampler the value of the distance between the bottom of child window "classeur1" and bottom of MDI is 10
Now i resize the window, and i want the value of the distance between the bottom of child window "classeur1" and bottom of MDI continue to be 10
You see in my photo, the distance have changed it's not good, i want always the value of the beginning before, during, and after resize the main window
No more, no less...always 10

Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 7:38 pm
by infratec
But something with the -19 is wrong
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
Global IdChild
Structure WindowHelpStructure
x.i
y.i
bottom.i
EndStructure
Global ChildWindow.WindowHelpStructure
Global Auto.i
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_SIZE
Select hWnd
Case WindowID(#FenetrePrincipale)
ResizeGadget(#MdiGadget, 0, 0, WindowWidth(#FenetrePrincipale), WindowHeight(#FenetrePrincipale))
Auto + 1
ResizeWindow(IdChild, #PB_Ignore, GadgetHeight(#MdiGadget) - ChildWindow\bottom, #PB_Ignore, #PB_Ignore)
EndSelect
EndIf
If uMsg = #WM_MOVE
If hWnd = WindowID(IdChild)
If Auto = 0
ChildWindow\x = lParam & $FFFF
ChildWindow\y = lParam >> 16
ChildWindow\bottom = GadgetHeight(#MdiGadget) - ChildWindow\y - 19
Else
Auto - 1
EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
SetWindowState(IdChild, #PB_Window_Minimize)
ChildWindow\x = 100
ChildWindow\y = 100
ChildWindow\bottom = GadgetHeight(#MdiGadget) - ChildWindow\y - 19
ResizeWindow(IdChild, 100, GadgetHeight(#MdiGadget) - ChildWindow\bottom, #PB_Ignore, #PB_Ignore)
UseGadgetList(WindowID(#FenetrePrincipale))
SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Bernd
Re: Flickering when MDI child move
Posted: Tue Oct 31, 2017 7:44 pm
by Kwai chang caine
Yeeeeeaaaaaahhh !!!
That works very well, and it's exactely the effect i want
It's a very hard code for just do this simple effect
Never i can found that alone
One thousand of thanks INFRATEC
I want also thanks JULIAN, for all the time he have spent for me
Have a very good day at you two

Re: Flickering when MDI child move [Resolved]
Posted: Tue Oct 31, 2017 7:53 pm
by infratec
Corrected version:
Code: Select all
#FenetrePrincipale = 0
#FenetreFille = 1
#MdiGadget = 2
Global IdChild
Structure WindowHelpStructure
x.i
y.i
bottom.i
EndStructure
Global ChildWindow.WindowHelpStructure
Global Auto.i
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_SIZE
Select hWnd
Case WindowID(#FenetrePrincipale)
ResizeGadget(#MdiGadget, 0, 0, lParam & $FFFF, lParam >> 16)
Auto + 1
ResizeWindow(IdChild, #PB_Ignore, (lParam >> 16) - ChildWindow\bottom, #PB_Ignore, #PB_Ignore)
EndSelect
EndIf
If uMsg = #WM_MOVE
If hWnd = WindowID(IdChild)
If Auto = 0
ChildWindow\x = lParam & $FFFF
ChildWindow\y = lParam >> 16
;Debug Str(GadgetHeight(#MdiGadget)) + " " + Str(ChildWindow\y)
ChildWindow\bottom = GadgetY(#MdiGadget) + GadgetHeight(#MdiGadget) - ChildWindow\y
Else
Auto - 1
EndIf
;Debug ChildWindow\y
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#FenetrePrincipale, 0, 0, 600, 400, "MDIGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
MDIGadget(#MdiGadget, 0, 0, 600, 400, 0, 0, #PB_MDI_NoScrollBars)
IdChild = AddGadgetItem(#MdiGadget, #PB_Any, "Fenêtre fille")
SetWindowState(IdChild, #PB_Window_Minimize)
ChildWindow\x = 100
ChildWindow\y = 100
;ChildWindow\bottom = GadgetHeight(#MdiGadget) - ChildWindow\y - 31
ChildWindow\bottom = GadgetY(#MdiGadget) + GadgetHeight(#MdiGadget) - ChildWindow\y
ResizeWindow(IdChild, 100, GadgetHeight(#MdiGadget) - ChildWindow\bottom, #PB_Ignore, #PB_Ignore)
UseGadgetList(WindowID(#FenetrePrincipale))
SetWindowCallback(@WinCallback())
Repeat
Event = WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Bernd
Re: Flickering when MDI child move [Resolved]
Posted: Tue Oct 31, 2017 7:58 pm
by Kwai chang caine
The last version worked, but if you say it's better...i say this one is better

Again thanks MASTER for all your precious help since all this years

Re: Flickering when MDI child move [Resolved]
Posted: Wed Nov 01, 2017 4:00 pm
by Julian
FYI the above two pieces of code cause incorrect movement in the window on Windows 10. Its to do with the different sizes of windows borders etc between editions of the Windows. If you're just running this on your OS then no worries, but if you want it to work elsewhere you will need to calculate the offset (+6 in my code and -+19 in the other two codes).
I was writing this in my post but I cut it off for some reason.
"The +6 is probably due to border size, you can find"
You can find out the border sizes using
GetSystemMetrics
Re: Flickering when MDI child move [Resolved]
Posted: Wed Nov 01, 2017 6:45 pm
by Kwai chang caine
Ok thanks for your advice
Yesterday, i have W7 X86 and the INFRATEC code works very well
Today, i have W10 X64 and the INFRATEC code works also good than with W7
For the moment only good news

Re: Flickering when MDI child move [Resolved]
Posted: Wed Nov 01, 2017 6:54 pm
by Julian
This is what I see, there is a jump when the window is open.
https://www.dropbox.com/s/yuiayhmk1d08q ... 3.mp4?dl=0