Second Edit Pane for SciTE4AutoHotkey

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 01:26

One of my favorite features of Notepad++ is that I can have a second editing pane open within the same window. I use it for viewing different files I want to reference right next to my code, and also to view one part of my script and do searches in it while I edit another part of it. It's much more handy to me to have it part of the same window than as a separate independent window.

I really like using SciTE4AutoHotkey, and I wish it had this feature. Since it doesn't, I wrote a script that makes a second SciTE4AutoHotkey window behave much like a second pane of the same window. It does so by doing the following:
  • the second pane is created within the original main window area
  • you can move the "split" between the two panes by dragging it
  • both panes resize/move together when either is resized/moved (i.e., they stay linked)
  • when one pane is activated, the other also moves in front of any other windows
  • when the main window is minimized or restored, the second pane minimizes/restores also
  • when you maximize the main window, both the main window and the second pane fill the screen
  • when the second pane is closed, the main window takes the size that both did together
  • when the main window is closed, the second pane closes as well (if open files are saved)
  • the second pane doesn't have a title bar or taskbar icon
If you don't yet have the feature installed to open new windows in SciTE4AutoHotkey, add the properties shown in the spoiler (also shown in the script comments) to your SciTEUser.properties file, per Joetazz at his two posts starting here: http://ahkscript.org/boards/viewtopic.p ... 180#p24690. You can open new windows with a shortcut key, from the tools menu, or from the context menu when you right click on a file's tab.
Spoiler
Note: Edits made in a second SciTE4AutoHotkey window containing the same file (whether using this script or not), do not appear in the other window until the file is saved. Save your edits in one window before making edits in the other window if you choose to edit the same file in both windows. You may wish to use the second window mainly for viewing and searching without losing your place in the main window.

Added feature: Support for TillaGoto for the second pane. Additional windows in SciTE4AutoHotkey don't have the TillaGoto controls, but this script adds functionality that allows for the second pane created by this script to make use of TillaGoto.
  • Both panes must be showing the same file.
  • If the second pane is active, press F12 once to activate the main window, and press it again to select TillaGoto. If the main window is already active, just press F12 once as usual.
  • Type the beginning of the function/label/hotkey (FLH) until the desired item is the first (or only) displayed item
  • Press F11, and the the script will automatically perform a "Find" and move to the desired FLH in the second pane

Code: Select all

; -------------------------------------------------------------
;             Second Edit Pane for SciTE4AutoHotkey
;                    boiler at ahkscript.org
; -------------------------------------------------------------
;  Causes a second SciTE window to behave similar to a second 
;  edit pane within the main window, similar to NotePad++.
;  Run this script before opening a second window, and keep it
;  open during your SciTE4AutoHotkey editing session.
; -------------------------------------------------------------
;                        Thanks to:
;         fincs at ahkscript.org for SciTE4AutoHotkey
;   Joetazz at ahkscript.org for SciTE new window properties
;  maul.esel at autohotkey.com for removing taskbar icons code
; -------------------------------------------------------------

/*

To add the ability to create a second window via menu selection or
shortcut key, add the following to the SciTEUser.properties file:

# Open file in a new window
command.name.17.*=Open in New Window
command.mode.17.*=subsystem:2
command.shortcut.17.*=Ctrl+Shift+N
command.17.*="$(SciteDefaultHome)\SciTE.exe" -check.if.already.open=0 -save.session=0 "$(FilePath)"

# Open a new window
command.name.18.*=Open New Window
command.mode.18.*=subsystem:2,savebefore:no
command.shortcut.18.*=Alt+Shift+N
command.18.*="$(SciteDefaultHome)\SciTE.exe" -check.if.already.open=0 -save.session=0

*/

#SingleInstance, Force
#Persistent
SetTitleMatchMode, 2
SetWinDelay, 1

SysGet, SM_CXFRAME, 32
SysGet, SM_CYFRAME, 33

IID_ITaskbarList  := "{56FDF342-FD6D-11d0-958A-006097C9A090}"
CLSID_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}"

; set LastCount with the initial number of SciTE4AutoHotkey windows:
WinGet, LastCount, Count, - SciTE4AutoHotkey ahk_exe SciTE.exe

SetTimer, WindowUpdate, 50

return

