Wednesday, May 14, 2014

3rd party apps within our forms - Detaching


Yesterday, I gave you the ways to place a 3rd party app inside our form.  Today though I thought "What if my users want to work on those excel file outside on its own after I have shown those inside my form?".  And so I decided to find a way to detach those back outside.



This appears to be comparatively easier because we already have the codes to bring those inside our forms.  All we need to do is ensure that we restore all those restrictions we first implemented before detaching it:

With Thisform._oexcel
      .DisplayFormulaBar = .T.
      .DisplayStatusBar = .T.
      .ActiveWindow.DisplayWorkbookTabs=.T.
      .ActiveWindow.DisplayHeadings=.T.

      .ActiveWindow.DisplayWorkbookTabs=.T.
      .ActiveWindow.WindowState = -4137  && xlMaximized
      .Application.ShowWindowsInTaskbar=.T.

      Local loRibbon
      loRibbon =.CommandBars.Item("Ribbon")
      If m.loRibbon.Height > 0
            .ExecuteExcel4Macro('Show.Toolbar("Ribbon",True)')
      Endif

Endwith

So far so good, now since we have a handle on said excel's window which is stored on a form property _nHwnd, we can do something like this:

SetParent(Thisform._nHwnd,_Screen.HWnd)

And great, Excel has been detached.  But the manipulation on Excel's window style is still in place meaning no titlebar and not resizable still.  We therefore should restore those back to its original WindowStyle as well and here are the codes:


Local lnStyle
lnStyle = GetWindowLong(Thisform._nHwnd, -6)
SetWindowLong(Thisform._nHwnd, -6, Bitxor(lnStyle,0x00C00000))

Cool!

However, I realize that while it is no longer latched inside our form, it remains inside VFP's main screen area. It is still a slave of  our VFP app.  That is not what we would have wanted isn't it?  We wanted it to be back outside again into the desktop....... and with that word desktop still ringing in my head, I googled for a WinApi that can do that.  And luck is on our side as within just a few minutes, I stumbled onto the needed WinAPI just for that which is GetDesktopWindow.

So instead of _Screen.HWnd, we should do it like this:

SetParent(Thisform._nHwnd,GetDesktopWindow())

The only remaining thing to do now is to totally relinquish hold onto it via releasing our earlier window handle with these two seedings:

Thisform._nHwnd = .F.
thisform._oexcel = .F.

And that is totally it.  Of course I am assuming you've read my post yesterday on how to put those 3rd party apps inside our forms.  If not, read it and copy the codes and play with it first.  Then add a new button with caption "Detach" and put these codes on its click event:

*** cmdDetach Click Event

* Restore Excel settings
With Thisform._oexcel
      .DisplayFormulaBar = .T.
      .DisplayStatusBar = .T.
      .ActiveWindow.DisplayWorkbookTabs=.T.
      .ActiveWindow.DisplayHeadings=.T.

      .ActiveWindow.DisplayWorkbookTabs=.T.
      .ActiveWindow.WindowState = -4137  && xlMaximized
      .Application.ShowWindowsInTaskbar=.T.

      Local loRibbon
      loRibbon =.CommandBars.Item("Ribbon")
      If m.loRibbon.Height > 0
            .ExecuteExcel4Macro('Show.Toolbar("Ribbon",True)')
      Endif
Endwith

* Restore Window Style
Local lnStyle
* Get the current style of excel window inside our form
lnStyle = GetWindowLong(Thisform._nHwnd, -6)

* Set it back to the default style
SetWindowLong(Thisform._nHwnd, -6, Bitxor(lnStyle,0x00C00000))

* Detach totally from VFP
SetParent(Thisform._nHwnd,GetDesktopWindow())

* Remove latching
Thisform._nHwnd = .F.
thisform._oexcel = .F.

And add this on Form's Load Event:

*** Form's Load Event

Declare Integer GetDesktopWindow In user32


Cheers!




2 comments:

  1. Thanks Mr. JUN,
    Awesome,
    your everyday give us New encouragement & experience !

    ReplyDelete
    Replies
    1. Welcome Zia. Glad to always be of help.

      Delete