Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

"Always on top" with Win32 and Tk

by kevin_i_orourke (Friar)
on May 08, 2001 at 19:00 UTC ( #78848=perlquestion: print w/ replies, xml ) Need Help??
kevin_i_orourke has asked for the wisdom of the Perl Monks concerning the following question:

I've written a quick and dirty program to show me various stats on software I'm building (free memory, etc.) using Perl/Tk under Windows. I'd like to have it stay "always on top" of other windows, like quite a few Win32 applications are able to.

The question is: can I do this using Perl/Tk? If I can, how do I do it?

Kev

--
Kevin O'Rourke

Comment on "Always on top" with Win32 and Tk
Replies are listed 'Best First'.
Re: "Always on top" with Win32 and Tk
by ozzy (Sexton) on May 09, 2001 at 04:05 UTC
    With toplevel widgets, i believe you can set the options so the widget will allways be in focus. One of the options for top level widgets is
     -takefocus or -focusmodel.
    To make sure check the Perl/TK documentation. If you are working on Win, you might also want to look into trying Win32::GUI.

    -= Ozzy =-

      Thanks for the suggestion. $window->focusmodel("active") doesn't seem to work (under NT at least). -takefocus is related to tab-key traversal of widgets.

      Looks like another one of those platform-dependent things that Tk hasn't got round to. Win32::GUI is something I'm looking into just now.

      --
      Kevin O'Rourke
      
Re: "Always on top" with Win32 and Tk
by spikey_wan (Scribe) on Dec 22, 2004 at 12:50 UTC
    I can't believe no-one's mentioned Tk::StayOnTop.

    It does what it says on the tin.

Re: "Always on top" with Win32 and Tk
by eserte (Deacon) on Dec 12, 2006 at 23:14 UTC
    Try $mw->attributes(-topmost => 1). This should work for Windows, and soon on freedesktop-compliant X11 window managers.
Re: "Always on top" with Win32 and Tk
by elwarren (Curate) on May 09, 2001 at 23:28 UTC
    There are third party programs you can run that can alter properties of existing windows to force them on top. Nice to keep a copy of notepad or something open on top of everything else. One that I used would allow you to shell out and execute it and it would update the window of the program it was called from.

    While not a perl solution, it's close...

        I've got it working now! As before I've removed most of the code from my program.

        use Tk; use Win32::API; ... # Windows constants my ($OnTop, $NoTop, $Top) = (-1, -2, 0); my ($SWP_NOMOVE, $SWP_NOSIZE) = (2, 1); # 'always on top' state my $isOnTop = $NoTop; ... # Create a Win32::API object for SetWindowPos my $SetWindowPos = new Win32::API("user32", "SetWindowPos", [N,N,N,N,N +,N,N], N); # and one for FindWindow my $FindWindow = new Win32::API("user32", "FindWindow", [P,P], N); ... my $w = new MainWindow; ... my $aotCBut = $w->Checkbutton(-text => "Always on top", -onvalue => $OnTop, -offvalue => $NoTop, -variable => \$isOnTop, -command => sub { # get a handle to the toplevel window containing our Perl/Tk a +pp my $class = "TkTopLevel"; my $name = $w->title; my $NULL = 0; my $topHwnd = $FindWindow->Call($class, $name); if ($topHwnd != $NULL) { # change 'always on top' state $SetWindowPos->Call($topHwnd, $isOnTop, 0, 0, 0, 0, $SWP_N +OMOVE | $SWP_NOSIZE); }; }) ->pack(-side => "bottom", expand => "yes", -fill => "x"); ... # start the UI MainLoop;

        The Win32 FindWindow API call will return a handle to a window with the specified title and class. Perl/Tk creates windows of the class TkTopLevel. You must call this after the window has been mapped (i.e. after MainLoop), otherwise you won't get a valid window handle.

        A useful reference when using Win32::API is here, it talks about Visual Basic but you can fairly easily convert it to Perl.

        --
        Kevin O'Rourke
        

        I tried the VB code, converted to Perl and using Win32::API. (the code isn't the tidiest in the world, I've missed out most of the program):

        ... use Tk; use Win32::API; # Windows constants my ($OnTop, $NoTop, $Top) = (-1, -2, 0); my ($SWP_NOMOVE, $SWP_NOSIZE) = (2, 1); ... # Create a Win32::API object for SetWindowPos my $SetWindowPos = new Win32::API("user32", "SetWindowPos", [N,N,N,N,N +,N,N], N); ... my $w = new MainWindow; ... # do the 'always on top' bit my $hwnd = $w->frame; # frame returns a hex value as a string, e.g. "0 +x1234" print "$hwnd\n"; $SetWindowPos->Call(hex($hwnd), $OnTop, 0, 0, 0, 0, $SWP_NOMOVE | $SWP +_NOSIZE); MainLoop;

        Unfortunately $w->frame returns the Tk MainWindow, not the Win32 window containing it. As a result setting $w->frame 'always on top' doesn't have any effect.

        Anyone know how to get an HWND for a window's parent out of Win32? Tk::Wm's $w->wrapper doesn't work either.

        --
        Kevin O'Rourke
        

        Thanks, I've had a look at the VB. I assume if I can extract an HWND from Tk I could use this. It's a bit nasty but looks like the only way.

        From my reading of Tk::Wm documentation I should be able to get the HWND using $w->frame. Time for a play with Win32::API

        --
        Kevin O'Rourke
        

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://78848]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (10)
As of 2015-07-31 04:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (274 votes), past polls