F11::
	if (WinExist("TillaGoto.ahk")) and (WinExist(ahk_id%SecondID%))
	{
		ControlGet, List, List,, Listbox1, TillaGoto.ahk
		StringSplit, ListItems, List, `n
		StringReplace, ListItems1, ListItems1, )
		WinClose, TillaGoto.ahk
		WinActivate, ahk_id%SecondID%
		WinMenuSelectItem, ahk_id%SecondID%,, Search, Find...
		Send, %ListItems1%
		ControlClick, Button2, ahk_id%SecondID%
		ControlFocus, Scintilla1, ahk_id%SecondID%
		Send, {Home}
	}
return

#if WinActive("ahk_id" . SecondID)
F12::WinActivate, ahk_id%MainID%
	
WindowUpdate:
	WinGet, NewCount, Count, % " SciTE4AutoHotkey" "ahk_exe SciTE.exe"
	if (LastCount = 1)
	{
		if (NewCount = 1)
		{
			WinGet, MainID, ID, % " SciTE4AutoHotkey" "ahk_exe SciTE.exe"
			WinGetPos, MainX, MainY, MainW, MainH, ahk_id %MainID%
			WinSet, Style, +0xC00000, ahk_id%SecondID%
		}
		else if (NewCount = 2) ; got here if new window appeared
		{
			WinGet, MainState, MinMax, ahk_id %MainID%
			if (MainState = 1)
			{
				WinRestore, ahk_id %MainID%
				WinMove, ahk_id %MainID%,, MainX + SM_CXFRAME, MainY + SM_CYFRAME, MainW - 2 * SM_CXFRAME, MainH - 2 * SM_CYFRAME
			}
			WinGet, WinList, List, % " SciTE4AutoHotkey" "ahk_exe SciTE.exe"
			Loop, %WinList%
				if (WinList%A_Index% != MainID)
				{
					SecondID := WinList%A_Index%
					WinGetPos, MainX, MainY, MainW, MainH, ahk_id %MainID%
					LastMainX := MainX
					LastMainY := MainY
					LastMainW := MainW
					LastMainH := MainH * 0.6
					LastSecondW := MainW
					LastSecondH := MainH * 0.4
					WinMove, ahk_id%MainID%,,,,, LastMainH
					WinMove, ahk_id%SecondID%,, MainX, MainY + LastMainH, MainW, LastSecondH
					LastSecondX := MainX
					LastSecondY := MainY + LastSecondH
					LastSecondW := MainW
					WinSet, Style, -0xC00000, ahk_id%SecondID%
					tbl := ComObjCreate(CLSID_TaskbarList, IID_ITaskbarList)
					DllCall(NumGet(NumGet(tbl+0), 3*A_PtrSize), "ptr", tbl)
					DllCall(NumGet(NumGet(tbl+0), 5*A_PtrSize), "ptr", tbl, "ptr", SecondID)
				}
		}
	}
	if (LastCount >= 2)
	{
		if (NewCount = 1) ; got here if 2nd pane was closed
		{
			WinMove,  % " SciTE4AutoHotkey" "ahk_exe SciTE.exe",, MainX, MainY, MainW, MainH
			IfWinNotExist, ahk_id%MainID%
				WinClose, ahk_id%SecondID%
		}
		if (NewCount >= 2) ; got here if the second pane was opened and is still open
		{
			Gosub, Sync
		}
	}
	LastCount := NewCount
return

Sync:
	{
		WinGet, MainState, MinMax, ahk_id%MainID%
		WinGet, SecondState, MinMax, ahk_id%SecondID%
		if (MainState = 1)
		{
			WinGetPos, MX, MY, MW, MH, ahk_id%MainID%
			WinRestore, ahk_id%MainID%
			LastMainX := MX + SM_CXFRAME
			LastMainY := MY + SM_CYFRAME
			LastMainW := MW - 2 * SM_CXFRAME
			LastMainH := MH - 2 * SM_CYFRAME - LastSecondH
			LastSecondX := LastMainX
			LastSecondY := LastMainY + LastMainH
			LastSecondW := LastMainW
			MainX := LastMainX
			MainY := LastMainY
			MainW := LastMainW
			MainH := LastMainH + LastSecondH
			WinMove, ahk_id%MainID%,, LastMainX, LastMainY, LastMainW, LastMainH
			WinMove, ahk_id%SecondID%,, LastSecondX, LastSecondY, LastSecondW, LastSecondH
		}
		if (MainState = -1) or (SecondState = -1)
		{
			if (MainState != -1) and (SecondState = -1)
				WinRestore, ahk_id%SecondID%
			if (MainState = -1) and (SecondState != -1)
				WinMinimize, ahk_id%SecondID%
		}
		else
		{
			WinGetPos, NewMainX, NewMainY, NewMainW, NewMainH, ahk_id %MainID%
			WinGetPos, NewSecondX, NewSecondY, NewSecondW, NewSecondH, ahk_id %SecondID%
			; main window resized but not moved:
			if ((NewMainW != LastMainW) or (NewMainH != LastMainH)) and (NewMainX = LastMainX) and (NewMainY = LastMainY)
			{
				WinMove, ahk_id%SecondID%,,, NewMainY + NewMainH, NewMainW, LastSecondH + LastMainH - NewMainH
				LastSecondY := NewMainY + NewMainH
				LastSecondH := LastSecondH + LastMainH - NewMainH
				LastMainW := NewMainW
				LastMainH := NewMainH
				MainW := NewMainW
				MainH := NewMainH + LastSecondH
			}
			; second pane resized but not moved:
			else if ((NewSecondW != LastSecondW) or (NewSecondH != LastSecondH)) and (NewSecondX = LastSecondX) and (NewSecondY = LastSecondY)
			{
				WinMove, ahk_id%MainID%,,,, NewSecondW
				LastMainW := NewSecondW
				LastSecondW := NewSecondW
				LastSecondH := NewSecondH
				MainW := NewSecondW
				MainH := LastMainH + NewSecondH
			}
			; main window moved but not resized:
			else if ((NewMainX != LastMainX) or (NewMainY != LastMainY)) and (NewMainW = LastMainW) and (NewMainH = LastMainH)
			{
				WinMove, ahk_id%SecondID%,, NewMainX, NewMainY + NewMainH
				LastMainX := NewMainX
				LastMainY := NewMainY
				LastSecondX := NewMainX
				LastSecondY := NewMainY + NewMainH
				MainX := NewMainX
				MainY := NewMainY
			}
			; main window resized and moved:
			else if ((NewMainX != LastMainX) or (NewMainY != LastMainY)) and ((NewMainW != LastMainW) or (NewMainH != LastMainH))
			{
				WinMove, ahk_id%SecondID%,, NewMainX, NewMainY + NewMainH, NewMainW, LastSecondH
				LastSecondX := NewMainX
				LastSecondY := NewMainY + NewMainH
				LastSecondW := NewMainW
				LastMainX := NewMainX
				LastMainY := NewMainY
				LastMainW := NewMainW
				LastMainH := NewMainH
				MainX := NewMainX
				MainY := NewMainY
				MainW := NewMainW
				MainH := NewMainH + LastSecondH
			}
			; second pane resized and moved from bottom:
			else if (NewSecondY = LastSecondY) and (NewSecondH != LastSecondH)
			{
				WinMove, ahk_id%MainID%,, NewSecondX,, NewSecondW
				LastSecondX := NewSecondX
				LastSecondY := NewSecondY
				LastSecondW := NewSecondW
				LastSecondH := NewSecondH
				LastMainX := NewSecondX
				MainX := NewSecondX
				MainW := NewSecondW
				MainH := LastMainH + NewSecondH
			}
			; second pane resized and moved from top:
			else if ((NewSecondX != LastSecondX) or (NewSecondY != LastSecondY)) and ((NewSecondW != LastSecondW) or (NewSecondH != LastSecondH))
			{
				WinMove, ahk_id%MainID%,, NewSecondX,, NewSecondW, LastMainH + LastSecondH - NewSecondH
				LastSecondX := NewSecondX
				LastSecondY := NewSecondY
				LastMainX := NewSecondX
				MainX := NewSecondX
				MainW := NewSecondW
			}
		}
	}
	IfWinActive, ahk_id%MainID%
	{
		DllCall("SetWindowPos", "uint", SecondID, "uint", MainID, "uint", 0, "uint", 0, "uint", 0, "uint", 0, "uint", 19) ;SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
		
	}
	IfWinActive, ahk_id%SecondID%
	{
		DllCall("SetWindowPos", "uint", MainID, "uint", SecondID, "uint", 0, "uint", 0, "uint", 0, "uint", 0, "uint", 19) ;SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
	}
return
Last edited by boiler on 30 Jan 2015, 00:52, edited 4 times in total.
User avatar
Soft
Posts: 174
Joined: 07 Jan 2015, 13:18
Location: Seoul
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 01:43

Nice! I needed this too
AutoHotkey & AutoHotkey_H v1.1.22.07
iPhilip
Posts: 822
Joined: 02 Oct 2013, 12:21

Re: Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 15:35

Nice work! It's a little sluggish on the window refresh. I wonder if you can use

Code: Select all

OnMessage(0x201,"WM_LBUTTONDOWN")
return

WM_LBUTTONDOWN(wParam, lParam, msg, hwnd)
{
   ; Code here
}
instead of

Code: Select all

SetTimer, WindowUpdate, 50

return

WindowUpdate:
Also, it appears that I have to exit the bottom window in order to open a another file in the bottom window. It would be convenient if the close button in the bottom window would close it, i.e. exit it.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 16:07

Thanks. I thought of that, and actually, I would use the more specific messages of WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE, but OnMessage() isn't triggered by those messages being sent to the window of another process. If you know of a way to have Windows messages sent to windows of another process trigger an event in our own process (our script), please let me know.

To me, the sluggishness isn't that big of a deal because I'm not going around resizing it all the time. I could shorten the duration of the timer from 50, but it would just tax system resources more. But I'm open to any and all suggestions for improving that or any other part of it.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 16:11

iPhilip wrote:Also, it appears that I have to exit the bottom window in order to open a another file in the bottom window. It would be convenient if the close button in the bottom window would close it, i.e. exit it.
It's true that using Close only closes the tab/file and not exit the window, but that's how I would want it. I want to be able to close the file and open another one.

I don't need to exit it in order to open another file. Maybe you are using the menu/toolbar from the top window. If you select from the menu/toolbar button in the bottom window to open a file, it should open another tab in the bottom window. It does for me. I can have several tabs open in both windows.
iPhilip
Posts: 822
Joined: 02 Oct 2013, 12:21

Re: Second Edit Pane for SciTE4AutoHotkey

27 Jan 2015, 16:20

boiler wrote:Thanks. I thought of that, and actually, I would use the more specific messages of WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE, but OnMessage() isn't triggered by those messages being sent to the window of another process. If you know of a way to have Windows messages sent to windows of another process trigger an event in our own process (our script), please let me know.

To me, the sluggishness isn't that big of a deal because I'm not going around resizing it all the time. I could shorten the duration of the timer from 50, but it would just tax system resources more. But I'm open to any and all suggestions for improving that or any other part of it.
Good point about OnMessage(). There is no easy way to have window messages sent to windows of another process.
boiler wrote:
iPhilip wrote:Also, it appears that I have to exit the bottom window in order to open a another file in the bottom window. It would be convenient if the close button in the bottom window would close it, i.e. exit it.
It's true that using Close only closes the tab/file and not exit the window, but that's how I would want it. I want to be able to close the file and open another one.

I don't need to exit it in order to open another file. Maybe you are using the menu/toolbar from the top window. If you select from the menu/toolbar button in the bottom window to open a file, it should open another tab in the bottom window. It does for me. I can have several tabs open in both windows.
You are right. I was using the menu/toolbar from the top window.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 04:00

Scintilla (the edit control used by SciTE) supports multiple controls editing the same document. A simple proof of concept shows this in action, using SciTE's output pane:

Code: Select all

if !WinExist("ahk_class SciTEWindow")
    throw "SciTE not found"
GetDocPointer=2357
SetDocPointer=2358
SendMessage GetDocPointer,,, Scintilla1
pDoc := ErrorLevel
SendMessage SetDocPointer,, pDoc, Scintilla2
When I ran it, >Exit code: 0 Time: 0.1375 was added to the end of the document. :lol:

There might be ways to disable output to the output pane (or perhaps just disable the mirroring before running a command). You would also need to set the output pane's lexer appropriately, and possibly do other things. If you wanted to use a separate Scintilla control, it would need to be created by SciTE itself, or a Lua script; but I'm not sure whether Lua has access to the necessary functions.

Of course, one could instead add the features of SciTE4AutoHotkey to a more feature-complete editor like Notepad++, which already supports split view (also using Scintilla).
I would use the more specific messages of WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE
To be honest, I haven't tried your script, so I'm not sure what you're talking about. If it's about keeping the second window's position and size in sync with the main window, majkinetor's Dock() used to work quite well. Unfortunately, I can't find a copy of it.

Rather than trying to synchronize window positions, you could shove both windows into a window of your own by using DllCall("SetParent", "ptr", each_scite_hwnd, "ptr", your_gui_hwnd).
iPhilip
Posts: 822
Joined: 02 Oct 2013, 12:21

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 04:42

Here's Dock() for future reference:

Code: Select all

; Title:     Dock 
;            *Dock desired top level windows (dock clients) to any top level window (dock host)* 
;
; 
;
;			 Using dock module you can glue your or third-party windows to any top level window.
;			 Docked windows in module terminology are called Clients and the window that keeps their 
;			 position relative to itself is called Host. Once Clients are connected to the Host, this
;			 group of windows will behave like single window - moving, sizing, focusing, hiding and other
;			 OS events will be handled by the module so that the "composite window" behaves like the single window.
;
;			 Module uses system hook to monitor windows changes, so it's idle when it is not aranging windows.
; 
;---------------------------------------------------------------------------------------------------------------------------------- 
; Function:  Dock 
;            Instantiate dock of given client upon host. Multiple clients per one host are supported. 
; 
; 
; Parameters: 
; 
;            pClientId   - HWND of the Client GUI. Dock is created or updated (if already exists) for that hwnd.    
;                       If "+" is the first char of pClientId, Dock will first show the window if it is hidden (for smoother initialisation) 
;            pDockDef   - Dock definition, see bellow. To remove dock client pass "-". 
;                       If you pass empty string, client will be docked to the host according to its current position relative to the host. 
;            reset      - internal parameter, do not use. 
; 
; Globals: 
;            Dock_HostID   - Sets docking host 
;         Dock_OnHostDeath - Sets label that will be called when host dies. Afterwards, module will disable itself using Dock_Toggle(false).
;
; Dock definition:  
;			Dock definition is string containing 10 numbers that describe Client positon relative to the Host. The big number of parameters allows
;			fine tuning of Client's postion and basicly every setup is possible. Parameters are grouped in 4 classes - first 3 influence X coordinate 
;			of the client, next 3 Y coordinate, next 2 Client's width and final 2 Client's height:
;			
;> 					xhw,xw,xd,  yhh,yh,yd [, whw,wd,  hhh,hd] 
;> 						X			Y			W		H
; 
;            o The *X* coordinate of the top, left corner of the client window is computed as 
;            *HostX + xhw*HostWidth + xw*ClientWidth + xd*, with the parameters xhw, xw and xd 
; 
;            o The *Y* coordinate of the top, left corner of the client window is computed as 
;            *HostY + yhh*HostHeight + yh*ClientHeight + yd*, with the parameters yhh, yh and yd 
; 
;            o The width *W* of the client window is computed as *whw*HostWidth + wd*, with the parameters whw and wd. 
;              Skip to let the client have its own width (or set to 0,0) 
; 
;            o The height *H* of the client window is computed as *hhh*HostHeight + hd*, with the parameters hhh and hd. 
;              Skip to let the client have its own height (or set to 0,0) 
; 
; Returns: 
;            "OK" or "Err" with text describing last succesiful or failed action.
;
; Remarks:
;			You must set DetectHiddenWindows if Host is practicing hiding. Otherwise, Dock will treat Host hiding as death.
;			All clients will be hidden once host is terminated or it becomes hidden itself.
;
;			Use SetBatchLines, -1 with dock module for fluid client movement. You will experience delay in clients moving otherwise.
;			However, if CPU usage is very high, you might experience a delay in client movement anyway.
;
;			If you are using *Gui, Show* command imediately before registering client, make sure you specify *NoActivate* flag.
;
;			Currently its not supported to set Client window on top Host window. AlwaysOnTop (or TopMost) flag will not influence 
;			behavior of the module so avoid setups in which client is entirely covered by the Host.
; 
; Example: 
;>      Dock(Client1ID, "0,-1,-10, 0,0,0, 0,63, 1,0")      ;top left, host height 
;>      Dock(Client2ID, "0,0,0, 0,-1,-5, 1,0,0,30")        ;top above, host width 
; 
Dock(pClientID, pDockDef="", reset=0) {                    ;Reset is internal parameter, used by Dock_Shutdown 
   local cnt, new, cx, cy, hx, hY 
   static init=0, idDel 

    if (reset)                                             ;Used by Dock Shutdown to reset the function 
		return init := 0 

	if !init
		Dock_aClient[0] := 0

   cnt := Dock_aClient[0] 

   ;remove dock client ? 
   if (pDockDef="-") and (Dock_%pClientID%){ 

      idDel := Dock_%pClientID% 

      loop, 10 
         Dock_%pClientID%_%A_Index% := 0 
      Dock_%pClientID% := "" 
       
      ;move last one to the place of the deleted one 
      Dock_aClient[%idDel%] := Dock_aClient[%cnt%], Dock_aClient[%cnt%] := "", Dock_aClient[0]-- 
      return "OK - Remove" 
   } 

   if *&pClientID = 43         ; 43 = "+" 
      DllCall("ShowWindow", "uint", pClientID := SubStr(pClientID, 2), "int", 4)  ;using this isntead WinShow cuz of A_WinDelay 


   if pDockDef = 
   { 
      WinGetPos hX, hY,,, ahk_id %Dock_HostID% 
      WinGetPos cX, cY,,, ahk_id %pClientID% 
      pDockDef := "0,0," cX - hX ",  0,0," cY - hY 
   } 

   ;add new dock client if it not exists, or update its dock settings if it exists 
   pDockDef .= ",0,0,0,0"      ;if user skiped last 4 params, add them here. If user gave 10 params, bottom loop will exit anyway. 
   loop, parse, pDockDef, `,,%A_Space%%A_Tab% 
         if A_Index > 10       
            break 
         else Dock_%pClientID%_%A_Index% := A_LoopField 


	if !Dock_%pClientID% {
		Dock_%pClientID%   := ++cnt, 
		Dock_aClient[%cnt%] := pClientId 
		Dock_aClient[0]++ 
	}

   ;start the dock if its not already started
   If !init { 
	
      init++, Dock_hookProcAdr := RegisterCallback("Dock_HookProc")
      return Dock_Toggle(true)	 
   } 

   Dock_Update()
   return "OK" 
}       


