TkAero

jdp - As promised on the Windows Aero page, here is the source code (below) and dll (here ) for a Tcl extension which allows Aero Glass [L1 ] to be extended inside a window. It is toolkit-independent, and requires knowledge of the handle of your application window. Then you can use the command below to find the handle of your window (This only works if you have one application window, so call it before you create any more). (MG Is this the same returned by [winfo id $window]?) (jdp No - that command does return a valid window handle, and TkAero will accept it without complaint, but nothing happens. However, since the twapi command is from the Win32 api, I could probably package it with TkAero so that you don't need twapi)

twapi::find_windows -pids [pid] -visible 1 -toplevel 1

Usage is documented in the code below.

jdp 2009-07-15 - Updated. Added a second command, and the twapi command is no longer required. The (renamed) dwm::extendframeintoclientarea command now takes a Tk window path and figures out the HWND itself. The link has been updated, and recompiled in native, rather than .NET, code, and UPX-packed, bringing it down to 4KB. (TkAero.dll )

2011/05/22 Aud -- Sounds neat, but I can't seem to load it. I keep getting this (on Windows 7):

% load TkAero.dll tkaero
couldn't load library "TkAero.dll": invalid argument

/*
 * TkAero.c - The one-and-only code file for TkAero.dll
 * Written by jdp 2009
 * This program is licensed under a Tcl-style BSD license.
 *
 *
 * This will create two commands: dwm::extendframeintoclientarea and dwm::iscompositionenabled
 * the former takes 5 arguments: win, left, right, top, & bottom, in that order.
 * win is the tk window path
 * left, right, top, & bottom are the number of pixels to extend the glass on those sides.
 * Setting them all to -1 will make the whole window glass.
 * Note that ONLY areas that are black will become glassified.
 * Also note that drawing regular widgets onto this glass frame has some (spectacularly) ugly results. Please post if you find a solution.
 * 
 * the latter takes no arguments, and returns a boolean value.
 */

#include <windows.h>
#include <tk.h>
#include <tkPlatDecls.h>

typedef struct _MARGINS {
    int cxLeftWidth;
    int cxRightWidth;
    int cyTopHeight;
    int cyBottomHeight;
} MARGINS, *PMARGINS;

#define CMD_ARGS ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]
#define GET_INT(n, p) if (Tcl_GetIntFromObj(interp, objv[n + 1], &p) != TCL_OK) return TCL_ERROR;
#define CHECK_ARGS(n, m) if (objc != n + 1) {Tcl_WrongNumArgs(interp, 1, objv, m); return TCL_ERROR;}

int ExtendGlass_Cmd(CMD_ARGS)
{
        HWND hwnd;
        HRESULT hr;
        int left, right, top, bottom;
        char *win;
        Tk_Window tk_win;        
        
        /* Make sure we have the correct number of arguments */
        CHECK_ARGS( 5, "win left right top bottom" );
        
        win = Tcl_GetString( objv[1] );
        tk_win = Tk_NameToWindow( interp, win, Tk_MainWindow( interp ) );
        
        /* Make sure this is a toplevel window */
        if ( !Tk_IsTopLevel( tk_win ) ) {
                Tcl_SetObjResult( interp, Tcl_NewStringObj( "win must be toplevel", 21 ) );
                return TCL_ERROR;
        }
        
        hwnd = GetParent( Tk_GetHWND( Tk_WindowId( tk_win ) ) );
        
        /* assemble the MARGINS struct */
        GET_INT(1, left);
        GET_INT(2, right);
        GET_INT(3, top);
        GET_INT(4, bottom);
        
        MARGINS mar = {left, right, top, bottom};
        
        /* actually make the call */
        hr = DwmExtendFrameIntoClientArea(hwnd, &mar);
        
        /* check if it succeeded */
        if ( !SUCCEEDED( hr ) ) {
                Tcl_SetObjResult( interp, Tcl_NewStringObj( "glass extension failed", 23 ) );
                return TCL_ERROR;
        }
        
        return TCL_OK;
}

int IsCmpEnabled_Cmd(CMD_ARGS)
{
        HRESULT hr;
        BOOL result;
        
        CHECK_ARGS( 0, "" );
        
        hr = DwmIsCompositionEnabled( &result );
        
        if ( result ) {
                Tcl_SetObjResult( interp, Tcl_NewBooleanObj( 1 ) );
        } else {
                Tcl_SetObjResult( interp, Tcl_NewBooleanObj( 0 ) );
        }
        
        return TCL_OK;
}

__declspec(dllexport) int Tkaero_Init(Tcl_Interp *interp)
{
        if ( Tcl_InitStubs( interp, "8.1", 0 ) == NULL ) return TCL_ERROR;
                if ( Tk_InitStubs( interp, "8.1", 0 ) == NULL ) return TCL_ERROR;
                
        Tcl_CreateObjCommand( interp, "dwm::extendframeintoclientarea", ExtendGlass_Cmd, NULL, NULL );
                Tcl_CreateObjCommand( interp, "dwm::iscompositionenabled", IsCmpEnabled_Cmd, NULL, NULL );
                
                Tcl_PkgProvide( interp, "tkaero", "0.2" );
                
        return TCL_OK;
}