Page 1 of 2

scalefactor and autoresize gives an error

Posted: Tue Apr 21, 2015 7:02 am
by skiman
Hi Roger,

I'm still working on the scalefactor and autoresize functionality. I had this implemented as test in my application, and I'm getting an error when resizing my main windows, when a cbrowse is open in another thread. It looks as with the resize, the open databases are closed?

I succeeded to simulate the same error with a modification of xsample5.prg and the sample_146. As soon as you try to run the sample_146, you get the same error as I get in my application.

Modifications I made:
- Open sample 146 in another thread.
- Open it in the drawingarea of the main window

Hereby the modified file, so you can test it.

Re: scalefactor and autoresize gives an error

Posted: Tue Apr 21, 2015 7:31 am
by Tom
Hi, Chris.

I didn't look at the code, but: If you have a browse showing a database, you may be able to resize this from another thread. But since the workareas are threadlocal, refreshing the browse can't work. The thread which refreshes the browse - if so - doesn't see the database. Evaluating the datalinks of the columns must create runtime errors.

Re: scalefactor and autoresize gives an error

Posted: Tue Apr 21, 2015 8:06 am
by skiman
Hi Tom,

This sounds very logical, but this means that autoresize can't be used when there are different windows in different threads?

It's not a problem for me, I don't need the autoresize. The scalefactor looks as a nice to have. I implemented it as you did, and it seems to work. I'm calculating the factor of the height and the width, and take the MIN of both to scale.

Re: scalefactor and autoresize gives an error

Posted: Tue Apr 21, 2015 8:40 am
by skiman
Hi Roger,

I just tested without the autoresize, and the error went away.

As Tom wrote, it isn't possible to refresh the browse in another thread. No need to spend time in this.

Re: scalefactor and autoresize gives an error

Posted: Tue Apr 21, 2015 11:19 am
by rdonnay
As Tom wrote, it isn't possible to refresh the browse in another thread. No need to spend time in this.
Actually, this isn't true.
I have helped with applications where this is a necessity and it is not hard to do.

It's done by sending a message to the other thread through PostAppEvent().
You need a pointer to the XbpDialog() object of the receiving thread so it has a mechanism for receiving events.

Example:

Code: Select all

Dialog 1

DCUSEREVENT xbeP_User+100 EVAL {||oBrowse:refreshAll()}

Dialog 2

PostAppEvent( xbeP_User+100,,,oDialog1 )
Here is the white paper I wrote for my session on Multi-Threading.
After I did this session, I realized that it wasn't only for Newbies.
The room was filled with Xbase++ programmers who have been using multi-threading for years but were not aware of some of it's capabilities. I will be doing this session again at my spring devcon and again in The Netherlands later this year.

http://donnay-software.com/ds/Articles/ ... ewbies.Pdf

Re: scalefactor and autoresize gives an error

Posted: Wed Apr 22, 2015 3:13 am
by skiman
Hi Roger,

I've read your document, but there is not so much about multi-threading.

I checked the \samples\events and I understand the principle. This could be usefull in some cases.

However, this seems not easy to implement this in the 'autoresize' system. If you resize your main window, it should check all the child windows, and send events to these childs. Looks rather complicated to me? Anyway, no need to implement this for me.

Re: scalefactor and autoresize gives an error

Posted: Wed Apr 22, 2015 4:31 am
by rdonnay
However, this seems not easy to implement this in the 'autoresize' system. If you resize your main window, it should check all the child windows, and send events to these childs. Looks rather complicated to me? Anyway, no need to implement this for me.
I will work on a sample program for you.

Re: scalefactor and autoresize gives an error

Posted: Wed Apr 22, 2015 6:09 am
by rdonnay
Here is a sample that works good for me.

Code: Select all

#include "dcdialog.ch"
#INCLUDE "appevent.CH"

#DEFINE RESIZE_EVENT  xbeP_User+100

FUNCTION Main()

LOCAL GetList[0], GetOptions, oMenuBar, oSubMenu, oMainWindow

DCMENUBAR oMenuBar

  DCSUBMENU oSubMenu PROMPT 'Window' PARENT oMenuBar

    DCMENUITEM 'Open Child Window' PARENT oSubMenu ;
      ACTION {|o|o := Thread():new(), Sleep(5), o:start({||OpenWindow(oMainWindow:drawingArea)})}

DCGETOPTIONS WINDOWHEIGHT 600 WINDOWWIDTH 800

DCREAD GUI TITLE 'Auto-Resize Test' PARENT @oMainWindow OPTIONS Getoptions ;
   EVAL {|o|InitResize(o,GetList)}

RETURN nil

* ---------

STATIC FUNCTION InitResize( oDlg, aGetList )

oDlg:resize := {|a,b,o,x|oDlg:lockUpdate(.t.), ;
                         DC_ReSize(a,b,o,aGetList), ;
                         ResizeChildren(a,b,o), ;
                         oDlg:lockUpdate(.f.), ;
                         o:invalidateRect()}
RETURN nil

* ---------

STATIC FUNCTION ResizeChildren( aOldSize, aNewSize, oDlg )

LOCAL aChildList := oDlg:drawingArea:childList(), oChildWindow, i, aChildSize

FOR i := 1 TO Len(aChildList)
  oChildWindow := aChildList[i]
  aChildSize := oChildWindow:currentSize()
  aChildSize[1] := aChildSize[1] + aNewSize[1] - aOldSize[1]
  aChildSize[2] := aChildSize[2] + aNewSize[2] - aOldSize[2]
  PostAppEvent( RESIZE_EVENT, aChildSize,, oChildWindow )
  Sleep(1)
NEXT
Sleep(1)

RETURN nil

* ---------

FUNCTION OpenWindow( oAppWindow )

LOCAL GetList[0], GetOptions, i

DCUSEREVENT RESIZE_EVENT ACTION {|mp1,mp2,oDlg,a|oDlg:setSize(mp1)}

FOR i := 1 TO 10
  @ i, 0 DCSAY 'This is line ' + Alltrim(Str(i)) FONT '10.Arial' SAYSIZE 30
NEXT

DCGETOPTIONS RESIZE RESIZEDEFAULT DCGUI_RESIZE_AUTORESIZE_SCALEFONT

DCREAD GUI FIT TITLE 'Auto-Resize Test Child Window' APPWINDOW oAppWindow ;
   OPTIONS GetOptions

RETURN nil

* ---------

PROC appsys ; RETURN

Re: scalefactor and autoresize gives an error

Posted: Wed Apr 22, 2015 7:38 am
by skiman
Hi Roger,

This is a nice sample of sending events.

I will check how to use it. Thanks.

Re: scalefactor and autoresize gives an error

Posted: Wed Apr 22, 2015 7:55 am
by rdonnay
This is a nice sample of sending events.
I think so too. I'm going to add this to my multi-threading session.