;----------------------------------------------------------------------------------------------------- 
;Function:  Dock_Shutdown 
;			Uninitialize dock module. This will clear all clients and internal data and unregister hooks. 
;			Dock_OnHostDeath, Dock_HostId are kept on user values. 
; 
Dock_Shutdown() { 
   local cID 

   Dock_Toggle(false) 
   DllCall("GlobalFree", "UInt", Dock_hookProcAdr), Dock_hookProcAdr := "" 
   Dock(0,0,1)         ;reset dock function 

   ;erase clients 
   loop, % Dock_aClient[0] 
   { 
      cId := Dock_aClient[%A_Index%], Dock_aClient[%A_Index%] := "" 
      Dock_%cID% := "" 
      loop, 10 
         Dock_%cID%_%A_Index% := "" 
   }
}    

;----------------------------------------------------------------------------------------------------- 
;Function: Dock_Toggle 
;          Toggles the dock module ON or OFF.
; 
;Parameters: 
;         enable - Set to true to set the dock ON, set to FALSE to turn it OFF. Skip to toggle. 
; 
;Remarks: 
;         Use Dock_Toggle(false) to suspend the dock module (to unregister hook), leaving its internal data in place. 
;         This is different from Dock_Shutdown as latest removes module completely from memory and 
;         unregisters its clients. 
;          
;         You can also use this function to temporary disable module when you don't want dock update routine to interrupt your time critical sections. 
;
Dock_Toggle( enable="" ) { 
   global 

   if Dock_hookProcAdr = 
      return "ERR - Dock must be loaded." 

   if enable = 
      enable := !Dock_hHook1 
   else if (enable && Dock_hHook1)
		return	"ERR - Dock already enabled"

   if !enable 
      API_UnhookWinEvent(Dock_hHook1), API_UnhookWinEvent(Dock_hHook2), API_UnhookWinEvent(Dock_hHook3), Dock_hHook3 := Dock_hHook1 := Dock_hHook2 := "" 
   else  { 
      Dock_hHook1 := API_SetWinEventHook(3,3,0,Dock_hookProcAdr,0,0,0)				; EVENT_SYSTEM_FOREGROUND 
      Dock_hHook2 := API_SetWinEventHook(0x800B,0x800B,0,Dock_hookProcAdr,0,0,0)	; EVENT_OBJECT_LOCATIONCHANGE 
	  Dock_hHook3 := API_SetWinEventHook(0x8002,0x8003,0,Dock_hookProcAdr,0,0,0)	; EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE

      if !(Dock_hHook1 && Dock_hHook2 && Dock_hHook3) {	   ;some of them failed, unregister everything
         API_UnhookWinEvent(Dock_hHook1), API_UnhookWinEvent(Dock_hHook2), API_UnhookWinEvent(Dock_hHook3) 
         return "ERR - Hook failed" 
      } 

	 Dock_Update() 
   } 
} 

