Window management

Revision as of 12:57, 10 October 2017 by Aamrun (talk | contribs) (Added C implementation for Windows.)

Treat windows or at least window identities as first class objects.

  • Store window identities in variables, compare them for equality.
  • Provide examples of performing some of the following:
    • hide, show, close, minimize, maximize, move, and resize a window.
Task
Window management
You are encouraged to solve this task according to the task description, using any language you may know.

The window of interest may or may not have been created by your program.

AutoHotkey

<lang AutoHotkey>F1::  ;; when user hits the F1 key, do the following WinGetTitle, window, A  ; get identity of active window into a variable WinMove, %window%, , 100, 100, 800, 800 ; move window to coordinates, 100, 100

                                       ; and change size to 800 x 800 pixels

sleep, 2000 WinHide, % window  ; hide window TrayTip, hidden, window is hidden, 2 sleep, 2000 WinShow, % window  ; show window again loop, {

 inputbox, name, what was the name of your window? 
 if (name = window) ; compare window variables for equality
 {
   msgbox you got it
   break
 }
else try again

} WinClose, % window return</lang>

BBC BASIC

<lang bbcbasic> SWP_NOMOVE = 2

     SWP_NOZORDER = 4
     SW_MAXIMIZE = 3
     SW_MINIMIZE = 6
     SW_RESTORE = 9
     SW_HIDE = 0
     SW_SHOW = 5
     
     REM Store window handle in a variable:
     myWindowHandle% = @hwnd%
     
     PRINT "Hiding the window in two seconds..."
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_HIDE
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_SHOW
     PRINT "Windows shown again."
     
     PRINT "Minimizing the window in two seconds..."
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_MINIMIZE
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_RESTORE
     PRINT "Maximizing the window in two seconds..."
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_MAXIMIZE
     WAIT 200
     SYS "ShowWindow", myWindowHandle%, SW_RESTORE
     PRINT "Now restored to its normal size."
     
     PRINT "Resizing the window in two seconds..."
     WAIT 200
     SYS "SetWindowPos", myWindowHandle%, 0, 0, 0, 400, 200, \
     \    SWP_NOMOVE OR SWP_NOZORDER
     
     PRINT "Closing the window in two seconds..."
     WAIT 200
     QUIT</lang>

== MB_ICONINFORMATION

 in
    {Window show}
    Window
 end
 %% Adds two methods to a toplevel instance.
 %% For maximize and restore we have to interact directly with Tk
 %% because that functionality is not part of the QTk library.
 fun {Extend Toplevel}
    proc {$ A}
       case A of maximize then
          {Tk.send wm(state Toplevel zoomed)}
       [] restore then
          {Tk.send wm(state Toplevel normal)}
       else
          {Toplevel A}
       end
    end
 end
 %% Returns the current entry of a listbox
 %% as an Oz value.
 fun {GetSelected LB}
    Entries = {LB get($)}
    Index = {LB get(firstselection:$)}
 in
    {Compiler.virtualStringToValue {Nth Entries Index}}
 end
 fun {ValueToString V}
    {Value.toVirtualString V 100 100}
 end

in

 {Record.forAll Windows CreateWindow}</lang>

Perl

Library: Perl/Tk

This is a translation of the Tcl solution for this task.

The preferred way of using Tk with perl is through the (relatively modern) Tkx module, not the (quite old) Tk module (also known as perl/tk), which my code uses.

I wrote the code using the Tk module, as that's what I had on my computer, and I was too lazy to install Tkx. Translating from perl/tk to Tkx should be fairly trivial.

<lang Perl>#!perl use strict; use warnings; use Tk;

my $mw; my $win; my $lab;

  1. How to open a window.

sub openWin { if( $win ) { $win->deiconify; $win->wm('state', 'normal'); } else { eval { $win->destroy } if $win; $win = $mw->Toplevel; $win->Label(-text => "This is the window being manipulated") ->pack(-fill => 'both', -expand => 1); $lab->configure(-text => "The window object is:\n$win"); } }

  1. How to close a window

sub closeWin { return unless $win; $win->destroy; $lab->configure(-text => ); undef $win; }

  1. How to minimize a window

