AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

New hide windows script

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Charon the Hand



Joined: 07 Aug 2007
Posts: 4

PostPosted: Tue Aug 07, 2007 8:51 pm    Post subject: New hide windows script Reply with quote

I know, just what the world needs is another script to hide windows. But this one is better.
Code:
/*
Autohide, by Charon the Hand.

This script hides a window with {Win}F5. {Win}F6 brings up a listview with icons showing the windows that
have been hidden. You can select one by double clicking its row or highlighting the row with arrow keys and
hitting {Enter}. The script will keep a list of windows currently hidden; if it exits for any reason other
than system shutdown, it writes the names of hidden windows to an .ini file. On restarting, the script reads
those values and rebuilds the listview. {Win}F7 exits the script (mostly for testing purposes). {Win}F8
currently does nothing, but I used it extensively for testing. The hotkeys are customizable. The colors of
the listview (background, border, text) are customizable. Currently you can hide 10 windows, but that too
is customizable if necessary.

Credit to evl for his Alt-Tab Replacement, from which I borrowed the DllCall code to retrieve icons and much
help in building listviews. Also to the author (can't find his/her name anywhere) of Minimize Window to Tray
Menu from the script showcase for the trick of raising the next window in the z-order when hiding.
*/

#NoEnv
#NoTrayIcon
#InstallKeybdHook
#SingleInstance Force
DetectHiddenWindows On
SetTitleMatchMode 3
CoordMode, Mouse
OnExit, ch_SaveToIni
OnMessage( 0x06, "ch_WM_ACTIVATE" )
ch_totalWindows := 0

;================================Variables================================;

ch_hotkeyHide := "#F5"                     ;{Win}F5
ch_hotkeyShow := "#F6"                     ;{Win}F6
ch_hotkeyExit := "#F7"                            ;{Win}F7
ch_maxWindows := 10
ch_bgColor := "EBEBEB"
ch_borderColor := "B22222"
ch_textColor := "191919"

;================================Autoexecute================================;


Loop, %ch_maxWindows%                     ;read the ini file to see if there are any
{                                               ;windows to be restored, then erase contents
   IniRead, ch_winNameFromIni, autohide.ini, Window%A_Index%, WinTitle
   If ch_winNameFromIni = ERROR
      continue
   IniRead, ch_winIdFromIni, autohide.ini, Window%A_Index%, WinId
   IniDelete, autohide.ini, Window%A_Index%
   Loop %ch_maxWindows%
   {
      If ch_winName%A_Index% =
      {
         ch_winName%A_Index% := ch_winNameFromIni
         ch_winId%A_Index% := ch_winIdFromIni
         ch_winNameLength%A_Index% := StrLen(ch_winNameFromIni)
         ch_totalWindows += 1
         break
      }
   }
}
ch_BuildListView()
Hotkey, %ch_hotkeyHide%, ch_HideWindow
Hotkey, %ch_hotkeyShow%, ch_ShowWindow
Hotkey, %ch_hotkeyExit%, ch_SaveToIni
return

;================================Hotkeys================================;

#F8::
msgbox, %ch_longestName%
return

;================================Subroutines================================;

ch_HideWindow:
   WinGetTitle, ch_winName, A
   WinGetClass, ch_winClass, A
   WinGet, ch_winId, Id, A
   If ch_winClass in Progman,Shell_TrayWnd
      return
   Send, !{Esc}
   WinHide, ahk_id %ch_winId%
   Loop %ch_maxWindows%
   {
      If ch_winId%A_Index% =                ;find an empty variable and put the window name in
      {
         ch_winId%A_Index% := ch_winId
         ch_winName%A_Index% := ch_winName
         ch_winNameLength%A_Index% := StrLen(ch_winName)
         ch_totalWindows +=1
         break
      }
   }
   return

ch_ShowWindow:
   If ch_totalWindows = 0
      return
   MouseGetPos, ch_xpos, ch_ypos            ;put LV right under the mouse
   ch_xpos -= 10
   ch_ypos -= 10
   ch_BuildListView()
   Gui, Show, x%ch_xpos% y%ch_ypos%
   return