;==================================== INTERNAL ====================================================== 
Dock_Update() { 
   local hX, hY, hW, hh, W, H, X, Y, cx, cy, cw, ch, fid, wd, cid 
   static gid=0   ;fid & gid are function id and global id. I use them to see if the function interupted itself. 

   wd := A_WinDelay 
   SetWinDelay, -1 
   fid := gid += 1 
   WinGetPos hX, hY, hW, hH, ahk_id %Dock_HostID% 
;   OutputDebug %hX% %hY% %hW% %hH%	 %event%

   ;xhw,xw,xd,  yhh,yh,yd,  whw,wd,  hhh,hd 
   loop, % Dock_aClient[0] 
   { 
      cId := Dock_aClient[%A_Index%] 
      WinGetPos cX, cY, cW, cH, ahk_id %cID% 
      W := Dock_%cId%_7*hW + Dock_%cId%_8,  H := Dock_%cId%_9*hH + Dock_%cId%_10 
      X := hX + Dock_%cId%_1*hW + Dock_%cId%_2* (W ? W : cW) + Dock_%cId%_3
      Y := hY + Dock_%cId%_4*hH + Dock_%cId%_5* (H ? H : cH) + Dock_%cId%_6 

	  if (fid != gid)   {				;some newer instance of the function was running, so just return (function was interupted by itself). Without this, older instance will continue with old host window position and clients will jump to older location. This is not so visible with WinMove as it is very fast, but SetWindowPos shows this in full light. 
         SetWinDelay, %wd% 
		 break
      } 

      if (W+H)				
           WinMove ahk_id %cId%,,X,Y, W ? W : "" ,H ? H : "" 
      else WinMove ahk_id %cId%,,X,Y 
  } 
	SetTimer, Dock_SetZOrder, -20		;set z-order in another thread (protects also from spaming z-order changes when host is rapidly moved).
	SetWinDelay, %wd% 
} 