sub minimizeWin { return unless $win; $win->iconify; }

  1. How to maximize a window

sub maximizeWin { return unless $win; $win->wm('state', 'zoomed'); eval { $win->wmAttribute(-zoomed => 1) }; # Hack for X11 }

  1. How to move a window

sub moveWin { return unless $win; my ($x, $y) = $win->geometry() =~ /\+(\d+)\+(\d+)\z/ or die; $_ += 10 for $x, $y; $win->geometry("+$x+$y"); }

  1. How to resize a window

sub resizeWin { return unless $win; my ($w, $h) = $win->geometry() =~ /^(\d+)x(\d+)/ or die; $_ += 10 for $w, $h; $win->geometry($w . "x" . $h); }

$mw = MainWindow->new; for my $label0 ($mw->Label(-text => 'Window handle:')) { $lab = $mw->Label(-text => ); $label0->grid($lab); }

my @binit = ('Open/Restore' => \&openWin, Close => \&closeWin, Minimize => \&minimizeWin, Maximize => \&maximizeWin, Move => \&moveWin, Resize => \&resizeWin);

while( my ($text, $callback) = splice @binit, 0, 2 ) { $mw->Button(-text => $text, -command => $callback)->grid('-'); }

MainLoop();

__END__ </lang>

In the Tcl code I translated from, the second label of the main window had a textvariable attribute. For some reason, this didn't work correctly for me, either due to a bug in Tk.pm, or some other reason. Because of that, I kept around a handle to that second label ($lab), and called configure on it when I needed it's text to change.

Doubtless some more modern Tk binding (such as Tkx, or perhaps Tcl::Tk) would handle that better.

Phix

Translation of: Nim
Library: pGUI

<lang Phix>-- -- demo\rosetta\Window_management.exw -- include pGUI.e

Ihandle dlg

function doFull(Ihandle /*ih*/)

   IupSetAttribute(dlg,"FULLSCREEN","YES")
   return IUP_DEFAULT

end function

function doMax(Ihandle /*ih*/)

   IupSetAttribute(dlg,"PLACEMENT","MAXIMIZED")
   -- this is a work-around to get the dialog minimised (on win platform)
   IupSetAttribute(dlg,"VISIBLE","YES")
   return IUP_DEFAULT

end function

function doMin(Ihandle /*ih*/)

   IupSetAttribute(dlg,"PLACEMENT","MINIMIZED")
   -- this is a work-around to get the dialog minimised (on win platform)
   IupSetAttribute(dlg,"VISIBLE","YES")
   return IUP_DEFAULT

end function

function doRestore(Ihandle /*ih*/)

   IupSetAttribute(dlg,"OPACITY","255")
   IupSetAttribute(dlg,"FULLSCREEN","NO")
   IupSetAttribute(dlg,"PLACEMENT","NORMAL")
   IupSetAttribute(dlg,"VISIBLE","YES")
   return IUP_DEFAULT

end function

function doDim(Ihandle /*ih*/)

   IupSetAttribute(dlg,"OPACITY","60")
   return IUP_DEFAULT

end function

function doShow(Ihandle /*ih*/)

   IupSetAttribute(dlg,"OPACITY","255")
   return IUP_DEFAULT

end function

function doMove(Ihandle /*ih*/)

   integer {x,y} = IupGetIntInt(dlg,"SCREENPOSITION")
   integer shift = iff(IupGetInt(NULL,"SHIFTKEY")?-10,+10)
   IupShowXY(dlg,x+shift,y+shift)
   return IUP_DEFAULT

end function

procedure main()

   IupOpen()

   Ihandle hbox = IupHbox({IupButton("restore",    Icallback("doRestore")),
                           IupButton("full screen",Icallback("doFull")),
                           IupButton("maximize",   Icallback("doMax")),
                           IupButton("minimize",   Icallback("doMin")),
                           IupButton("dim",        Icallback("doDim")),
                           IupButton("show",       Icallback("doShow")),
                           IupButton("move",       Icallback("doMove"))})
   IupSetAttribute(hbox,"MARGIN", "10x10")
   IupSetAttribute(hbox,"PADDING", "5x5")

   dlg = IupDialog(hbox)
   IupSetAttribute(dlg,"OPACITY","255")

   IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
   IupMainLoop()
   IupClose()

end procedure main()</lang>

PicoLisp

The following works on ErsatzLisp, the Java version of PicoLisp. <lang PicoLisp>$ ersatz/pil +

(setq
  JFrame         "javax.swing.JFrame"
  MAXIMIZED_BOTH (java (public JFrame 'MAXIMIZED_BOTH))
  ICONIFIED      (java (public JFrame 'ICONIFIED))
  Win            (java JFrame T "Window") )

-> $JFrame

  1. Compare for equality
(== Win Win)

-> T

  1. Set window visible

(java Win 'setLocation 100 100) (java Win 'setSize 400 300) (java Win 'setVisible T)

  1. Hide window

(java Win 'hide)

  1. Show again

(java Win 'setVisible T)

  1. Move window

(java Win 'setLocation 200 200)

  1. Iconify window

(java Win 'setExtendedState

  (| (java (java Win 'getExtendedState)) ICONIFIED) )
  1. De-conify window

(java Win 'setExtendedState

  (& (java (java Win 'getExtendedState)) (x| (hex "FFFFFFFF") ICONIFIED)) )
  1. Maximize window

(java Win 'setExtendedState

  (| (java (java Win 'getExtendedState)) MAXIMIZED_BOTH) )
  1. Close window

(java Win 'dispose)</lang>

PureBasic

<lang PureBasic>;- Create a linked list to store created windows. NewList Windows() Define i, j, dh, dw, flags, err$, x, y

- Used sub-procedure to simplify the error handling

Procedure HandleError(Result, Text.s,ErrorLine=0,ExitCode=0)

 If Not Result
   MessageRequester("Error",Text)
   End ExitCode
 EndIf
 ProcedureReturn Result

EndProcedure

- Window handling procedures

Procedure Minimize(window)

 SetWindowState(window,#PB_Window_Minimize)

EndProcedure

Procedure Normalize(window)

 SetWindowState(window,#PB_Window_Normal)

EndProcedure

- Get enviroment data

HandleError(ExamineDesktops(), "Failed to examine you Desktop.") dh=HandleError(DesktopHeight(0),"Could not retrieve DesktopHight")/3 dw=HandleError(DesktopWidth(0), "Could not retrieve DesktopWidth")/3

- Now, creating 9 windows

flags=#PB_Window_SystemMenu err$="Failed to open Window" For i=0 To 8

 j=HandleError(OpenWindow(#PB_Any,i*10,i*10+30,10,10,Str(i),flags),err$)
 SmartWindowRefresh(j, 1) 
 AddElement(Windows())
 Windows()=j

Next i Delay(1000)

- Call a sub-routine for each Window stored in the list.

ForEach Windows()

 Minimize(Windows())

Next Delay(1000)

- and again

ForEach Windows()

 Normalize(Windows())

Next Delay(1000)

- Spread them evenly

ForEach Windows()

 ResizeWindow(Windows(),x*dw,y*dh,dw-15,dh-35)
 x+1
 If x>2
   x=0: y+1
 EndIf

Next Delay(2000)

End</lang>

Python

Works with: Python version 3.x
Library: tkinter

Using the tkinter GUI: <lang Python> from tkinter import * import tkinter.messagebox

def maximise(): """get screenwidth and screenheight, and resize window to that size. Also move to 0,0""" root.geometry("{}x{}+{}+{}".format(root.winfo_screenwidth(), root.winfo_screenheight(), 0, 0))

def minimise(): """Iconify window to the taskbar. When reopened, the window is unfortunately restored to its original state, NOT its most recent state.""" root.iconify()

def delete(): """create a modal dialog. If answer is "OK", quit the program""" if tkinter.messagebox.askokcancel("OK/Cancel","Are you sure?"): root.quit()

root = Tk()

mx=Button(root,text="maximise",command=maximise) mx.grid() mx.bind(maximise)

mn=Button(root,text="minimise",command=minimise) mn.grid() mn.bind(minimise)

  1. catch exit events, including "X" on title bar.

root.protocol("WM_DELETE_WINDOW",delete)

mainloop() </lang>

Racket

<lang racket>

  1. lang racket/gui

(define (say . xs) (printf ">>> ~a\n" (apply ~a xs)) (flush-output))

(define frame (new frame% [label "Demo"] [width 400] [height 400])) (say "frame = " frame) ; plain value

(say 'Show) (send frame show #t) (sleep 1) (say 'Hide) (send frame show #f) (sleep 1) (say 'Show) (send frame show #t) (sleep 1) (say 'Minimize) (send frame iconize #t) (sleep 1) (say 'Restore) (send frame iconize #f) (sleep 1) (say 'Maximize) (send frame maximize #t) (sleep 1) (say 'Restore) (send frame maximize #f) (sleep 1) (say 'Move) (send frame move 100 100) (sleep 1) (say 'Resize) (send frame resize 100 100) (sleep 1) (say 'Close) (send frame show #f) (sleep 1) ; that's how we close a window </lang>


Ring

<lang ring>

Load "guilib.ring"

/*

+--------------------------------------------------------------------------
+        Program Name : ScreenDrawOnReSize.ring
+        Date         : 2016.06.16
+        Author       : Bert Mariani
+        Purpose      : Re-Draw Chart after ReSize or move
+--------------------------------------------------------------------------
  • /


      1. -------------------------------
      2. DRAW CHART size 1000 x 1000
      1. ------------------------------
      1. Window Size
   WinLeft   = 80                  ### 80    Window position on screen
   WinTop    = 80                  ### 80    Window position on screen
   WinWidth  = 1000                ### 1000  Window Size - Horizontal-X WinWidth
   WinHeight = 750                 ### 750   Window Size - Vertical-Y WinHeight
   WinRight  = WinLeft + WinWidth  ### 1080
   WinBottom = WinTop  + WinHeight ### 830
            
      1. Label Box Size
   BoxLeft   = 40                  ###  Start corner   Label1 Box Start Position inside WIN1
   BoxTop    = 40                  ###  Start corner 
   BoxWidth  = WinWidth  -80       ###  End   corner   Label1 Box Size
   BoxHeight = WinHeight -80       ###  End   corner  
      1. ----------------------------


New qapp {

       win1 = new qwidget() {
       
               ### Position and Size of WINDOW on the Screen
               setwindowtitle("DrawChart using QPainter")
               setgeometry( WinLeft, WinTop, WinWidth, WinHeight)
               
               win1{ setwindowtitle("Initial Window Position: " +" L " + WinLeft +" T " + WinTop +" Width" + width() +" Height " +  height() ) }
               ### ReSizeEvent ... Call WhereAreWe function
               myfilter = new qallevents(win1)
               myfilter.setResizeEvent("WhereAreWe()")
               installeventfilter(myfilter)
               
               ### Draw within this BOX
               label1 = new qlabel(win1) {
                       setgeometry(BoxLeft, BoxTop, BoxWidth, BoxHeight)
                       settext("We are Here")
               }


               ### Button Position and Size ... Call DRAW function
               new qpushbutton(win1) {
                       setgeometry( 30, 30, 80, 20)
                       settext("Draw")
                       setclickevent("Draw()")
               }
               ###---------------
               show()
       }
       
   exec()

}


      1. -----------------
      2. FUNCTION Draw
      3. -----------------

Func WhereAreWe

       Rec = win1.framegeometry()
   
       WinWidth  = win1.width()            ### 1000 Current Values 
       WinHeight = win1.height()           ### 750 
       
       WinLeft   = Rec.left() +8           ### <<< QT FIX because of Win Title
       WinTop    = Rec.top()  +30          ### <<< QT FIX because of Win Title 
       WinRight  = Rec.right()
       WinBottom = Rec.bottom()
       BoxWidth  = WinWidth  -80           ### 950
       BoxHeight = WinHeight -80           ### 700
       win1{ setwindowtitle("Window ReSize: Win " +  WinWidth + "x" + WinHeight + " --- Box " + BoxWidth  + "x" + BoxHeight  + 
                             " --- LT " +  WinLeft + "-"   + WinTop  + " --- RB " + WinRight + "-" + WinBottom      ) }
       
       See "We Are Here - setResizeEvent - " 
       See " Win "  + WinWidth  + "x" + WinHeight + " --- Box  "  + BoxWidth + "x" + BoxHeight  
       See " --- LT " + Winleft   + "-"   + WinTop    + " --- RB " + WinRight + "-"   + WinBottom +nl
       
         win1.setgeometry( WinLeft, WinTop, WinWidth, WinHeight )
       label1.setgeometry( BoxLeft, BoxTop, BoxWidth, BoxHeight )
       
   

return

Func Draw

       win1{ setwindowtitle("Draw Position: Win " +  WinWidth + "x" + WinHeight + " --- Box " + BoxWidth  + "x" + BoxHeight  + 
                             " --- LT " +  WinLeft + "-"   + WinTop  + " --- RB " + WinRight + "-" + WinBottom      ) }
                             
       See "Draw Position: " +  WinWidth + "x" + WinHeight + " --- Box " + BoxWidth  + "x" + BoxHeight  + 
                             " --- LT " +  WinLeft + "-"   + WinTop  + " --- RB " + WinRight + "-" + WinBottom  + nl
                             
 
 #     ##-----------------------------
       ### PEN Colors
       
       p1 = new qpicture()
           colorBlue = new qcolor() { setrgb(0,    0,255,255) }
           penBlue   = new qpen() { setcolor(colorBlue)  setwidth(1) }


       ###-----------------------
       ### PAINT the Chart
       new qpainter() {
               begin(p1)
               setpen(penBlue)
               ###---------------------
               ### Draw Line Chart
               drawline(        1 ,         1 , BoxWidth ,         1 )     ### WinTop line horizonal
               drawline(        1 ,         1 ,        1 , BoxHeight )     ### WinLeft Line vetical
               
               drawline(        1 , BoxHeight , BoxWidth , BoxHeight )     ### Bottom Line horizontal
               drawline( BoxWidth ,         1 , BoxWidth , BoxHeight )     ### WinRight Line vertical
               
               drawline( BoxWidth / 2 ,             1 , BoxWidth / 2 ,   BoxHeight     )    ### Central vertical   
               drawline(            1 , BoxHeight / 2 , BoxWidth     ,   BoxHeight / 2 )    ### Central horizontal


               ###--------------------------------------------------


               endpaint()
       }
       
       
       label1 { setpicture(p1) show() }
       

return

      1. --------------------------------------------

</lang>


Tcl

Library: Tk

<lang tcl>package require Tk

  1. How to open a window

proc openWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       # Already existing; just reset
       wm deiconify $win
       wm state $win normal
       return
   }
   catch {destroy $win} ;# Squelch the old one
   set win [toplevel .t]
   pack [label $win.label -text "This is the window being manipulated"] \
       -fill both -expand 1

}

  1. How to close a window

proc closeWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       destroy $win
   }

}

  1. How to minimize a window

proc minimizeWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       wm state $win iconic
   }

}

  1. How to maximize a window

proc maximizeWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       wm state $win zoomed
       catch {wm attribute $win -zoomed 1} ;# Hack for X11
   }

}

  1. How to move a window

proc moveWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       scan [wm geometry $win] "%dx%d+%d+%d" width height x y
       wm geometry $win +[incr x 10]+[incr y 10]
   }

}

  1. How to resize a window

proc resizeWin {} {

   global win
   if {[info exists win] && [winfo exists $win]} {
       scan [wm geometry $win] "%dx%d+%d+%d" width height x y
       wm geometry $win [incr width 10]x[incr height 10]
   }

}

grid [label .l -text "Window handle:"] [label .l2 -textvariable win] grid [button .b1 -text "Open/Reset" -command openWin] - grid [button .b2 -text "Close" -command closeWin] - grid [button .b3 -text "Minimize" -command minimizeWin] - grid [button .b4 -text "Maximize" -command maximizeWin] - grid [button .b5 -text "Move" -command moveWin] - grid [button .b6 -text "Resize" -command resizeWin] -</lang>