ch_SaveToIni:
   If A_ExitReason in Shutdown,Exit         ;if shutting down the computer, skip
      ExitApp
   Loop, %ch_maxWindows%                  ;if closing for any other reason, store currently
   {                                           ;hidden windows in ini file for restoration later
      If ch_winName%A_Index% =
         continue
      ch_outerLoopA_Index := A_Index
      Loop, %ch_maxWindows%
      {
         IniRead, ch_freeSpace, autohide.ini, Window%A_Index%, WinTitle
         If ch_freeSpace = ERROR
         {
            IniWrite, % ch_winName%ch_outerLoopA_Index%, autohide.ini, Window%A_Index%, WinTitle
            IniWrite, % ch_winId%ch_outerLoopA_Index%, autohide.ini, Window%A_Index%, WinId
            break
         }
      }
   }
   ExitApp

ch_LVMenu:
   If A_GuiEvent = DoubleClick               ;restore window on double-click
   {
      ch_RestoreWindow(A_EventInfo)
   }
   return

ButtonOK:                              ;restore window on {Enter}
   GuiControlGet, ch_FocusedControl, FocusV
   If ch_FocusedControl <> ch_LVMenu
       return
   else
   {
      ch_RowNum := LV_GetNext(0, "Focused")
      ch_RestoreWindow(ch_RowNum)
   }
   return

;================================Functions================================;

ch_WM_ACTIVATE(ch_wParam)
{
   Global
   If (ch_wParam = 0)                      ;if the listview loses focus, hide it
   {
      Gui, Hide
    }
}

ch_BuildListView()
{   
   global
   Gui, Destroy
   ch_GetLongestName()
   Gui, Color, %ch_borderColor%, %ch_bgColor%
   Gui, Margin, 1,1
   Gui, +ToolWindow -Caption
   Gui, Font, s12 c%ch_textColor%
   Gui, Add, ListView, Report -Hdr r%ch_totalWindows% w%ch_longestName% Count10 gch_LVMenu vch_LVMenu, |
   Gui, Add, Button, w0 h0 x0 y-1 Hidden Default, OK
   ch_ImageListID := IL_Create(10)           ;invisible OK button, so you can use {Enter} to select
   LV_SetImageList(ch_ImageListID)          ;Create an ImageList to hold 10 small icons.
                                                ;Assign the above ImageList to the current ListView.
   Loop, %ch_maxWindows%
   {
      If ch_winId%A_Index% =
         continue
      ch_winName := ch_winName%A_Index%      ;this whole icon routine is from evl, I don't pretend to
      ch_winId := ch_winId%A_Index%         ;understand it, I just modified it until it worked for me
      SendMessage, 0x7F, 2, 0,, ahk_id %ch_winId%
       ch_hIcon := ErrorLevel               
       If ( ! ch_hIcon )
       {
             SendMessage, 0x7F, 0, 0,, ahk_id %ch_winId%
             ch_hIcon := ErrorLevel
             If ( ! ch_hIcon )
             {
                 ch_hIcon := DllCall( "GetClassLong", "uint", ch_winId, "int", -34 ) ; GCL_HICONSM is -34
                 If ( ! ch_hIcon )
                 {
                     ch_hIcon := DllCall( "LoadIcon", "uint", 0, "uint", 32512 ) ; IDI_APPLICATION is 32512
                 }
             }
       }
         ;Add the HICON directly to the small-icon and large-icon lists.
         ;Below uses +1 to convert the returned index from zero-based to one-based:
       ;Create the new row in the ListView and assign it the icon number determined above ; Add 2 spaces for looks
        ch_IconNumber := DllCall("ImageList_ReplaceIcon", UInt, ch_ImageListID, Int, -1, UInt, ch_hIcon) + 1
         LV_Add("Icon" . ch_IconNumber, A_Space . A_Space . ch_winName)
         continue
      }
   WinGetClass, ch_winClass, ahk_id %ch_winId%
   If ch_winClass = #32770 ; fix for displaying control panel related windows (dialog class) that aren't on taskbar
   {
         ch_IconNumber := IL_Add(ch_ImageListID, "C:\WINDOWS\system32\shell32.dll" , 217) ; generic control panel icon
         LV_Add("Icon" . ch_IconNumber,  ch_winName)
         
   }
   return
}

ch_RestoreWindow(ch_RowNum)
{
   global
    LV_GetText(ch_RowText, ch_RowNum, 1)        ;Get the text from the row's first field.
    StringTrimLeft, ch_RowText, ch_RowText, 2   ;Remove the 2 spaces before using
    WinGet, ch_winIdToRestore, Id, %ch_RowText%   
    WinShow, ahk_id %ch_winIdToRestore%         
    LV_Delete(ch_RowNum)                       
    Loop, %ch_maxWindows%                       ;Delete the contents of the variables so the
    {                                           ;row doesn't get recreated in the next call
       If ch_winName%A_Index% = %ch_RowText%
       {
          ch_winName%A_Index% := 
          ch_winId%A_Index% :=
          ch_winNameLength%A_Index% :=   
          ch_totalWindows -= 1
          break
       }
    }
    Gui, Hide
    return
}