Dock_SetZOrder: 
   loop, % Dock_aClient[0] 
      DllCall("SetWindowPos", "uint", Dock_aClient[%A_Index%], "uint", Dock_HostID, "uint", 0, "uint", 0, "uint", 0, "uint", 0, "uint", 19) ;SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE

;   OutputDebug setzorder
return 

Dock_SetZOrder_OnClientFocus:
   loop, % Dock_aClient[0] 
      DllCall("SetWindowPos", "uint", Dock_aClient[%A_Index%], "uint", A_Client, "uint", 0, "uint", 0, "uint", 0, "uint", 0, "uint", 19) ;SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE

  DllCall("SetWindowPos", "uint", Dock_HostID, "uint", A_Client, "uint", 0, "uint", 0, "uint", 0, "uint", 0, "uint", 19) ;SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
;  OutputDebug onclientfocus
return 

;-----------------------------------------------------------------------------------------
; Events :
;			3	  - Host is set to foreground
;			32779 - Location change
;			32770 - Show
;			32771 - Hide (also called on exit)
;
Dock_HookProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime ) { 
   global 

	if (event = 3) 
		loop, % Dock_aClient[0]
 		  if (hwnd = Dock_aClient[%A_Index%])
		  {
			   A_Client := hwnd
			   SetTimer, Dock_SetZOrder_OnClientFocus, -20 
			   return
		  }			

	If (hwnd != Dock_HostID){				
      if !WinExist("ahk_id " Dock_HostID) && IsLabel(Dock_OnHostDeath)
	  {
 		 Dock_Toggle(false)
		 gosub %Dock_OnHostDeath% 
	  }
	  return 
	} 

	if (idChild or idObject)
		return
	

	if event in 32770,32771
	{
	   event := (event - 32771) * -5
	   loop, % Dock_aClient[0] 
			DllCall("ShowWindow", "uint", Dock_aClient[%A_Index%], "uint",  event)
	}

	Dock_Update() 
} 


