Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Combining+GUI+applications+developed+with+Tk+and+%27native%27+Windows+toolkits?V=50
QUERY_STRINGV=50
CONTENT_TYPE
DOCUMENT_URI/revision/Combining+GUI+applications+developed+with+Tk+and+'native'+Windows+toolkits
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.69.6.71
REMOTE_PORT32186
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR18.116.239.195
HTTP_CF_RAY87c54b91ab8b618a-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP18.116.239.195
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {Combining GUI applications developed with Tk and 'native' Windows toolkits} {Three senses:
   * Tk within frame of other application (written in, for example, Visual C++).  So far, only works--barely--with IE.
   * [Embedding Windows applications in Tk frames]
   * Tk application that also invokes, say, MFC widgets.  This might involve, in particular, [Using MFC Controls as Tk widgets].

[Jeffrey Hobbs] and [David Gravereaux] know the most about these.  
None of them (except for MFC controls as widgets) really work as of January 2002 
without a lot of fiddling ...

[Arjen Markus] There may be a connection with [Drawing Into Foreign Windows].

[Frame] and [toplevel] bear on this topic.  If an external X11 application has a command-line option to configure its placement (as, for example, xanim's +Wid), then mumble-mumble used with the -container of toplevel and frame.  "man [winfo]" gives information on X11-id-s.  
Credit [Andreas Leitgeb] with this observation.

[Theo Verelst] There ''is'' at least a connection with [tclhttpd] ..

James Wettenhall <[email protected]> has experimented with embedding Tk windows within GraphApp 
(a GUI toolkit in the C language which uses 'native' Microsoft Windows widgets):
http://bioinf.wehi.edu.au/folders/james/tkEmbed/

-----------------------------------------------------
placing the Tk widgets in IE has been simplified by using the TclControl activeX. 
Using the IE version 6.0, I have found it to be the most stable...

TclControl can be found at:
http://www.sys.uea.ac.uk/~fuzz/optcl/default.html

I have made little to no changes to many Tcl/Tk apps that can run within the IE window... 
Yes you still need to have a copy of Tcl/Tk installed (but so does java requires a VM to be resident)...
Of coarse you need to worry about security issues by allowing the activeX to access Tcl...

James Garrison <[email protected]>


[[Explain tangential connections of [TclScript] and [GPS] work.]]

----

The point of TclScript is to plug in the Tcl '''language''' as an IE extension. 
This would mean that IE would be able to parse pages with the following type of script code:

   <script language="TclScript">
      package require base64
      proc encode_text {str} {
          return [base64::encode $str]
      }
      proc show_dialog {message} {
          toplevel .dlg
          ....
      }
   </script>
   <form ....>

This isn't quite the same as the ActiveX component which has more to do with placing a Tk toplevel widget onto the browser window and processing Tcl script within itself. 

Of course at present (Jan 2002) TclScript remains vapour-ware (or maybe liquid-ware as there is code, it's just not useable :) ) but I hope to find the time to continue at some point this year. [PT]
----
[NEM] '''19May2003''' - Here's a quick example of embedding an application into a Tk widget using [BLT]'s container and bgexec commands. The application being embedded in this case is Vim running in an Eterm under Linux. I tried quickly to get this working with xterm, but I couldn't, whereas Eterm played nicely.

 package require Tk
 package require BLT

 # Create a unique name for the new process
 set name "EmbedTk[pid][clock seconds]"
 eval blt::bgexec wait [list Eterm -n $name -e vi] $argv
 pack [blt::container .c -name $name] -fill both
 wm title . "Vim running in Tk"
 # Wait for app to exit (could use trace + callback here)
 vwait wait
 destroy .

This allows you to embed the program based on its name. The reason for using bgexec is that we need a method of detecting when the application has finished (yet it needs to run in the background), so that we can destroy the widget or do whatever. BTW, to use with xterm you have to change the "-n" switch to "-name". However, for some reason, this still didn't work. Note that resizing the widget won't resize the embedded window, so don't pack with -expand 1.
----

[DG] -- Here is a C++ example for how to use external windows as containers. Use [[[toplevel] <newPath> -use <window id>]] to attach to it.  Notice the four special windows messages used for the "container protocol".

======C
 #include <windows.h>

 HINSTANCE hInstance;

 class MainWnd {
 public:
    MainWnd(int nCmdShow);
    ~MainWnd();
    HWND GetWindowId();
 private:
    friend LRESULT CALLBACK MainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

    static bool first;
    int UserSizeChanging;
    HWND hMain;
    HWND hAttach;
 };


 MainWnd::MainWnd (int nCmdShow)
    : hAttach(NULL), UserSizeChanging(0)
 {
    // do first time inits ?
    //
    if (first)
    {
        WNDCLASSEX wndcls;

        first = false;

        // register our StatBox window class
        //
        wndcls.cbSize = sizeof (WNDCLASSEX);
        wndcls.style = 0;
        wndcls.cbClsExtra = 0;
        wndcls.cbWndExtra = sizeof (HANDLE);
        wndcls.hInstance = hInstance;
        wndcls.hCursor = ::LoadCursor (NULL, IDC_ARROW);
        wndcls.lpszMenuName = NULL;
        wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
        wndcls.hIcon = ::LoadIcon (NULL, IDI_APPLICATION);
        wndcls.hIconSm = ::LoadIcon (NULL, IDI_APPLICATION);
        wndcls.lpfnWndProc = MainWndProc;
        wndcls.lpszClassName = "TkFriendly";

        ::RegisterClassEx (&wndcls);
    }

    hMain = ::CreateWindowEx (
            WS_EX_LEFT,
            "TkFriendly",
            "Tk container protocol example.",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            0L, 0L, hInstance, this
            );

    ::ShowWindow(hMain, nCmdShow);
    ::UpdateWindow(hMain);
 }

 MainWnd::~MainWnd () {
    if (hMain) ::SendMessage(hMain, WM_CLOSE, 0, 0);
 }

 HWND MainWnd::GetWindowId() {
    return hMain;
 }

 bool MainWnd::first = true;


 LRESULT CALLBACK
 MainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
    MainWnd *pMain = reinterpret_cast <MainWnd *>
            (::GetWindowLongPtr(hwnd, GWLP_USERDATA));

    switch (iMsg)
    {
        case WM_CREATE:
            // Supposedly, lpCreateParams has a DWORD alignment problem.
            // I don't know what this means for pointers.  I doubt much.
            //
            pMain = reinterpret_cast <MainWnd *>(((LPCREATESTRUCT)lParam)->lpCreateParams);

            // move the MainWnd class pointer into the
            // userdata of the window.
            //
            ::SetWindowLongPtr (hwnd, GWLP_USERDATA, reinterpret_cast <LONG_PTR>(pMain));
            return 0;

        case WM_CLOSE:
            ::DestroyWindow(hwnd);
            return 0;

        case WM_DESTROY:
            pMain->hMain = NULL;
            delete pMain;
            ::PostQuitMessage(0);
            return 0;

 // ---------  Begin Tk container specials ----------

 #define TK_CLAIMFOCUS     (WM_USER)
 #define TK_GEOMETRYREQ    (WM_USER+1)
 #define TK_ATTACHWINDOW   (WM_USER+2)
 #define TK_DETACHWINDOW   (WM_USER+3)

        case TK_CLAIMFOCUS:
            if (wParam || (GetFocus() != NULL)) {
                ::SetFocus(pMain->hAttach);
            }
            return 0;

        case TK_GEOMETRYREQ:
            if (!pMain->UserSizeChanging) {

                // Make the client area to be the size given, but
                // we move the whole window.  Calc the additions
                // to get us there.

                wParam += 2 * GetSystemMetrics(SM_CXEDGE) + 3;
                lParam += GetSystemMetrics(SM_CYCAPTION) +
                        (2 * GetSystemMetrics(SM_CYEDGE) + 3);
                ::SetWindowPos(hwnd, NULL, 0, 0, wParam, lParam,
                        SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
            }
            return 0;

        case TK_ATTACHWINDOW:
            pMain->hAttach = (HWND)wParam;
            ::SetParent(pMain->hAttach, hwnd);
            return 0;

        // We have found that as written, the return value of 0
        // prevents the generation of the TK_GEOMETRYREQ message in 
        // UpdateWrapper(TkWindow*) - see tk8.5.6/win/tkWinWm.c, 
        // lines 2299-2306.  When we returned a value of 1, the 
        // remainder of this code behaved as we expected.
        // -- AJS

        case TK_DETACHWINDOW:
            pMain->hAttach = NULL;
            ::PostMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;

 // ---------  End Tk container specials ----------

        case WM_ENTERSIZEMOVE:
            pMain->UserSizeChanging = 1;
            break;

        case WM_EXITSIZEMOVE:
            pMain->UserSizeChanging = 0;
            break;

        case WM_SIZE:
            if (wParam != SIZE_MINIMIZED && pMain->hAttach) {
                ::SetWindowPos(pMain->hAttach, NULL, 0, 0,
                        LOWORD(lParam), HIWORD(lParam),
                        SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
            }
            return 0;

        case WM_PARENTNOTIFY:
            switch (LOWORD(wParam)) {
                case WM_LBUTTONDOWN:
                case WM_MBUTTONDOWN:
                case WM_RBUTTONDOWN:
                    ::SetFocus(pMain->hAttach);
                    return 0;

                case WM_DESTROY:
                    ::PostQuitMessage(0);
                    return 0;
            }
            break;

        case WM_ERASEBKGND:
            if (pMain->UserSizeChanging) return 1;
            break;
    }

    return ::DefWindowProc(hwnd, iMsg, wParam, lParam);
 }


 int WINAPI
 WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
 {
    MSG msg;
    MainWnd *main;
    char buf[50];

    main = new MainWnd(nCmdShow);
    wsprintf(buf, "%ld", main->GetWindowId());
    MessageBox(main->GetWindowId(), buf, "Window ID is:", MB_OK);

    while (::GetMessage(&msg, NULL, 0, 0)) {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return msg.wParam;
 }
======

There's a problem when this technique is used in-process regarding resizing.  
No solution is known at this time.  See what it looks like in my IRC client.  
[[IRC::makeblank]] creates a new MDI child and returns the HWND of it using code nearly identical to the above.

[http://tomasoft.sourceforge.net/x2_tkembed.gif]

<<categories>> GUI | Design | Windows} regexp2} CALL {my render {Combining GUI applications developed with Tk and 'native' Windows toolkits} {Three senses:
   * Tk within frame of other application (written in, for example, Visual C++).  So far, only works--barely--with IE.
   * [Embedding Windows applications in Tk frames]
   * Tk application that also invokes, say, MFC widgets.  This might involve, in particular, [Using MFC Controls as Tk widgets].

[Jeffrey Hobbs] and [David Gravereaux] know the most about these.  
None of them (except for MFC controls as widgets) really work as of January 2002 
without a lot of fiddling ...

[Arjen Markus] There may be a connection with [Drawing Into Foreign Windows].

[Frame] and [toplevel] bear on this topic.  If an external X11 application has a command-line option to configure its placement (as, for example, xanim's +Wid), then mumble-mumble used with the -container of toplevel and frame.  "man [winfo]" gives information on X11-id-s.  
Credit [Andreas Leitgeb] with this observation.

[Theo Verelst] There ''is'' at least a connection with [tclhttpd] ..

James Wettenhall <[email protected]> has experimented with embedding Tk windows within GraphApp 
(a GUI toolkit in the C language which uses 'native' Microsoft Windows widgets):
http://bioinf.wehi.edu.au/folders/james/tkEmbed/

-----------------------------------------------------
placing the Tk widgets in IE has been simplified by using the TclControl activeX. 
Using the IE version 6.0, I have found it to be the most stable...

TclControl can be found at:
http://www.sys.uea.ac.uk/~fuzz/optcl/default.html

I have made little to no changes to many Tcl/Tk apps that can run within the IE window... 
Yes you still need to have a copy of Tcl/Tk installed (but so does java requires a VM to be resident)...
Of coarse you need to worry about security issues by allowing the activeX to access Tcl...

James Garrison <[email protected]>


[[Explain tangential connections of [TclScript] and [GPS] work.]]

----

The point of TclScript is to plug in the Tcl '''language''' as an IE extension. 
This would mean that IE would be able to parse pages with the following type of script code:

   <script language="TclScript">
      package require base64
      proc encode_text {str} {
          return [base64::encode $str]
      }
      proc show_dialog {message} {
          toplevel .dlg
          ....
      }
   </script>
   <form ....>

This isn't quite the same as the ActiveX component which has more to do with placing a Tk toplevel widget onto the browser window and processing Tcl script within itself. 

Of course at present (Jan 2002) TclScript remains vapour-ware (or maybe liquid-ware as there is code, it's just not useable :) ) but I hope to find the time to continue at some point this year. [PT]
----
[NEM] '''19May2003''' - Here's a quick example of embedding an application into a Tk widget using [BLT]'s container and bgexec commands. The application being embedded in this case is Vim running in an Eterm under Linux. I tried quickly to get this working with xterm, but I couldn't, whereas Eterm played nicely.

 package require Tk
 package require BLT

 # Create a unique name for the new process
 set name "EmbedTk[pid][clock seconds]"
 eval blt::bgexec wait [list Eterm -n $name -e vi] $argv
 pack [blt::container .c -name $name] -fill both
 wm title . "Vim running in Tk"
 # Wait for app to exit (could use trace + callback here)
 vwait wait
 destroy .

This allows you to embed the program based on its name. The reason for using bgexec is that we need a method of detecting when the application has finished (yet it needs to run in the background), so that we can destroy the widget or do whatever. BTW, to use with xterm you have to change the "-n" switch to "-name". However, for some reason, this still didn't work. Note that resizing the widget won't resize the embedded window, so don't pack with -expand 1.
----

[DG] -- Here is a C++ example for how to use external windows as containers. Use [[[toplevel] <newPath> -use <window id>]] to attach to it.  Notice the four special windows messages used for the "container protocol".

======C
 #include <windows.h>

 HINSTANCE hInstance;

 class MainWnd {
 public:
    MainWnd(int nCmdShow);
    ~MainWnd();
    HWND GetWindowId();
 private:
    friend LRESULT CALLBACK MainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

    static bool first;
    int UserSizeChanging;
    HWND hMain;
    HWND hAttach;
 };


 MainWnd::MainWnd (int nCmdShow)
    : hAttach(NULL), UserSizeChanging(0)
 {
    // do first time inits ?
    //
    if (first)
    {
        WNDCLASSEX wndcls;

        first = false;

        // register our StatBox window class
        //
        wndcls.cbSize = sizeof (WNDCLASSEX);
        wndcls.style = 0;
        wndcls.cbClsExtra = 0;
        wndcls.cbWndExtra = sizeof (HANDLE);
        wndcls.hInstance = hInstance;
        wndcls.hCursor = ::LoadCursor (NULL, IDC_ARROW);
        wndcls.lpszMenuName = NULL;
        wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
        wndcls.hIcon = ::LoadIcon (NULL, IDI_APPLICATION);
        wndcls.hIconSm = ::LoadIcon (NULL, IDI_APPLICATION);
        wndcls.lpfnWndProc = MainWndProc;
        wndcls.lpszClassName = "TkFriendly";

        ::RegisterClassEx (&wndcls);
    }

    hMain = ::CreateWindowEx (
            WS_EX_LEFT,
            "TkFriendly",
            "Tk container protocol example.",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            0L, 0L, hInstance, this
            );

    ::ShowWindow(hMain, nCmdShow);
    ::UpdateWindow(hMain);
 }

 MainWnd::~MainWnd () {
    if (hMain) ::SendMessage(hMain, WM_CLOSE, 0, 0);
 }

 HWND MainWnd::GetWindowId() {
    return hMain;
 }

 bool MainWnd::first = true;


 LRESULT CALLBACK
 MainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
    MainWnd *pMain = reinterpret_cast <MainWnd *>
            (::GetWindowLongPtr(hwnd, GWLP_USERDATA));

    switch (iMsg)
    {
        case WM_CREATE:
            // Supposedly, lpCreateParams has a DWORD alignment problem.
            // I don't know what this means for pointers.  I doubt much.
            //
            pMain = reinterpret_cast <MainWnd *>(((LPCREATESTRUCT)lParam)->lpCreateParams);

            // move the MainWnd class pointer into the
            // userdata of the window.
            //
            ::SetWindowLongPtr (hwnd, GWLP_USERDATA, reinterpret_cast <LONG_PTR>(pMain));
            return 0;

        case WM_CLOSE:
            ::DestroyWindow(hwnd);
            return 0;

        case WM_DESTROY:
            pMain->hMain = NULL;
            delete pMain;
            ::PostQuitMessage(0);
            return 0;

 // ---------  Begin Tk container specials ----------

 #define TK_CLAIMFOCUS     (WM_USER)
 #define TK_GEOMETRYREQ    (WM_USER+1)
 #define TK_ATTACHWINDOW   (WM_USER+2)
 #define TK_DETACHWINDOW   (WM_USER+3)

        case TK_CLAIMFOCUS:
            if (wParam || (GetFocus() != NULL)) {
                ::SetFocus(pMain->hAttach);
            }
            return 0;

        case TK_GEOMETRYREQ:
            if (!pMain->UserSizeChanging) {

                // Make the client area to be the size given, but
                // we move the whole window.  Calc the additions
                // to get us there.

                wParam += 2 * GetSystemMetrics(SM_CXEDGE) + 3;
                lParam += GetSystemMetrics(SM_CYCAPTION) +
                        (2 * GetSystemMetrics(SM_CYEDGE) + 3);
                ::SetWindowPos(hwnd, NULL, 0, 0, wParam, lParam,
                        SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
            }
            return 0;

        case TK_ATTACHWINDOW:
            pMain->hAttach = (HWND)wParam;
            ::SetParent(pMain->hAttach, hwnd);
            return 0;

        // We have found that as written, the return value of 0
        // prevents the generation of the TK_GEOMETRYREQ message in 
        // UpdateWrapper(TkWindow*) - see tk8.5.6/win/tkWinWm.c, 
        // lines 2299-2306.  When we returned a value of 1, the 
        // remainder of this code behaved as we expected.
        // -- AJS

        case TK_DETACHWINDOW:
            pMain->hAttach = NULL;
            ::PostMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;

 // ---------  End Tk container specials ----------

        case WM_ENTERSIZEMOVE:
            pMain->UserSizeChanging = 1;
            break;

        case WM_EXITSIZEMOVE:
            pMain->UserSizeChanging = 0;
            break;

        case WM_SIZE:
            if (wParam != SIZE_MINIMIZED && pMain->hAttach) {
                ::SetWindowPos(pMain->hAttach, NULL, 0, 0,
                        LOWORD(lParam), HIWORD(lParam),
                        SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
            }
            return 0;

        case WM_PARENTNOTIFY:
            switch (LOWORD(wParam)) {
                case WM_LBUTTONDOWN:
                case WM_MBUTTONDOWN:
                case WM_RBUTTONDOWN:
                    ::SetFocus(pMain->hAttach);
                    return 0;

                case WM_DESTROY:
                    ::PostQuitMessage(0);
                    return 0;
            }
            break;

        case WM_ERASEBKGND:
            if (pMain->UserSizeChanging) return 1;
            break;
    }

    return ::DefWindowProc(hwnd, iMsg, wParam, lParam);
 }


 int WINAPI
 WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
 {
    MSG msg;
    MainWnd *main;
    char buf[50];

    main = new MainWnd(nCmdShow);
    wsprintf(buf, "%ld", main->GetWindowId());
    MessageBox(main->GetWindowId(), buf, "Window ID is:", MB_OK);

    while (::GetMessage(&msg, NULL, 0, 0)) {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return msg.wParam;
 }
======

There's a problem when this technique is used in-process regarding resizing.  
No solution is known at this time.  See what it looks like in my IRC client.  
[[IRC::makeblank]] creates a new MDI child and returns the HWND of it using code nearly identical to the above.

[http://tomasoft.sourceforge.net/x2_tkembed.gif]

<<categories>> GUI | Design | Windows}} CALL {my revision {Combining GUI applications developed with Tk and 'native' Windows toolkits}} CALL {::oo::Obj3377217 process revision/Combining+GUI+applications+developed+with+Tk+and+%27native%27+Windows+toolkits} CALL {::oo::Obj3377215 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4