ch_GetLongestName()
{
   global
   ch_longestName := 0
   Loop, %ch_maxWindows%
   {
      If % ch_winName%A_Index% =
         continue
      If % ch_winNameLength%A_Index% >= ch_longestName   
      ch_longestName := ch_winNameLength%A_Index%
   }
   If ch_longestName <= 20                  ;window names with fewer letters get a slightly bigger window built
      ch_longestName := ((ch_longestName + 2) * 7) + 40
   else
      ch_longestName := ((ch_longestName + 2) * 7.75)
   return
}


I've been playing with AHK for a couple months, but this is the first script I've polished up enough to release to the world. Thanks to chris and the forum for constantly amazing me with AHK's versatility.
Back to top
View user's profile Send private message
Zusukar
Guest





PostPosted: Mon May 12, 2008 6:20 pm    Post subject: Modifications to Autohide Reply with quote

I loved this script, but a few things bothered me enough to fix them. Here is an improved version that fixes a few bugs.

Notably:

The window titles will update if they change while hidden.
The width of the list is correctly determined.
If a window closes while hidden, it will automatically be removed from the list.
Don't hide a window if there are no available entries in the array.
The icon list will allocate enough entries based on the number of hidden windows instead of always 10.
Other minor changes.

Code:

/*
HideWinList, by Zusukar
Originally Autohide by Charon the Hand.

This script hides a window with {Win}Q. {Win}W brings up a listview with icons showing the windows that
have been hidden. You can select one by double clicking its row or highlighting the row with arrow keys and
hitting {Enter}. The script will keep a list of windows currently hidden; if it exits for any reason other
than system shutdown, it writes the names of hidden windows to an .ini file. On restarting, the script reads
those values and rebuilds the listview. {Win}F7 exits the script (mostly for testing purposes). The hotkeys
are customizable. The colors of the listview (background, border, text) are customizable. Currently you can
hide 10 windows, but that too is customizable if necessary.

Credit to evl for his Alt-Tab Replacement, from which I borrowed the DllCall code to retrieve icons and much
help in building listviews. Also to the author (can't find his/her name anywhere) of Minimize Window to Tray
Menu from the script showcase for the trick of raising the next window in the z-order when hiding.

Credit to Sean for his GetTextExtentPoint function that determines text height and width.  This has been
modified to only return the width.
(http://www.autohotkey.com/forum/post-113847.html&sid=cb1840004443b42e1a730db24896b406#113847)
*/

#KeyHistory 0
#NoEnv
#NoTrayIcon
#InstallKeybdHook
#SingleInstance Force
DetectHiddenWindows On
SetTitleMatchMode 3
CoordMode, Mouse
OnExit, ch_Exit
OnMessage( 0x06, "ch_WM_ACTIVATE" )

;================================Variables================================;

ch_hotkeyHide := "#q"                     ;{Win}q
ch_hotkeyShow := "#w"                     ;{Win}w
ch_hotkeyExit := "#F7"                    ;{Win}F7
ch_maxWindows := 10
ch_bgColor := "EBEBEB"
ch_borderColor := "000000"
ch_textColor := "191919"
ch_textFont := "Microsoft Sans Serif"
ch_totalWindows := 0

;===============================Autoexecute===============================;

ch_LoadFromIni()
Hotkey, %ch_hotkeyHide%, ch_HideActiveWindow
Hotkey, %ch_hotkeyShow%, ch_ShowWindow
Hotkey, %ch_hotkeyExit%, ch_Exit
return

;=================================HotKeys=================================;


;===============================Subroutines===============================;

ch_HideActiveWindow:
  WinGetClass, ch_winClass, A
  If ch_winClass in Progman,Shell_TrayWnd
    return
  WinGet, ch_winId, Id, A
  Send, !{Esc}
  ch_HideWindow(ch_winId)
  return

ch_ShowWindow:
  If ch_totalWindows = 0
    return
  MouseGetPos, ch_xpos, ch_ypos            ;put LV right under the mouse
  ch_xpos -= 10
  ch_ypos -= 10
  ch_BuildListView()
  if ch_totalWindows > 0
    Gui, Show, x%ch_xpos% y%ch_ypos%
  return