API_SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) { 
   DllCall("CoInitialize", "uint", 0) 
   return DllCall("SetWinEventHook", "uint", eventMin, "uint", eventMax, "uint", hmodWinEventProc, "uint", lpfnWinEventProc, "uint", idProcess, "uint", idThread, "uint", dwFlags) 
} 

API_UnhookWinEvent( hWinEventHook ) { 
   return DllCall("UnhookWinEvent", "uint", hWinEventHook) 
} 

;--------------------------------------------------------------------------------------------------------------------- 
; Group: Presets
;		 This section contains some common docking setups. You can just copy/paste dock definition strings in your script.
;
;		0,-1,0,   0,0,0					- top left, own size
;		0,-1,10,  0,0,0					- top left, own size, 10px padding 
;		0,-1,0,   0,0,0,   0,0,   1,0	- top left, use host's height, keep own width
;		0,-1,20,  0,0,0,   0,50,  1,0	- top left, use host's height, set width to 50 and padding to 20px
;		0,-1,0,   .5,-.5,0				- middle left, keep own size
;				
;		0,-1,0,   1,-1,0,  0,20,  0,20	- bottom left, fixed width & height to 20px
;		0,-1,0,   1,-1,0,  0,0,  .5,0   - bottom left, keep height half of the Host's height, keep own width
;		1,-1,0,   1,0,0,   .25,0  .25,0	- bottom right, width and height 1/5 of the Host
;
;		0,0,0,	  1,0,0,    1,0,  0,100 - below the host, use host's width, height = 100
;		0,0,0,	  0,-1,-5,  1,0   	    - above the host, use host's width, keep own height, 5px padding
;		.5,-.5,0, 0,-1,0,   0,200, 0,30	- center above the host, width=200, height=30
;		.5,-.5,0, 1,0,0,   0.3,0, 0,30	- center bellow the host, use 1/3 Host's width, height=30
;
;		1,0,0,   0,0,0					- top right, own size
;		1,0,0,   0,0,0,     0,40,  1,0  - top right, use host's height, width = 40
;       1,0,0,	 .5,-.5,0				- middle right, keep own size