ch_Exit:
  If A_ExitReason in Shutdown,Exit         ;if shutting down the computer, skip
    ExitApp
  ch_SaveToIni()                           ;if closing for any other reason, save hidden windows
  ExitApp
 
ch_LVMenu:
  If A_GuiEvent = DoubleClick               ;restore window on double-click
    ch_RestoreWindow(A_EventInfo)
  return

ButtonOK:                                  ;restore window on {Enter}
  GuiControlGet, ch_FocusedControl, FocusV
  If ch_FocusedControl <> ch_LVMenu
  {
    ch_FocusedControl :=
    return
  }
  else
  {
    ch_FocusedControl :=
    ch_RestoreWindow(LV_GetNext(0, "Focused"))
  }
  return

GUIEscape:
  GUI, Destroy
  return

;================================Functions================================;

ch_HideWindow(ch_winId)
{
  global
  local ch_stored := 0
  Loop, %ch_maxWindows%
  {
    If ch_winId%A_Index% =                ;find an empty variable and put the window ID in
    {
      ch_winId%A_Index% := ch_winId
      ch_totalWindows += 1
      ch_stored := 1
      Break
    }
  }
  If ch_stored = 1
    WinHide, ahk_id %ch_winId%
  return
}

ch_SaveToIni()
{
  global
  local this_id
  Loop, %ch_maxWindows%                  ;store currently
  {                                      ;hidden windows in ini file for restoration later
    this_id := ch_winId%A_Index%
    IfWinNotExist, ahk_id %this_id%
      continue
    If ch_winId%A_Index% =
      continue
    IniWrite, % ch_winId%A_Index%, HideWinList.ini, Window%A_Index%, WinId
  }
  return
}

ch_LoadFromIni()
{
  global
  local this_id
  Loop, %ch_maxWindows%                     ;read the ini file to see if there are any
  {                                         ;windows to be restored, then erase contents
    IniRead, this_id, HideWinList.ini, Window%A_Index%, WinId
    If this_id = ERROR
      continue
    IniDelete, HideWinList.ini, Window%A_Index%
    IfWinNotExist, ahk_id %this_id%
      continue
    ch_HideWindow(this_id)
  }
  return
}

ch_WM_ACTIVATE(ch_wParam)
{
  If (ch_wParam = 0)                      ;if the listview loses focus, hide it
    Gui, Destroy
  return
}

ch_BuildListView()
{   
  global
  Gui, Destroy
  ch_GetLongestName()
  If ch_longestName = 0
    return
  Gui, Color, %ch_borderColor%, %ch_bgColor%
  Gui, Margin, 1,1
  Gui, +ToolWindow -Caption
  Gui, Font, s12 c%ch_textColor%, %ch_textFont%
  Gui, Add, ListView, Report -Hdr r%ch_totalWindows% w%ch_longestName% Count%ch_totalWindows% gch_LVMenu vch_LVMenu, ||
  ch_longestName :=
 
  ;invisible OK button, so you can use {Enter} to select
  Gui, Add, Button, w0 h0 x0 y-1 Hidden Default, OK
 
  ;Create an ImageList to hold the small icons.
  local ch_ImageListID := IL_Create(ch_totalWindows)
 
  ;Assign the above ImageList to the current ListView.
  LV_SetImageList(ch_ImageListID)
  Loop, %ch_maxWindows%
  {
    local this_id := ch_winId%A_Index%
    If this_id =
      continue
    IfWinNotExist ahk_id %this_id%
    {
      ch_winId%A_Index% :=
      ch_totalWindows -= 1
      continue
    }   
    local ch_winId := ch_winId%A_Index%         

    local ch_winClass
    WinGetClass, ch_winClass, ahk_id %ch_winId%
    If ch_winClass = #32770 ; fix for displaying control panel related windows (dialog class) that aren't on taskbar
      local ch_IconNumber := IL_Add(ch_ImageListID, "C:\WINDOWS\system32\shell32.dll" , 217) ; generic control panel icon
    Else
    {
      ;this whole icon routine is from evl, I don't pretend to
      ;understand it, I just modified it until it worked for me
      SendMessage, 0x7F, 2, 0,, ahk_id %ch_winId%
      local ch_hIcon := ErrorLevel               
      If ( ! ch_hIcon )
      {
        SendMessage, 0x7F, 0, 0,, ahk_id %ch_winId%
        ch_hIcon := ErrorLevel
        If ( ! ch_hIcon )
        {
          ch_hIcon := DllCall( "GetClassLong", "uint", ch_winId, "int", -34 ) ; GCL_HICONSM is -34
          If ( ! ch_hIcon )
          {
            ch_hIcon := DllCall( "LoadIcon", "uint", 0, "uint", 32512 ) ; IDI_APPLICATION is 32512
          }
        }
      }
      ;Add the HICON directly to the small-icon and large-icon lists.
      ;Below uses +1 to convert the returned index from zero-based to one-based:
      ;Create the new row in the ListView and assign it the icon number determined above ; Add 2 spaces for looks
      ch_IconNumber := DllCall("ImageList_ReplaceIcon", "uint", ch_ImageListID, "int", -1, "uint", ch_hIcon) + 1
    }
    local ch_winName
    WinGetTitle, ch_winName, ahk_id %ch_winId%
    LV_Add("Icon" . ch_IconNumber, A_Index . A_Space . ch_winName)
    continue
  }
  LV_ModifyCol()
  return
}

ch_RestoreWindow(ch_RowNum)
{
  LV_GetText(ch_rowText, ch_RowNum, 1)        ;Get the Info from the row's first field.
  StringGetPos, ch_firstSpace, ch_rowText, %A_Space%  ;These two lines extract the
  StringLeft, ch_index, ch_rowText, ch_firstSpace     ;array index for the selected window
  ch_winId := ch_winId%ch_Index%
  WinShow, ahk_id %ch_winId%
  ch_winId%ch_index% :=                   ;Delete the contents of the variable
  global ch_totalWindows -= 1
  Gui, Destroy
  return
}

ch_GetLongestName()
{
  global
  ch_longestName := 0
  Loop, %ch_maxWindows%
  {
    local this_id := ch_winId%A_Index%
    If ch_winId%A_Index% =
      continue
    IfWinNotExist, ahk_id %this_id%
      continue
    local ch_winId := ch_winId%A_Index%
    local ch_winName
    WinGetTitle, ch_winName, ahk_id %ch_winId%
    local ch_winNameLength := GetTextWidth(ch_winName, ch_textFont)
    If (ch_winNameLength >= ch_longestName)
      ch_longestName := ch_winNameLength
  }

  If ch_longestName <> 0
    ch_longestName := ch_longestName + 50  ;add some room for the icon

  return
}

;GetTextWidth by Sean:  http://www.autohotkey.com/forum/post-113847.html&sid=cb1840004443b42e1a730db24896b406#113847
GetTextWidth(sString, sFaceName, nHeight = 12, bBold = False, bItalic = False, bUnderline = False, bStrikeOut = False, nCharSet = 0)
{
  hDC := DllCall("GetDC", "Uint", 0)
  nHeight := -DllCall("MulDiv", "int", nHeight, "int", DllCall("GetDeviceCaps", "Uint", hDC, "int", 90), "int", 72)

  hFont := DllCall("CreateFont", "int", nHeight, "int", 0, "int", 0, "int", 0, "int", 400 + 300 * bBold, "Uint", bItalic, "Uint", bUnderline, "Uint", bStrikeOut, "Uint", nCharSet, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0, "str", sFaceName)
  hFold := DllCall("SelectObject", "Uint", hDC, "Uint", hFont)

  DllCall("GetTextExtentPoint32", "Uint", hDC, "str", sString, "int", StrLen(sString), "int64P", nSize)

  DllCall("SelectObject", "Uint", hDC, "Uint", hFold)
  DllCall("DeleteObject", "Uint", hFont)
  DllCall("ReleaseDC", "Uint", 0, "Uint", hDC)

  nWidth  := nSize & 0xFFFFFFFF

  Return nWidth
}
Back to top
Charon the Hand



Joined: 07 Aug 2007
Posts: 4

PostPosted: Tue May 13, 2008 3:01 pm    Post subject: Reply with quote

Thank you, Zusukar! It is gratifying to know that someone uses this script and found ways to improve it. I always knew a few things were a bit hacky, especially the window width, thank you for fixing it up.
Back to top
View user's profile Send private message
Guest






PostPosted: Wed Jun 04, 2008 7:35 pm    Post subject: Reply with quote

Nice, thank you Charon and Zusukar for the script and the fix. It's very simple and useful Smile
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group