;--------------------------------------------------------------------------------------------------------------------- 
; Group: About 
;      o Ver 1.0 by majkinetor. See http://www.autohotkey.com/forum/topic19400.html 
;	   o Thank You's: Laszlo, JGR, Joy2World, bmcclure 
;      o Licenced under Creative Commons Attribution-Noncommercial <http://creativecommons.org/licenses/by-nc/3.0/>.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 10:59

lexikos wrote:Scintilla (the edit control used by SciTE) supports multiple controls editing the same document. A simple proof of concept shows this in action, using SciTE's output pane...

There might be ways to disable output to the output pane (or perhaps just disable the mirroring before running a command). You would also need to set the output pane's lexer appropriately, and possibly do other things. If you wanted to use a separate Scintilla control, it would need to be created by SciTE itself, or a Lua script; but I'm not sure whether Lua has access to the necessary functions.
Thanks for all the great ideas. This one is pretty cool and looks promising. I would want it to have a separate Scintilla control so it could use Find, TillGoto, etc. I don't know how to do those things that you mentioned would have to be done, but I'm willing to look into it. If nothing else, I would probably get quite an education in trying to implement it. :D
lexikos wrote:Of course, one could instead add the features of SciTE4AutoHotkey to a more feature-complete editor like Notepad++, which already supports split view (also using Scintilla).
I really like this idea, but it sounds even more ambitious than the first one. I don't yet have the knowledge to pull this off. My first searches on the subject don't reveal much on how someone has implemented something like this on Notepad++, so I'd be flying kind of blind. I might go down this path a bit and see how big the obstacles are.
lexikos wrote:
I would use the more specific messages of WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE
To be honest, I haven't tried your script, so I'm not sure what you're talking about. If it's about keeping the second window's position and size in sync with the main window, majkinetor's Dock() used to work quite well. Unfortunately, I can't find a copy of it.
Yes, it's about keeping them in sync. Dock() sounds like it might be an improvement on how I've done it. I'll definitely try implementing it. (Thanks iPhilip for posting the code.)
lexikos wrote:Rather than trying to synchronize window positions, you could shove both windows into a window of your own by using DllCall("SetParent", "ptr", each_scite_hwnd, "ptr", your_gui_hwnd).
Interesting idea. This would definitely get them to move together without the script needing to intervene, but for resizing, the script would still need to take over and resize both windows within it, so there would still be the lag that was mentioned. And since they would be child windows, the user couldn't move the split by resizing one of the windows (as is how it's done using my script, which then resizes the other window automatically so the user only moves one border), so the script would have to somehow recognize that they are trying to resize with a drag operation on the border between the windows and react to it. But I might play around with this too.

I'll start with the Dock() approach, hopefully get that working, then pursue one or more of the others. Thanks again!
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 11:34

I just replaced the code in the first post with a significant improvement (although not yet the ideas that were discussed in the last few posts).

This update corrects an issue where the menu would flicker if it overlapped the other window (the File menu can be quite long and overlap the other pane, depending on the size of each window). That resulted from the method that was used to keep both windows on top when either was active, which was to move the other one to the top briefly, which caused it to cover the overlapping menu briefly, resulting in a flicker. Now the other window is moved just behind the active one in the z-order, so it is still on top of other windows, but it doesn't cover the overlapping menu from the active window.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 21:27

My first searches on the subject don't reveal much on how someone has implemented something like this on Notepad++
What's "something like this"? As I said, Notepad++ already supports split view. Just right click a tab and click "Clone to other view". I mainly use SciTE4AutoHotkey because the AutoHotkey debugger and syntax highlighting support is a bit better, but also for the platform selector (on the toolbar). What I meant was that one could add features like the platform selector to Notepad++ via plugins or AutoHotkey script.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 21:38

Yes, I use "Clone to other view" all the time. That's the feature I'm trying to emulate here. I mean I wasn't able to find how to implement all the other AHK-specific capabilities of SciTE4AutoHotkey into Notepad++. That would be quite an undertaking for me. I realize there is syntax highlighting for AHK and there is a debugger plugin in Notepad++ (both of which I use), but there's a lot more to be implemented, especially IntelliSense or CallTips or whatever it's called. TillaGoto would be another nice feature to have.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 22:39

Ah, I didn't even consider calltips, because they never seem to work right in SciTE when I might need them (which is rare). For Notepad++, looks like you just need to edit an XML file. It would just be a matter of taking one thing at a time. There's not all that much, and several of the SciTE4AutoHotkey features are implemented with AutoHotkey, mostly separate from SciTE anyway.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

28 Jan 2015, 23:39

Yes, I would imagine you don't need nearly as much reminding on how the commands and their parameters are formatted as I do. :) When I use Notepad++, I bring up the command page from the help document very often using Rajat's context-sensitive help script, which I like a lot, especially as I modified it to return focus back to the editor and move the cursor to the end of the current line.

I think I'll give editing that XML file a shot, as I think it would be very useful. Thanks for the info. I also noticed that if I turn on Auto-Completion, it's pretty much useless, so there must be a similar file I would need to edit. I was surprised it contained any AHK commands at all. Maybe they were just the result of usage like a smart phone's auto-complete, but then I would have thought there would be more commands in it.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 00:19

I was surprised it contained any AHK commands at all.
It might not. Notepad++ auto-completes words that it detects in the current document.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 00:31

That explains the limited number of commands I found. It was just what happened to be in the document I was editing at the time.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 14:37

iPhilip wrote:Here's Dock() for future reference: ...
FYI - That version of Dock() does not work with AHK_L. Need to use this version found near the end of that thread:
http://www.autohotkey.com/board/topic/1 ... /?p=547469

Dock() is a nice script, but it won't do everything I need for this application. It does keep the window docked to where I want it if you're just dragging the main window around, or resizing the main window from the top only. However, if you drag the border between the two windows (i.e., the split), the docked window stays at it's current size and just moves up or down, which is to be expected. My script would still have to resize the lower window to keep the overall size the same (giving the effect of moving the split). Doing that would require re-computing the necessary sizes as the window's size changes and updating Dock() with the new parameters. That would have the same lag as in my script without Dock(). Plus, if you grab the top of the lower window rather than the bottom of the top window, they separate, so again, my script would have to accommodate by resizing the top window accordingly and also update Dock(), so it would again appear just as it does already.

Similarly, resizing the lower window doesn't cause the upper window to change accordingly (i.e., sync their width), so again my script would have to make updates.

Bottom line is that for the most part, my script would have few benefits from incorporating Dock(), so I'm going to leave it as it as far as this point goes. In my opinion, the lag in the windows syncing each other is minimal, anyway. It would be just for aesthetic reasons only (and that benefit would only when moving the main window, not when resizing) -- there is no real practical benefit.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 18:03

Added feature: Support for TillaGoto for the second pane. Additional windows in SciTE4AutoHotkey don't have the TillaGoto controls, but this script adds functionality that allows for the second pane created by this script to make use of TillaGoto.
  • Both panes must be showing the same file.
  • If the second pane is active, press F12 once to activate the main window, and press it again to select TillaGoto. If the main window is already active, just press F12 once as usual.
  • Type the beginning of the function/label/hotkey (FLH) until the desired item is the first (or only) displayed item
  • Press F11, and the the script will automatically perform a "Find" and move to the desired FLH in the second pane
The script in the first post has been updated to include this feature.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 21:26

Rather than using Dock() as is, you could employ the same method it does for detecting window resizing. I don't think there would be noticeable lag.
User avatar
boiler
Posts: 16957
Joined: 21 Dec 2014, 02:44

Re: Second Edit Pane for SciTE4AutoHotkey

29 Jan 2015, 21:39

Well, if you think the lag would be less, I'll look into it. I was thinking that I will still have to do conventional resizes and moves, but perhaps the WinGetPos and subsequent calculations take long enough that reducing the time they take will be enough to significantly speed it up.

I did play with the SetTimer period and found that the amount of lag wasn't really a function of the period length. I have it at 50ms, but I've tried as low as 10ms without a noticeable reduction in lag, which would seem to confirm what you're saying that it would get better by reducing the time it takes to actually do the stuff.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 141 guests